Repository navigation
fix(ai): mint evidence tokens with metadata:read on CopilotKit only - #289
Merged
Merged
Conversation
The support agent asked GitHub for an installation token narrowed to contents:read. The Outpost App does not hold Contents, so GitHub refused every exchange with HTTP 422 and every read_source/read_release call reported auth_unavailable. Both allowlisted evidence repositories are public, and GitHub serves commits, contents and releases of a public repository to any token. Ask for metadata:read, which the App already holds, and narrow the token to the CopilotKit repository. ag-ui-protocol/ag-ui stays readable as a public repository. The App is not granted Contents on purpose.
jpr5
marked this pull request as ready for review
October 28, 2026 17:49
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The support agent's GitHub evidence reads (
read_source,read_release) fail in production.github-evidence-auth.tsasks GitHub for an installation token narrowed topermissions: { contents: 'read' }. The Outpost App (installation 146859931) holds only Issues: write, Discussions: write and Metadata: read. GitHub refuses the token request with HTTP 422 ("The permissions requested are not granted to this installation."). The worker logs[SupportAgent] GitHub evidence authentication unavailable: { code: 'token_exchange_failed' }21 times since Oct 23, and the bot replies without source evidence.Why we did not grant Contents
The App is installed with
repository_selection: allon 197 org repositories, 91 of them private. Contents: Read would apply to every token the App mints, not only this code path. The bot reads untrusted issue text and posts in public. The evidence allowlist (support-agent.ts) is two public repositories,CopilotKit/CopilotKitandag-ui-protocol/ag-ui. GitHub serves commits, contents and releases of a public repository to any token, so the feature does not need Contents.Fix
permissions: { metadata: 'read' }(the App already holds it) instead ofcontents: 'read'.CopilotKitrepository (repositoryNames). A leaked token then cannot read even the metadata of other org repositories.ag-ui-protocol/ag-uiis in another org and cannot be named, but it stays readable because it is public (proved below).Red-green proof (real App credentials, real GitHub API)
Harness: the real
SupportAgentwith aimock as the model, scripted to callread_source(README.md @ main) andread_release(latest release) on both allowlisted repositories. Everything from env credentials to token minting to the GitHub fetch is production code. A fetch observer prints only method, path and status. No key or token was printed or written to disk. The harness was not committed.RED (main @ 52e6859), 10:29 AM PDT:
GREEN (this branch), 10:30 AM PDT:
Scope check (same App, token request shapes probed directly): a
metadata:read+repositoryNames: ['CopilotKit']token reads all six public evidence URLs above with 200, and gets 404 onCopilotKit/internal-skills/contents/README.md(private). Without the repository narrowing the same private read gets 403.Local checks
prettier --checkandeslinton the changed files: cleantsc --project ai/tsconfig.json --noEmit: cleanvitest run ai/: 3807/3807 pass. (On local Node v26.8.1,classifier-backtracking.test.ts"starts the probe child cleanly" fails only because Node prints a DEP0205 deprecation warning on stderr. It passes withNODE_OPTIONS=--no-deprecation. Unrelated to this change.)Follow-up (not in this PR)
docs/deployment.md(GitHub App Setup) anddocs/support-agent.mdstill tell operators to grant Contents: Read-only for evidence reads. That is now wrong and contrary to this decision; they need a separate docs update.No App settings or Railway configuration were changed.