Before submitting
Area
apps/mobile
Steps to reproduce
- Link two or more T3 Code environments to T3 Connect.
- Sign in to the native Android app and let it connect to the linked environments.
- On each environment host, open Settings → Connections → Authorized clients.
- Observe two identical
T3 Connect connect Android clients for the one phone/environment connection.
- Close/reopen or resume the Android app after the cached environment access token has expired; the pattern recurs as another pair.
This was reproduced repeatedly across multiple days and on each linked host.
Expected behavior
One Android device connecting to one environment should create one authorized environment session and one RPC/WebSocket connection, matching the documented single connection-runtime ownership model.
Actual behavior
Two distinct T3 Connect connect sessions are created for the same Android device and environment. Both have the same five scopes, DPoP proof-key thumbprint, Android/OkHttp metadata, and one-hour lifetime.
This is not only a duplicated UI row. Read-only inspection of the environment database and server traces shows two independent end-to-end flows:
- two
/api/t3-connect/mint-credential requests
- two environment descriptor requests
- two
/oauth/token exchanges
- two
/api/auth/websocket-ticket requests
- two actual
/ws connections
For one measured occurrence:
- pairing links were created 5 ms apart
- access-token sessions were issued 35 ms apart
- both pairing links were consumed by the same Android DPoP key
Historical session rows show the same paired issuance pattern repeatedly, generally tens of milliseconds apart.
Impact
Minor bug or occasional failure
The app remains usable, but each Android connection doubles authorized-client rows and briefly opens duplicate WebSockets. Revoking one row is not a durable workaround because the pair can be recreated on a later bootstrap.
Version or commit
Environment server: 0.0.34-nightly.20260817.1120
Android app: installed Android T3 Connect build current as of 2026-08-22; exact client build is not exposed in the server-side metadata for this version.
Current main was also inspected for the relevant connection/auth flow.
Environment
- Native T3 Code Android app (
okhttp/4.9.2)
- T3 Connect managed relay / Cloudflare tunnel
- Linux and macOS linked environment hosts
- Same behavior on each linked host
Logs or stack traces
# Sanitized shape from auth_sessions for one occurrence:
issued_at client_device_type client_os client_user_agent scopes
2026-08-22T15:54:36.149Z mobile Android okhttp/4.9.2 5 standard scopes
2026-08-22T15:54:36.184Z mobile Android okhttp/4.9.2 5 standard scopes
# Corresponding sanitized pairing-link timing:
created_at consumed_at proof_key
2026-08-22T15:54:35.708Z 2026-08-22T15:54:36.182Z same Android key
2026-08-22T15:54:35.713Z 2026-08-22T15:54:36.147Z same Android key
All session IDs, hostnames, IPs, tokens, proofs, and key material have been omitted.
Investigation notes
The observed race appears compatible with two concurrent calls to RemoteEnvironmentAuthorization.authorizeDpop. In packages/client-runtime/src/authorization/service.ts, authorization reads the per-environment token store, then obtains a bootstrap credential, exchanges it, and only afterward persists the token. There is no visible per-environment single-flight/critical section around that read-mint-write sequence, so two concurrent connection attempts can both observe a miss and mint separate sessions.
That explains how the duplicates survive server-side, but not why Android initiates two connection attempts. The server traces have distinct propagated trace IDs for the two complete flows, indicating separate client-side attempts rather than duplicate rendering or a server retry.
Potential hardening:
- Identify the duplicate Android startup/resume connection owner or signal.
- Single-flight
authorizeDpop per environment/device so concurrent cache misses share one bootstrap exchange.
- Consider server-side replacement/deduplication for an active
cloud-connect session with the same DPoP thumbprint and client identity.
- Include mobile app version/surface in authorized-session metadata to improve diagnostics.
Workaround
Revoking one duplicate while the Android app is closed removes the extra row temporarily. It may be recreated when the app next needs a fresh environment access token.
Before submitting
Area
apps/mobile
Steps to reproduce
T3 Connect connectAndroid clients for the one phone/environment connection.This was reproduced repeatedly across multiple days and on each linked host.
Expected behavior
One Android device connecting to one environment should create one authorized environment session and one RPC/WebSocket connection, matching the documented single connection-runtime ownership model.
Actual behavior
Two distinct
T3 Connect connectsessions are created for the same Android device and environment. Both have the same five scopes, DPoP proof-key thumbprint, Android/OkHttp metadata, and one-hour lifetime.This is not only a duplicated UI row. Read-only inspection of the environment database and server traces shows two independent end-to-end flows:
/api/t3-connect/mint-credentialrequests/oauth/tokenexchanges/api/auth/websocket-ticketrequests/wsconnectionsFor one measured occurrence:
Historical session rows show the same paired issuance pattern repeatedly, generally tens of milliseconds apart.
Impact
Minor bug or occasional failure
The app remains usable, but each Android connection doubles authorized-client rows and briefly opens duplicate WebSockets. Revoking one row is not a durable workaround because the pair can be recreated on a later bootstrap.
Version or commit
Environment server:
0.0.34-nightly.20260817.1120Android app: installed Android T3 Connect build current as of 2026-08-22; exact client build is not exposed in the server-side metadata for this version.
Current
mainwas also inspected for the relevant connection/auth flow.Environment
okhttp/4.9.2)Logs or stack traces
All session IDs, hostnames, IPs, tokens, proofs, and key material have been omitted.
Investigation notes
The observed race appears compatible with two concurrent calls to
RemoteEnvironmentAuthorization.authorizeDpop. Inpackages/client-runtime/src/authorization/service.ts, authorization reads the per-environment token store, then obtains a bootstrap credential, exchanges it, and only afterward persists the token. There is no visible per-environment single-flight/critical section around that read-mint-write sequence, so two concurrent connection attempts can both observe a miss and mint separate sessions.That explains how the duplicates survive server-side, but not why Android initiates two connection attempts. The server traces have distinct propagated trace IDs for the two complete flows, indicating separate client-side attempts rather than duplicate rendering or a server retry.
Potential hardening:
authorizeDpopper environment/device so concurrent cache misses share one bootstrap exchange.cloud-connectsession with the same DPoP thumbprint and client identity.Workaround
Revoking one duplicate while the Android app is closed removes the extra row temporarily. It may be recreated when the app next needs a fresh environment access token.