Skip to content

fix(auth): preserve explicitly granted pairing scopes - #9785

Open
juliusmarminge wants to merge 4 commits into
mainfrom
t3code/auth-pairing-scopes
Open

fix(auth): preserve explicitly granted pairing scopes#9785
juliusmarminge wants to merge 4 commits into
mainfrom
t3code/auth-pairing-scopes

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 4, 2026

Copy link
Copy Markdown
Member

Clients request the full default scope set when pairing, which rejects deliberately limited grants. A rejected exchange can consume the pairing link, and an already-authenticated browser skips replacement pairing links.

Use the scopes granted by the pairing token across web, desktop, and mobile. Validate requested scopes before consuming a link, add repeatable --scope options to the pairing and session commands, and let an explicit browser pairing link replace the current grant. Successful browser pairing reloads the app to refresh its WebSocket credentials; a rejected token preserves the existing session and shows the error.

Existing clients retain their current scopes until they pair again with a fresh grant. Reconnecting does not add permissions.

Tests added cover selected CLI scopes and persistence, rejected exchanges preserving a usable link, clients retaining custom grants, and browser replacement with cached authentication, query/hash tokens, and invalid-token recovery.

Model: GPT-6. Harness: Codex.


Note

High Risk
Changes authentication scope validation, pairing-link consumption, and how sessions are issued across server, CLI, and all clients—security-critical behavior with nuanced edge cases (browser re-pair, desktop bootstrap narrowing).

Overview
Fixes pairing and token exchange so clients inherit the scopes minted on the link instead of always requesting the full default set, which could reject limited grants and (previously) burn one-time tokens.

Server: PairingGrantStore.consume and pairing-link SQL consumption now accept optional requestedScopes, return BootstrapCredentialScopeNotGrantedError when a requested scope exceeds the grant, and do not consume the link on that failure. Token exchange forwards requested scopes into consume and maps that error to ServerAuthScopeNotGrantedError.

CLI: Repeatable --scope on t3 pair, t3 auth pairing create, and t3 auth session issue (defaults unchanged when omitted); invalid scopes fail at parse time.

Clients: Web, mobile, and client-runtime stop attaching fixed client scopes to presentation and OAuth exchange—omitting scope means “use the grant.”

Browser: Visiting /pair with a token forces the pairing flow even if already authenticated; success reloads / to refresh WebSocket credentials; a bad replacement token keeps the existing session and stays on the pairing UI.

Docs cover choosing scopes and replacing grants via a new link.

Reviewed by Cursor Bugbot for commit fa5d32f. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve explicitly granted pairing scopes and add CLI --scope flags

  • Moves scope validation into PairingGrantStore.consume so requesting ungranted scopes fails and leaves the credential available for later use.
  • Adds repeated --scope options to the t3 pair, auth pairing create, and auth session issue CLI commands, defaulting to standard client or administrative scopes.
  • Removes AuthStandardClientScopes from the ClientPresentation contract across mobile, web, and client-runtime so bootstrap grants dictate the authorized scopes.
  • Adds explicit pairing state to the web primary auth flow to force the pairing surface when opening /pair on an already authenticated browser.
  • Behavioral Change: The ClientPresentation service contract no longer includes a scopes field, breaking out-of-tree implementations that rely on it. Successful browser re-pairing now performs a full application reload via window.location.replace instead of a client-side router transition.

Macroscope summarized fa5d32f.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 4, 2026
@juliusmarminge juliusmarminge changed the title t3code/auth pairing scopes fix(auth): preserve explicitly granted pairing scopes Sep 4, 2026
@juliusmarminge
juliusmarminge marked this pull request as ready for review September 4, 2026 21:15
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.6 KiB 13.5 KiB −43 B (−0.3%) 15.1 KiB
Codex Thread snapshot wire 7.0 KiB 7.0 KiB −3 B (−0.0%) 7.3 KiB
Codex Live turn WebSocket wire 6.6 KiB 6.5 KiB −40 B (−0.6%) 7.8 KiB
Codex Live turn WebSocket decoded 57.1 KiB 57.0 KiB −44 B (−0.1%) 66.4 KiB
Codex Live turn messages 10 9 −1 (−10.0%) 21
Claude Total thread wire 13.6 KiB 13.5 KiB −39 B (−0.3%) 15.1 KiB
Claude Thread snapshot wire 7.0 KiB 7.0 KiB +7 B (+0.1%) 7.3 KiB
Claude Live turn WebSocket wire 6.6 KiB 6.5 KiB −46 B (−0.7%) 7.8 KiB
Claude Live turn WebSocket decoded 57.9 KiB 57.8 KiB −88 B (−0.1%) 66.4 KiB
Claude Live turn messages 10 8 −2 (−20.0%) 21

Baseline: b906ce2 · PR result: fa5d32f · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR changes production authentication and authorization behavior across server, browser, mobile, and shared client-runtime flows, including scope issuance and grant replacement. It also adds static-analysis suppression directives, so the sensitive runtime surface and review policy require human review.

You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge
juliusmarminge force-pushed the t3code/auth-pairing-scopes branch from 6c5c74d to d52b9a1 Compare September 4, 2026 21:36
@juliusmarminge
juliusmarminge force-pushed the t3code/auth-pairing-scopes branch from d52b9a1 to fa5d32f Compare September 4, 2026 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant