Skip to content

[Bug]: iOS Provider accounts fails with missing providers:manage on fresh T3 Connect tokens #16804

Description

@amoscicki

Observation

On T3 Code Nightly 0.0.46-nightly.20261007.2761 (Windows x64 environment), the iOS client 2.0.0 opens Provider accounts but both Cursor provider panels fail with:

The authenticated token is missing required scope: providers:manage.

The server trace independently records provider.auth.subscribe failing with:

EnvironmentAuthorizationError: The authenticated token is missing required scope: providers:manage.

A freshly issued mobile DPoP session at 2026-10-07T11:02:46.233Z has exactly:

  • orchestration:read
  • orchestration:operate
  • terminal:operate
  • relay:read

It does not have providers:manage. Several fresh mobile sessions show the same restricted scope set, so this is not just an expired token. This report concerns mobile T3 authorization, independently of the provider's own credentials.

Why it matters

The authenticated mobile client exposes account management UI, but subscribing to its provider auth state fails before any provider login can begin. User cannot reconnect a provider through the displayed account panel.

Where to investigate

Verified against the installed server bundle, whose source regions identify:

  • apps/server/src/auth/RpcAuthorization.ts: RPC_REQUIRED_SCOPES, rpcAuthorizationError, requiredScopesForRpcCall require providers:manage for provider auth RPCs, including subscribe.
  • packages/contracts/src/auth.ts: AuthStandardClientScopes includes providers:manage; authScopeRequiredResponse supplies compatibility response fields.
  • apps/server/src/auth/EnvironmentAuth.ts: token exchange intersects requested scopes with granted scopes.
  • apps/server/src/cloud/CloudLink.ts: managed-connect pairing creation uses AuthStandardClientScopes.
  • The iOS/managed-connect token-exchange request should be checked for an outdated requested scope set. The exact component omitting the permission has not been established.

Expected state and acceptance

  • A client authorized for provider management requests and receives providers:manage, and Provider accounts can subscribe/start the supported login flow.
  • A deliberately restricted client remains restricted, but UI explicitly reflects the missing permission instead of showing a broken sign-in panel.
  • No blanket permission widening or disabling server scope checks.
  • Cover old/narrow mobile scope requests and full permitted scope requests across token exchange and provider auth subscription.

Evidence (2026-10-07)

Local sanitized report: P:\codex-memory-palace\palace\projects\t3-multinode-env\provider-diagnosis-2026-10-07.json; companion diagnosis .md.

Server evidence: ~/.t3/userdata/logs/server.trace.ndjson.1, span ws.rpc.provider.auth.subscribe; metadata-only read of auth_sessions in ~/.t3/userdata/statev2.sqlite.

No credential values, tokens, account identifiers, IP addresses, or secret store contents are included.

Activity

  1. juliusmarminge commented on Oct 7, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Thanks for the detailed report. I can confirm this is a bug. Server permissions changed, and released mobile clients weren't carried over.

    Root cause

    • feat(auth): separate environment administration permissions #9786 (merged Oct 6) moved provider sign-in from orchestration:operate to the new providers:manage scope. provider.auth.subscribe, start, complete, respond, cancel and logout now all require it (apps/server/src/auth/RpcAuthorization.ts:62-72).
    • The server side of managed connect is fine. CloudLink mints the pairing grant with AuthStandardClientScopes (apps/server/src/cloud/CloudLink.ts:1620), and that list includes providers:manage (packages/contracts/src/auth.ts:205-219).
    • Token exchange then keeps only the scopes that are both requested and granted (apps/server/src/auth/EnvironmentAuth.ts:901-904). The session you saw has exactly orchestration:read, orchestration:operate, terminal:operate and relay:read. That is the overlap between the standard grant and the frozen pre-granular wire vocabulary (legacyScopes, packages/contracts/src/auth.ts:130-140). So the iOS 2.0.0 build is asking for the old scope list, and nothing on the server translates it into the new granular scopes. Current main mobile/client-runtime code sends no scope (packages/client-runtime/src/authorization/service.ts:340-345) and would receive the full grant.
    • The mobile UI checks providers:manage (apps/mobile/src/features/settings/SettingsEnvironmentDetailRouteScreen.tsx:84), but a client built before that check still shows the panel. That's why you get a broken sign-in panel instead of a hidden or disabled one.

    Proposed fix (no blanket widening)

    1. Add a compatibility rule to token exchange: when a request uses only the legacy vocabulary, expand orchestration:operate to the scopes it covered before feat(auth): separate environment administration permissions #9786 (providers:manage, settings:write, environment:maintain). Still keep only what the bootstrap grant allows. Explicit granular requests stay unchanged.
    2. Add tests for a legacy-only request, a granular request and a request with no scope, covering both the exchange and provider.auth.subscribe.
    3. Mobile: keep gating the Provider accounts panel on the session's permissions, and show a "missing permission" state instead of the sign-in panel.

    Workaround
    For now, use desktop or web to sign in to providers. Once an iOS build that no longer sends the old scope list ships, remove and re-add the environment to get a fresh session.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 7, 2026
  3. juliusmarminge commented on Oct 7, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    #16856 reports the same four-scope session from the macOS desktop app on server 0.0.46-nightly.20261007.2774, paired with a fresh link that had all 16 permissions. There it shows up as the Files panel saying "This connection cannot read host files", because filesystem:read is dropped too. So the compatibility fix here should cover the desktop app as well, and the legacy expansion needs to include every scope split out of the old vocabulary (including filesystem:read), not only the provider-management ones.

  4. entity commented on Oct 7, 2026

    @entity
    Contributor

    Same issue here on iOS 2.0.0 against 0.0.46-nightly.20261007.2761 (Linux server). The clone flow fails with missing required scope: source-control:write and the folder browser with filesystem:read. The pairing link had 13 scopes and the stored auth_sessions row had only the four legacy ones, so source-control:write is affected as well.

    Two things that might matter for the fix:

    • Existing sessions stay broken after a pairing-time fix. The narrowed scopes are already persisted, so already-paired clients will either need to re-pair (worth calling out in release notes) or need a one-off migration that expands sessions whose scopes are exactly the legacy set.
    • Bearer and WebSocket verification read scopes from different places. verifySessionToken returns claims.scopes from the signed token, but verifyWebSocketToken returns row.value.scopes from auth_sessions. Any migration would need to account for both.

    Workaround that worked for me: I updated the iPhone session's scopes in auth_sessions to match its pairing link's grant (no server restart), then force-quit and reopened the iOS app. After that the folder browser and cloning a repo both worked. Bearer HTTP requests presumably still carry the token's original four scopes until a new token is issued, so some HTTP-only paths may still fail.

  5. theophanemayaud commented on Oct 8, 2026

    @theophanemayaud

    Same issue here with the Files screen on an iPhone.

    • iOS app: TestFlight 2.0.0, build 110. TestFlight shows “Open”, with no update offered on that screen.
    • Host: macOS, T3 Code 0.0.46-nightly.20261008.2801, updated from 0.0.46-nightly.20261007.2761.
    • Connection: T3 Connect. The host is reachable remotely and its tunnel is healthy.

    Opening Files shows:

    The authenticated token is missing required scope: filesystem:read.

    A fresh mobile session issued 2026-10-08 at 04:08:37 UTC, after the host update, still has only these scopes in auth_sessions:

    ["orchestration:read", "orchestration:operate", "terminal:operate", "relay:read"]

    So this also blocks file browsing, and updating the host does not resolve it for build 110. No session permissions were manually modified.

    Is there a fixed TestFlight build available, or a supported way to refresh the permissions for this client?

  6. AISupplyGuy commented on Oct 8, 2026

    @AISupplyGuy

    Same here on TestFlight 2.0.0 (110) against 0.0.46-nightly.20261008.2801 on two Linux servers and two macOS hosts. It isn't limited to T3 Connect: pairing directly over Tailscale with a link that grants all 16 scopes also stores a 4-scope iOS session (orchestration:read orchestration:operate terminal:operate relay:read). Clone fails with source-control:write and the folder browser with filesystem:read. Desktop and Safari sessions on the same links get the full grant.

  7. theophanemayaud commented on Oct 8, 2026

    @theophanemayaud

    Another affected action on the same iOS TestFlight 2.0.0 (build 110): updating the host remotely is blocked by a missing environment:maintain scope.

    The environment is shown as Connected, with T3 Connect in use. The host is on 0.0.46-nightly.20261008.2801, and the app offers 0.0.46-nightly.20261008.2813, but attempting the update shows:

    The authenticated token is missing required scope: environment:maintain.

    This is in addition to the filesystem:read failure reported above. It also prevents using the iOS app to install the available host update, so I’m updating the Mac locally.

  8. treyecollins commented on Oct 8, 2026

    @treyecollins

    Another symptom of the same four-scope iOS session: media embedded in chat messages by host path never loads, and the UI doesn't say why.

    • iOS TestFlight 2.0.0 (build 110), T3 Connect, macOS host on 0.0.46-nightly.20261008.2801.
    • The latest mobile session in auth_sessions (issued 2026-10-08T12:01Z) has ["orchestration:read","orchestration:operate","terminal:operate","relay:read"].

    When the agent embeds a host file in its reply (![video](</abs/path/clip.mp4>) or a PNG path), the phone shows a bare Video unavailable / Image unavailable box. The host trace shows ws.rpc.assets.createUrl failing with:

    EnvironmentAuthorizationError: The authenticated token is missing required scope: filesystem:read.
    

    So the client never gets an asset URL. No /api/assets/... request for those files reaches the server. Uploaded attachments (pasted images) in the same threads load fine with HTTP 200, because they don't need filesystem:read. The Files screen fails the same way but at least shows the scope error. The chat embeds hide it behind a generic "unavailable", which made this look like an encoding or iOS player problem at first.

    Suggestion for the fix: when assets.createUrl is refused for a missing scope, the media placeholder should say so ("This connection can't read host files") instead of "unavailable".

  9. jlipworth commented on Oct 8, 2026

    @jlipworth

    Another symptom of the same four-scope iOS session: Usage shows $0.00 on every environment.

    • iOS TestFlight 2.0.0 (110), T3 Connect, macOS host on 0.0.46-nightly.20261008.2819.
    • Every mobile cloud-connect session issued today has ["orchestration:read","orchestration:operate","terminal:operate","relay:read"]. Desktop sessions minted the same way in the same hour have the full standard set.
    • Since feat(auth): separate diagnostics and usage permissions #9790, server.getUsageSummary and server.refreshUsageRates require diagnostics:read (apps/server/src/auth/RpcAuthorization.ts:106-107). Before that they only needed orchestration:read.

    This matters for the proposed fix. diagnostics:read was split from orchestration:read, not orchestration:operate (legacyParents, packages/contracts/src/auth.ts:154-164). So expanding only orchestration:operate leaves Usage broken, the same gap noted above for filesystem:read. Expanding a legacy-only request by every legacyParents entry whose parent was requested, then intersecting with the grant, would cover all the split permissions in one rule. It would also match what sessionGrantsScope already does on the client side for old servers.

  10. max-miller1204 commented on Oct 8, 2026

    @max-miller1204

    Confirmed another fresh mobile 2.0.0 session with the same four-scope grant on 2026-10-08. This also shows that the pairing link had the missing permissions before redemption.

    Read-only metadata checks in the macOS host's statev2.sqlite found:

    • Pairing link created at 2026-10-08T14:32:34.948Z.
    • Link consumed at 2026-10-08T14:33:09.773Z.
    • Matching client session issued at 2026-10-08T14:33:09.776Z, with client_app_version = 2.0.0.

    The consumed link's auth_pairing_links.scopes contained 16 permissions:

    ["orchestration:read","orchestration:operate","settings:write","providers:manage","environment:maintain","preview:operate","diagnostics:read","terminal:read","terminal:operate","source-control:write","filesystem:read","filesystem:write","relay:read","access:read","access:write","relay:write"]

    The resulting session's auth_sessions.scopes contained only four:

    ["orchestration:read","orchestration:operate","terminal:operate","relay:read"]

    Two other fresh mobile 2.0.0 sessions on the same host had the same four permissions. The permission drop is stored in the session record, so it is not only a display problem. The consumed link explicitly granted providers:manage, along with the other missing permissions.

    Reproduction observed:

    1. Create a pairing link with the permissions above.
    2. Redeem the link in mobile 2.0.0.
    3. Inspect the resulting session permissions on the host.
    4. Observe that only the four permissions above remain.

    Expected: mobile requests the permissions needed for its supported features, within the owner's grant. If it intentionally requests fewer permissions, the UI explains that restriction.

    The environment auth documentation states that token exchange intersects requested scopes with the pairing grant. This matches the legacy scope request described in the maintainer response above. The token-exchange request was not captured in this reproduction, so this local evidence confirms the grant reduction rather than independently proving the request payload.

    No credential values, pairing URLs, session IDs, device names, or account identifiers are included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions