Repository navigation
Conversation
Released clients such as iOS 2.0.0 request the pre-split scope names at token exchange. The exchange kept only those names, so new sessions lost filesystem:read, providers:manage, source-control:write and the other permissions split out of them, even when the pairing grant included them. Expand a request made only of pre-split scopes by the permissions split out of each requested parent, then intersect with the grant as before. Granular requests and requests without a scope are unchanged, and stored credentials are still never widened. Fixes pingdotgg#16804 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This is a focused compatibility fix that changes which permissions are issued during production pairing-token exchange, while retaining the pairing grant as the cap. Because it modifies authentication code and affects authorization scope issuance, human review is required. You can add or adjust custom eligibility rules. Learn more. |
This branch has not been deployed
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
Released clients such as iOS 2.0.0 (TestFlight build 110) still request the pre-split scope names at token exchange (
orchestration:read orchestration:operate terminal:operate relay:read, withreview:writedropped as retired). Token exchange keeps only requested scopes that the grant holds, and nothing translates the old names. So every new session from those clients is stored with four scopes, even when the pairing link granted all of them. Folder browsing and host media fail withmissing required scope: filesystem:read, cloning withsource-control:write, provider sign-in withproviders:manage, remote updates withenvironment:maintain, and Usage withdiagnostics:read. Re-pairing does not help.Reproduction on a macOS host running
0.0.46-nightly.20261007.2787, over Tailscale:t3 pair --tailscale. The stored link holds the full standard grant.auth_sessionsrow holds only["orchestration:read","orchestration:operate","terminal:operate","relay:read"].Change
Token exchange now expands a request made only of pre-split scopes by every permission split out of a requested parent, using the existing
legacyParentsmap. It then intersects the result with the bootstrap grant as before. This follows the compatibility rule proposed in #16804, extended to every split permission per the maintainer follow-up aboutfilesystem:readand the report aboutdiagnostics:read.orchestration:operatewithoutproviders:managedoes not gain it.expandLegacyScopeRequestlives next tolegacyParentsinpackages/contracts/src/auth.ts, and the comment on that map now says servers read old requests with it. One sentence indocs/internals/environment-auth.mddescribing token exchange is updated.Scope and approval
Fixes #16804, which maintainers have triaged and confirmed as a bug, with this server-side compatibility rule proposed as the fix (maintainer comment). #17256 and #16856 were closed as duplicates of it. This PR covers only proposal item 1, the token-exchange rule. The mobile "missing permission" state (item 3) and the T3 Connect session refresh in #17308 are separate problems.
Verification
vp test run apps/server/src/auth/EnvironmentAuth.test.ts packages/contracts/src/auth.test.ts apps/server/src/auth/http.test.ts apps/server/src/auth/PairingGrantStore.test.ts: 64 passed.EnvironmentAuth.test.ts:AuthStandardClientScopes, checked through bearer authentication.orchestration:read,orchestration:operateandfilesystem:readyields exactly those three, so the grant still caps the expansion.2 failed | 18 passed).orchestration:readalone, which is now a pre-split request. They requestfilesystem:readinstead, so they still cover narrowing by a granular request. Their rejection cases are unchanged:["access:write"],["review:write"]and[]still fail withServerAuthScopeNotGrantedError.McpOAuth,CliTokenManager,publicConfig,RpcAuthorizationandSessionStore(74 passed).tsc --noEmitforapps/serverandpackages/contractsshows no errors, andvp lintandvp fmt --checkare clean on the changed files.Not checked: I did not build this server and pair a real iOS 2.0.0 client against it. Instead, I confirmed the client's request on a live host: a stored link with the full grant was consumed into a session holding exactly the four legacy scopes. As a stopgap on that host, I set the session's scopes in
auth_sessionsto the full standard list without a restart, and the phone's WebSocket requests then passed thefilesystem:readcheck. The new test reproduces that request.Done with Claude Code (Claude Opus 5.5) running in T3 Code.
🤖 Generated with Claude Code