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

Open
#1,679 2 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.