Files
orca/src
Jinwoo Hong c8ed629217 fix(cloud-auth): one owner for the cloud session; never drop a rotated token, stop after a 401 (#28523)
* fix(cloud-auth): never drop a rotated refresh token, and stop after a 401 even when the store cannot be written

A refresh whose session save failed (write error, or a moved mutation fence)
discarded the rotated token, so the relay broker's ~10 s renewal kept
replaying the spent one until the server revoked the family. The 401 then
could not clear the session because the revocation write failed the same way,
so the broker looped on 401s indefinitely.

* fix(cloud-auth): one compare-and-swap save for rotated tokens; org selection keeps them

- Rotated tokens save only while the store still holds the spent token and the
  identity is not signed out; linkage (and a server-reported org change) moves
  only under the refresh's own fence.
- Org selection refreshes through the shared single-flight and merges onto the
  latest stored session instead of writing back the tokens it started with.
- A failed session write removes the stale file so a restart cannot replay it.
- A cleared session refuses conditional saves until the next sign-in.

* refactor(cloud-auth): one read-merge-save helper for stored sessions; tokens before relink

- updateStoredOrcaCloudSession re-reads, applies an update and saves under the
  fence in one turn; org selection, capability refresh and rotation all use it.
- Rotation saves tokens first and relinks best effort, so a failed fence write
  cannot leave the spent token stored.
- Only a rotation removes the on-disk file after a failed write; other saves
  leave a still-valid token in place.
- Capability refresh fences at request time, after any inner refresh relink.

* fix(cloud-auth): roll the fence back when relinking after a refresh fails

A fence left on the server-reported org while the profile link kept the old
one made every later capability refresh return reconnect-required.

* refactor(cloud-auth): one owner for each profile's cloud session

profile-cloud-session-owner.ts is now the only code that reads or writes a
profile's session. Renewal, org selection, capability refresh, sign-in and
sign-out ask it for changes; it keeps an in-memory generation (sign-in/out)
and link version (org changes) instead of the on-disk mutation fence.

Deletes profile-cloud-session-mutation.ts (account-session-mutation.json),
profile-cloud-session-rotation-save.ts, updateStoredOrcaCloudSession and the
profile-switch fence write.

* fix(cloud-auth): retry an unsaved rotation until it lands; sign-in save failures throw as before

- The store keeps a rotation whose write failed and retries it on every read and at quit,
  so one failed write no longer signs the user out on the next restart.
- Only a rotation keeps its session after a failed write; sign-in, org selection and
  capability writes throw as on main.
- Org selection succeeds when the link already moved to the selected org.
- The owner reads the profile's link itself and bumps its link version only on an org
  change; commitCloudSessionRelink returns the profile list.
- Adds the auth characterization suite that pins main's behaviour.

* fix(cloud-auth): a failed non-rotating save keeps a pending unsaved rotation

Found in the real-app run: a capability save that failed while a rotation was
unsaved dropped the pending rotation, so the next renewal resent the spent token.

* fix(cloud-auth): flush unsaved rotations on OS shutdown; stale capability replies match main

- Flush unsaved rotations on Windows session-end and powerMonitor shutdown, through the
  owner, which now also owns the quit flush.
- Capability replies are refused once the org link moved at all, as on main; only org
  selection accepts a link that already reached the selected org.
- Sign-in and sign-out reuse invalidateCloudSessionChanges; small store cleanups.
- Pins the A->B->A stale capability reply in the characterization suite.

* fix(cloud-auth): flush unsaved sessions before recording the Windows session end
2026-10-14 09:25:30 -04:00
..