fix(auth): show a retry after rejected relaunch callbacks

Merged
TE
7d ago
+165-5

A browser sign-in callback arriving after cmux relaunched lost its in-memory state and was silently rejected. URLs delivered before launch finishes now wait for the initialized app instead of being dropped. The callback now records the existing safe failure state and opens Accounts, where “Sign-in did not finish. Try again.” and Sign In are already available. A fresh sign-in uses a new state. Existing signed-in accounts and active attempts keep their current screen.

Callback rejection, token handling and single-use state rules are unchanged. No callback state is persisted. The risk is opening Accounts after a failed external callback; the app waits for restoration and checks that it is still signed out and idle before doing so.

Leo’s request:

Also, we need to be fixing authentication issues, like the whole onboarding situation. Is that in? What does you improve? What does you fix? The edge cases, like you guys need to be comprehensively brainstorming all the onboarding edge cases: foot guns, paper cuts, snags, clips, whatever the fuck.

Validation: earlier head f683013988ee6cb2f5cb0ad5f9138d108e246471 passed all 13 HostBrowserSignInFlowFailureTests in fleet job 8de508e31f2cd62cd53e1dc3 (exit 0; summary SHA-256 129e0812e7121ba4f7f0962b4247d1c8db5946abfd40af3e6b9cc067a4271110). Predecessor 3043fc8fd77de1f2c64b9b40b072bbe75dc87332 passed all 13 HostBrowserSignInFlowFailureTests in fleet job 23df842f83450a08068fd2b7. Tests cover rejected relaunch without token writes, fresh retry, signed-in replay, restore races, and existing failure paths. Fleet job f9453cc5da18083a4667a9f6 compiled the app and all test targets in 404.38s and passed OpenedURLDeliveryTests (1/1) at 646b6a1cfc3c63d53044c4ea95dc3a2c8da718e7. The only change from that head to the final head is a runtime-test synchronization fix; app and delivery-test sources are identical, so the compile is reused. Static prepush checks and diff checks pass. Regression-only d4e4b9856349382a7e2d68865361275c6630be74 ran in job ddbeb4b23ad9078f40a960b9 (run 40621236174): compilation passed, the relaunch retry assertion failed as expected (lastFailure remained nil), and the other 11 tests passed.

Overlap search found only #26508, owned by this lane, which changes the Safari continuation in a separate branch of the same function. This fix does not include that change. Reuses the existing Accounts surface, colours, glass, copy and buttons; no new visual design.

No capture: this reuses the existing Accounts failure state (“Sign-in did not finish. Try again.” with Sign In), with no new view or copy. The fault only shows when macOS hands a stale callback URL to a relaunched app, and the capture tours drive the app through cmux CLI and RPC steps only, so no tour can deliver that URL; the red/green tests below cover the behavior.

Carry fix (head aca019689fe1166e44fa9215078fa976e93e1338): auth-refresh-tests was red at c8d829c1 on this PR's own change (run 40750150140: lateCallbackAfterSignOutIsRejected and statefulExternalCallbackWithoutActiveAttemptIsRejected saw .invalidCallback). The flow now remembers whether the user signed out since the last attempt started. While that holds, every late callback (unknown state, old state without tokens, or a malformed payload) stays quiet, as before this PR. With no sign-out (the relaunch case), or once a new attempt has started, a stale callback offers the retry; statefulExternalCallbackWithoutActiveAttemptIsRejected, which is the relaunch case, now expects it. Two new tests cover this: lateMalformedCallbackAfterSignOutStaysQuiet and staleCallbackAfterSignOutAndALaterAttemptStillOffersRetry.

Validation at aca01968, the last commit with this PR's changes (later commits up to 1f9b79d3 only merge feat-cmux-next): fleet step c74571e6de36090368c606cd at aca01968 passed HostBrowserSignInFlowFailureTests (15/15) and HostBrowserSignInFlowTests (24/24). Red: test-only commit d2ba1091b78c4c24bb2b77e201229aa47d1ad4d2 (fleet step bef0f2cf35bc2b70d2bb0608) failed both new tests and passed the other 37.

Changelog

Show a sign-in retry after a browser callback arrives following an app relaunch.

Review (codex gpt-6-astra high): SHIP at f683013988ee6cb2f5cb0ad5f9138d108e246471. Fresh independent review: no blocking findings.

Agent session: agent session