Require local Allow for Phone Access on this Mac

Merged
TE
6d ago
+1986-96

Leo, asked "should Phone Access ask on this Mac before serving a new phone on your account?", answered: "probably? you can decide". Decided: yes, an unfamiliar phone waits for a local Allow on this Mac.

Leo's words for the iOS/remote push: "well i just think we can improve it a f***ton more than it is now... it's slow it's bad it belabours the point in too many tooltips it's ugly in places it doesn't even work in places there's lots of functionality that needs to get in"

What changes

Phone Access currently serves same-account MobileIrx peers without a local decision on this Mac. With this PR, an unfamiliar TLS-proved phone endpoint waits for a person's Allow on this Mac. The decision is saved in the shared per-user/per-Mac phone list, and removing the phone in Settings > Mobile closes its sessions and makes it ask again.

  • The question shows the signed-in account and the full device key. Allow, Don't Allow and Cancel are buttons. Only Don't Allow starts a 10-minute cooldown; Cancel, Escape, dismissal and the 2-minute timeout leave the next connection free to ask.
  • One question is shared per endpoint, at most two questions are pending, and debug automation can't answer it.
  • Removing a phone cancels its open question and invalidates a late Allow, per phone. A store change that began before a removal can't re-approve the removed phone.
  • Account switches invalidate trust synchronously. Allow is published only after a successful save.
  • Legacy stored entries decode as hostd. Iroh entries never reach hostd's devices, credentials or Face ID approvers. Settings > Mobile lists and removes Iroh phones even when the legacy host is off.

This adds a local Allow gate to the existing Iroh phone transport (MobileIrxHost, already on base). It adds no new Iroh machine-to-machine use.

Credits the intent of #21898 and the sole-user ownership/question-binding fix from #23552. From #21898:

This adds the Codex-style per-device step for phones, and Settings > Mobile becomes the one place that lists every phone allowed on this Mac.

Screens

Before: no prompt; a same-account phone is served with no decision on this Mac.

After (dark, 2x, synthetic device and account), from PhoneAdmissionCaptureTests on a fleet Mac at this head's app code. I viewed it before landing:

Allow Demo iPhone to use this Mac? dialog

The light capture draws the shared dialog's glass-layer title and buttons blank in an offscreen render. That happens in the existing CmuxDialogView, which this PR does not change, so it isn't shown here.

Validation at 49bcf768a371a604a541b607b0ee3e551905c3f7

  • Fleet app compile: passed at fc52c2a3 (the last commit only adds two entries to scripts/localization-allowed-omissions.json).
  • Fleet suites at fc52c2a3, all passed: CmuxNextMobileHostTests (44 tests, 10 suites) and CmuxNextMobileTests (93 tests, 18 suites), which include PhoneAdmissionTests, PhoneAdmissionCaptureTests, PhoneAdmissionStoreTests and PhoneAccessGateTests; PhoneAccessMigrationTests and PhoneAccessSettingTests in a separate run.
  • The six Phone Access suites also passed with a GUI session (same app code, at 88d80eca).
  • The localization debt ratchet failed at fc52c2a3: the new labels "%@ · cmux next" and "%@ · cmux (iOS)" copied English into 8 locales each. 49bcf768 lists them as brand literals, so IPhone.xcstrings stays at its baseline of 19.
  • Independent reviews: SHIP at 88d80eca (full PR, including both earlier BLOCK findings), f016131 (capture test), fd115828 and fc52c2a3 (hand-resolved feat-cmux-next updates; both sides of each conflict are kept), and 49bcf768 (the localization entries).

Changelog

Added: Phone Access asks once on this Mac for each unfamiliar phone, and Settings > Mobile can forget it.

Agent session: agent session

🤖 Generated with Claude Code