HarperFast / HarperFast/studio
Sign-out sweep: serial retry-armed instance logouts stall the CM logout, a failed logout leaves basic-auth on disk, and a re-added entity is skipped
- Dominant language
- TypeScript
- Stars
- 5
- Forks
- 4
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 40
Description
## Summary
`authStore.signOutFromPotentiallyAuthenticatedInstances` (`src/features/auth/store/authStore.ts`) is the per-entity sweep that Studio's Sign out runs before the central-manager `/Logout/`. Three defects in it were surfaced by the cross-model review of the #1672 fix and are pre-existing, so they were left out of that PR. None is introduced by the fix; all three are still present after it.
## 1. Instance logouts are serial, retry-armed, and ahead of the central-manager logout
The loop `await`s `onInstanceLogoutSubmit` once per entity, in order, and only then does `useLogout` post `/Logout/` to the central manager and run `logoutOnSuccess` (which is what clears localStorage). Every client it uses comes from `getInstanceClient`, which installs `curryRetryGatewayErrors`: on a 502/503/504 that interceptor sleeps 5s + 10s + 20s before giving up (`src/integrations/api/retryGatewayErrors.ts`), and a hung connection burns the client's 60s timeout.
Two signed-in instances, the first answering 503 on `operation: 'logout'`: the second instance's session, the central-manager logout, and the storage wipe all wait ~35s. A user who clicks Sign out and walks away is still fully signed in for that window.
Suggested shape: run the local clears for every entity up front (they already precede each network call), then dispatch the instance logouts with `Promise.allSettled` and don't make the central-manager logout wait on them — or at least build the logout client without the gateway-retry interceptor.
## 2. A failed instance logout leaves stored basic-auth credentials on disk
`flagForBasicAuth(id, null)` and `flagForFabricConnect(id, false)` run only after a *successful* POST, inside `onInstanceLogoutSubmit` (`src/integrations/api/instance/auth/onInstanceLogoutSubmit.ts`). The sweep's own clears don't touch them — unlike `signOutLocally`, which does. Normally `logoutOnSuccess` → `clearLocalStorage` wipes them anyway, so this only bites when the instance logout fails *and* the central-manager `/Logout/` rejects (offline, 401): then `Studio:BasicAuth:` (base64 username/password) survives a user-requested sign-out until the next successful logout.
Suggested shape: clear the basic-auth entry and the Fabric Connect flag in the sweep's local-clear block, the way `signOutLocally` already does, so a failed POST cannot leave them behind.
## 3. An entity re-added during an `await` is skipped
The loop is a `for…in` over `potentiallyAuthenticated` with an `await` between iterations, and `signOutAllLocally` snapshots `Object.keys` first for exactly this reason. A `loadUser` in flight when the sweep starts captured its key before the clear, and its `flagKeyAsSignedIn` on resolve re-adds `potentiallyAuthenticated[id]`; keys added after a `for…in` starts are not visited, so the sweep never revisits it, and `logoutOnSuccess`'s `localStorage.clear()` does not touch the in-memory entry. A same-tab re-login then inherits the prior user's connection — the leak `signOutAllLocally` was written to close. (Deleting the *current* key mid-loop is spec-safe; the re-add is the defect.)
Suggested shape: iterate a snapshot of the keys, and drop any entry re-added during the sweep at the end.
## Notes
- Found by review, not by a customer report; no production trail beyond the #1672 RUM family.
- All three are independent of the ordering fix in the #1672 PR and can land separately.
Contributor guide
Research direction
Read authStore.signOutFromPotentiallyAuthenticatedInstances in src/features/auth/store/authStore.ts, then compare its local clears with signOutLocally. Inspect onInstanceLogoutSubmit.ts and retryGatewayErrors.ts to understand the logout and retry paths. Done means failed sign-out cannot retain basic-auth or Fabric Connect state, re-added entities are removed, and instance failures do not stall central-manager logout.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100