feat(cloud): use Codex broker for auth recovery

Merged
TE
9d ago
+322-6

Summary

Codex authentication recovery now uses the account-scoped refresh broker after confirmation. This Mac remains the single refresh-token holder; only a short-lived access token is delivered to the selected VM. The native device-code prompt is cancellable, bounded, and shows the code in cmux instead of a VM terminal. Claude recovery remains unchanged.

The recovery dialog explains exactly what moves and reminds the user to keep cmux running on this Mac so the broker can renew access. Cancellation, dismissal, logout, and scope changes stop the in-flight prompt without retrying the failed turn. Debug-only fixtures and focused tests cover cancellation, already-cancelled tasks, browser handoff, and successful retry.

Dependencies

The broker and auth-recovery prerequisites have landed. This auth-only follow-up is based on NEXT at 1c1632b0eb6f53b647adf485914d21a67c1cd74f; it preserves the native backend availability check and the account, team, tab, session, and daemon guards from #26148. The wizard switch is separate.

Operational rules

The OpenAI CI/CD auth guidance says:

“Use one auth.json per runner or per serialized workflow stream.”

“Do not share the same file across concurrent jobs or multiple machines.”

The broker follows those rules by keeping refresh state on the user's Mac, serializing refreshes, and delivering only short-lived access to confirmed VMs. It never copies a shared refresh seed into a VM, writes credentials to the repository, or prints them to logs.

Note coverage

This addresses the setup note “Claude failed to authenticate” and the requirement to make “manual transfer claude credentials to VM” explicit and confirmed. Codex recovery now has the same one-click, user-confirmed path while stating that its refresh credential stays on the Mac.

Validation

  • prepush-gate.py --base 1c1632b0eb6f53b647adf485914d21a67c1cd74f — pass (no new violations; app-size warnings only).
  • Catalog validation passes; all seven new keys include all 21 locales.
  • Focused fleet verification at cde52914522c43d0644641163b93d19d87c5fa42: CloudCodexDeviceRecoveryTests, CloudCredentialRecoveryTests, and CloudCodexBrokerAdapterTests, cmux-ci step 33a791a56a95b31fe3aeda26: PASS (exit 0); app/test package compiled and all three suites passed.
  • The device prompt has no timer. Its user-answer stream is bounded to one answer; cancellation and scope changes dismiss it, and deferred cleanup finishes the stream.

Native UI evidence

Native cmux app captures at cde52914522c43d0644641163b93d19d87c5fa42, artifact job 2ea571994eaade549d021b8f. The before fixture reproduces the prior disclosure text from 1c1632b0eb6f; it is not an execution of that base build. The after disclosure and device-code prompt use the production native dialog specs. All fixtures are inert; no real credentials or sign-in were used. Capture privacy checks passed.

Before — previous per-VM disclosure (inert reconstruction of existing text)

LightDark
lightdark

After — broker disclosure

LightDark
lightdark

After — native device-code prompt (synthetic DEMO-CODE)

LightDark
lightdark

Review (codex gpt-6-astra xhigh, review-26211): SHIP at cde52914522c43d0644641163b93d19d87c5fa42. No findings.

Agent session: agent session