cmux NEXT: keep incognito workspaces off the phone
Merged
TE
5d ago+211+211+012345678901234567890123456789-17-17-01234567890123456789
Problem
A paired phone listed an incognito window's workspace (its title, folder and terminal titles) and could replay, type into, rename and close its terminals over the shipped-iOS compat RPC (spaces-incognito-audit leak 3). Leo asked for incognito spaces on 2026-10-31. The spec (leo-workspace design/spaces.md, "Incognito") says: "Normal and incognito content never mix", and nothing of the window is kept.
Change
PhoneAccessGateholds the app's set of hidden workspace keys (setHiddenWorkspaces/hidesWorkspace, case-insensitive).MobileWorkspaceRows.resultleaves hidden workspaces out of the list.locate(surfaceID:)skips them, so terminal replay, input, paste, rename, close and viewport on one of their terminals answernot_found.workspace.close,workspace.actionandterminal.createthat name a hidden workspace also answernot_found.- The app publishes the set each time its incognito windows change (
recordIncognitoWorkspaces, through the newPhoneIncognitoHiding). The set covers claimed workspaces still being created and every ephemeral workspace the local daemon flags.
Relay policy (GHSA-9vmv-3hjw-j28c): no v2 socket method is added or allowlisted. This change only narrows what the compat session answers.
Tests
- Commit 1 adds failing tests only:
IncognitoPhoneTestsandIncognitoSpaceTests.phonesAreToldToHideIncognitoWorkspaces. - Commit 2 adds the fix.
- The fleet package suite runs red at the test commit and green at the head.
- The god-file ratchet passes;
WindowManageris net zero in lines.
Not covered (residual)
- The daemon-lane path (a raw socket splice through
DaemonLanePolicy) still answerslist-workspacesand similar calls for newer iOS builds unfiltered. The fix belongs in the daemon: hide ephemeral workspaces fromremote: trueclients. - Feed and iPhone push items for incognito notifications are not filtered here.
- There is a short gap before the daemon's ephemeral flag reaches the app for a workspace that no window lists yet.
🤖 Generated with Claude Code
Agent session: agent session