Skip to content

feat(mobile): switch between signed-in T3 accounts - #1

Draft
rachelagent[bot] wants to merge 5 commits into
t3code/codex-turn-mappingfrom
feat/mobile-account-switching
Draft

rachelagent[bot] wants to merge 5 commits into
t3code/codex-turn-mappingfrom
feat/mobile-account-switching

Conversation

@rachelagent

@rachelagent rachelagent Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Mobile users with more than one T3 Connect account have to sign out and sign back in to move between them. Once Clerk multi-session is enabled on the instance, Clerk's native profile view (already used for Settings → T3 Account) shows Add account and Switch account on both iOS and Android. We don't need a custom switcher.

Before this PR, a switch from account A directly to B was a corner case. CloudAuthBridge handled it inside one untested effect. With multi-session it becomes the main path, so the logic now lives in cloudAccountSync.ts, a small controller with tests. CloudAuthBridge feeds it the current Clerk session and the set of signed-in accounts.

The controller tracks the installed account: whose drafts and relay environments are on the device. When the user switches from A to B, it:

  1. Deactivates the relay session right away, so neither account's relay state can be read during the switch.
  2. Saves A's environment list (while A stays signed in), then archives A's drafts, disconnects A's relay environments, clears the relay token cache and unregisters A's push device.
  3. Installs B: restores its drafts and, if B has a saved list, reconnects those environments with no onboarding. T3 Connect onboarding only appears for an account this device has nothing saved for.

Signing out forgets that account's saved environments, including an account that isn't active. Signing out of one account while another stays signed in falls through to the remaining account, which reconnects its saved environments.

Each account's relay token reader is bound to its own Clerk session. That way the cleanup that runs after a switch unregisters the previous account's push device, not the new one's.

Races and crashes fail safe:

  • A cold start never onboards.
  • If switches come in faster than cleanup, only the last account activates, and skipped accounts keep their saved lists.
  • A failed cleanup keeps the next account inactive, and the next attempt retries it.
  • The list is saved before removal, and deleted only once restored. So an interrupted cleanup keeps the complete list, and an interrupted restore resumes on the next start.
  • A switch made while the app was closed is handled on the next start.

One account is active at a time. Keeping every account connected at once is a later PR.

Stacked on pingdotgg#2829's branch (t3code/codex-turn-mapping). Multi-session is not yet enabled on the production Clerk instance. Until it is, the native view hides the new rows and behavior is unchanged.

Testing

  • vp test run src/features/cloud in apps/mobile: 47 passed. The cloudAccountSync tests cover:
    • cold start
    • switch ordering
    • reconnecting saved environments when switching back, with no onboarding
    • accounts with no environments
    • repeated Clerk sessions, both before and during install
    • rapid switches, including skipped accounts keeping their lists
    • a failed cleanup retried against the right account
    • interrupted cleanups and restores
    • a switch made while the app was closed
    • sign-out, including an inactive account and signing straight back in
    • cancellation
  • tsc --noEmit for mobile, plus vp lint on the changed files: clean.
  • Three rounds of review by a separate model. Each finding was checked against the code, and each fix has a regression test that fails without it.
  • The screenshots and recording come from one scripted, unattended run, repeated against the final commit with the same result.

Recording

One scripted take:

  1. Sign in as alpha and connect Alpha Studio from onboarding.
  2. Add bravo and connect Bravo Workstation.
  3. Switch back to alpha. Alpha Studio reconnects without onboarding.
  4. Sign out of alpha. The app falls through to bravo, and Bravo Workstation reconnects.

Idle stretches are trimmed.

account-switching.mp4

Screenshots

Captured on an iOS 27 simulator running this branch. A local mitmproxy addon stands in for Clerk multi-session and the T3 Connect relay. Each account has its own relay environments, backed by real local T3 servers. "Alpha MacBook" is listed but has no server behind it.

1. Sign in as alpha: a new account, so onboarding lists its environments

Signed out Clerk sign-in Onboarding Alpha Studio connected
Signed out Sign in Alpha onboarding Alpha connected

2. Add bravo: alpha's environments are disconnected and saved, bravo onboards

Home as alpha Bravo onboarding Bravo Workstation connected Home as bravo
Alpha home Bravo onboarding Bravo connected Bravo home

3. Switch back to alpha: Alpha Studio reconnects, no onboarding

Switch account Alpha's environments Home as alpha
Switcher Alpha reconnected Alpha home again

4. Sign out of alpha: the app falls through to bravo, whose environment reconnects

Bravo's environments
Bravo after alpha sign-out

Opus 5.5 via Claude Code in T3 Code.

🤖 Generated with Claude Code

Clerk multi-session lets the native profile view add and switch accounts.
Move the account transition logic out of CloudAuthBridge into a tested
controller so a direct A to B switch revokes A before B activates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Sep 23, 2026
Switching accounts used to act like a sign-out followed by a sign-in: the
previous account's relay environments were dropped and T3 Connect onboarding
ran again on every switch.

Now each transition saves the outgoing account's relay environments while it
stays signed in. Switching back reconnects them and restores drafts without
onboarding. Onboarding only appears for an account this device has no saved
record for, and sign-out forgets the account's saved environments.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added size:XL and removed size:L labels Sep 23, 2026
rachelagent Bot and others added 3 commits September 23, 2026 03:27
- Bind each account's relay token reader to its own Clerk session, so
  cleanup after a switch unregisters the previous account's push device
  rather than the new one's.
- Save an account's environment list before removing its environments, and
  never overwrite a saved list with an empty registry. A retried cleanup or
  an account skipped by rapid switches keeps its list.
- Finish installing an account once its drafts are restored, even if a newer
  switch arrives, so the next cleanup archives everything it restored.
- Delete a saved list once it has been restored, and resume a restore
  interrupted by the app closing.
- Forget saved environments as soon as an inactive account signs out.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Cleanup targeted the last observed account, which is not always the
account whose data is on the device. Track the installed account (and its
token reader) instead, read from the drafts' owner on a cold start:

- A failed cleanup leaves its account installed, so the next switch
  retries it rather than cleaning a skipped account's empty state.
- Leaving an installed account always saves its list, including an empty
  one, so returning to it never re-onboards. An existing saved list is
  kept, since after an interrupted cleanup or restore it is the complete one.
- The onboarding decision is made once at install and carried to
  activation, so a repeated Clerk session cannot re-request it.
- Every account change clears a pending onboarding request.
- Pending Clerk sessions count as signed in and keep their saved lists.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Read the signed-in accounts when a change is observed, not when its
  cleanup runs, so signing straight back in cannot undo a sign-out and
  bring the old environments back.
- Skip onboarding only before the first account change of the process
  (a cold start), so a session Clerk repeats before the new account
  installs still onboards it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for bd04637.

This comment will update automatically after the next completed run.

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

Labels

size:XL 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.

0 participants