Repository navigation
feat(ai, ai-harness, ai-mcp): one redaction sink, the final tool result in the log, secret answers by reference, and single-flight OAuth refresh - #1815
Conversation
…and one scrubSecrets
…ts, plugin state, notes, and the model context
…and errors and step results leave the session scrubbed
…he credential store as a one-time reference
…anscript, the events, the log, or the model input
…h compare-and-set to the scope it came from, and keeps the client registration
… the final tool result, OAuth refresh, and the CredentialStore compare-and-set pair
🦋 Changeset detectedLatest commit: a7cc5c1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 53 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
View your CI Pipeline Execution ↗ for commit a7cc5c1
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-cloudflare
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-compaction
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-harness
@tanstack/ai-harness-cli
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-e2b
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-ollaya
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-reactor
@tanstack/ai-remix
@tanstack/ai-sandbox
@tanstack/ai-sandbox-blaxel
@tanstack/ai-sandbox-boxd
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-e2b
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-railway
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-upstash-box
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-typesafe
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/ai-worldlabs
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
Coverage✅ Coverage held across 68 compared package(s). Each package is measured twice in this job — on this PR and on its merge-base with
|
A secret that the harness hands out never lands in the log, the event stream, or the model input. The log keeps the tool result that the model really saw. A secret answer sent to another server goes through the credential store, not the log. OAuth refresh runs once per host and saves with compare-and-set. This is PR 6 of the harness redesign stack for #1755. It targets #1814 (
feat/harness-log-session).🎯 Changes
ctx.context.run.credentialsandkeys.[redacted]in log records, feed events, plugin state, notes, the model context, tool results, the error frames of HTTP, the socket, and the stdio worker, and durable step results.scrubSecrets. The core one in@tanstack/ai/byokis the only body. The harness re-exports it.onAfterToolCallhook. A replacement wins, also on an error.secret: truequestion that reaches a host that does not own the log is saved in the app'scredentialsstore as a one-time reference. Only the reference goes into the input lane.credentials.listhides theharness:answer:ids.credentialsstore, such an answer is refused withsecret_answer_needs_credentials.[tenantId, userId, connectorId]. A caller's abort rejects only that caller.setIfwhen the store has it, and on a conflict it uses the winner's token. A tenant token stays in the tenant scope.previous.clientis kept.CredentialsAccess.refresh(id, update, { signal })does this for connectors. MCP connectors save the SDK's refreshed tokens through it, andinvalidateCredentialsdeletes only the token it saw.CredentialStore. It has an optionalgetVersioned?andsetIf?pair, the same shape asMetadataStore.memoryCredentialStore()implements both. The newreadCredentialEntry(store, scope, id)says which scope matched, and the revision.Docs: new sections in
auth,durable-sessions, andadvanced/server-keys. Updates indurable-tools,session-log,plugins,provider-keys,mcp,shared-threads, andapi/ai. Changesets for@tanstack/ai,@tanstack/ai-harness, and@tanstack/ai-mcp.Decisions made while building:
info.ok ? info.result : (info.result ?? { error }). A successful tool that returnsundefinedis not stored as an error.host.close()aborts it.mcp.mdsay so.Known limits: a secret split across two streaming deltas is not caught in those live events (the stored transcript is). A secret that is JSON-escaped twice is not caught. A secret answer reference that nobody reads stays in the store until PR 7 adds wait expiry.
✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Testing
Commands run:
ai,ai-persistence,ai-harness, andai-mcp.test:typesof those four plusai-acp,ai-harness-cli,ai-code-mode,ai-skills, andai-sandbox. All pass.--maxWorkers=2. Examples:byok,redaction,resume,durable-tools,bound-output,input-lane,oauth-edges,auth, and the ai-mcpconnector-edgesandconnector. All pass.test:oxlintofai-harness,test:sherif,pnpm test:docs,kiira checkon the changed pages, andoxfmt --checkon every changed file.Not run locally: the full suites, knip, E2E (including the new
harness-secret-answer.spec.ts), and coverage. CI runs them.Manual test:
pnpm --dir packages/ai-harness exec vitest run tests/redaction.test.ts tests/input-lane.test.ts tests/oauth-edges.test.ts.tests/redaction.test.ts: a tool echoes a saved key in its result and its error. The key is[redacted]in the log, the feed, plugin state, and the next model call.refresh racesintests/oauth-edges.test.ts: two hosts refresh at once, one save wins, and both use the winner's token.How this PR makes testing easy: the new
tests/redaction.test.tsand therefresh racesanda secret answerblocks pin each part.testing/e2e/tests/harness-secret-answer.spec.tsanswers a secret question on a second server and checks that the secret is nowhere.Risk / rollback
Medium. Every log record and event now passes the redactor, and the OAuth refresh path changed. The redactor skips all work when the session has no secret, and it returns the same object when nothing matches. The harness is not released yet. To undo, revert this PR.
Public API change
Before
After