Skip to content

fix(auth): sign out without posting a logout the proxy cannot deliver - #1976

Merged
dawsontoth merged 1 commit into
stagefrom
fix/skip-proxied-logout-at-sign-out
Oct 15, 2026
Merged

dawsontoth merged 1 commit into
stagefrom
fix/skip-proxied-logout-at-sign-out

Conversation

@dawsontoth

@dawsontoth dawsontoth commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

⊙ Problem

Signing out of Studio posts logout to every remembered instance and cluster sign-in before the central-manager /Logout/. For an entity reached through the Fabric Connect proxy, that logout can't end anything. The host manager calls the instance with no cookie or token, so Harper has no session of the user's to end and answers 500. In 30 days of RUM, 16 of 24 proxied logouts were 500s, each a round trip /Logout/ waited on. Closes #1973.

🤔 Is skipping the request the right fix, rather than making it work?

Yes as filed: a proxied connection holds no credential of the user's on the instance, so no logout could end anything. On app sign-out, /Logout/ ends the only session there is. The 8 answers that were not 500 (6 × 400, 2 × 200) are unexplained, but carried no session either. Reverting is one line.

💡 Solution

  • Sign out skips the instance logout for an entity that connects through the proxy, using the predicate getInstanceClient already exports.
  • Its local state is still cleared by the shared helper's callers: the sign-out sweep and signOutEntities (self-hosted cluster removal).
  • Direct, basic-auth and cookie sign-ins keep their logout.
  • A second tab, which sees another tab's direct sign-in as proxied, no longer posts the doomed logout either.

⚖️ Alternatives

  • Central manager refuses logout on the proxy — still one round trip per entity that /Logout/ waits on; useful hardening for older clients, not the fix.
  • Keep proxied entities out of the sign-in markers — the marker also shows a proxied connection as signed in and controls the proxy fallback.
  • Read the mode from the built client instead of calling connectsThroughProxy — one source of truth for routing, but the predicate already mirrors getInstanceClient, and the existing src/config/getInstanceClient.test.ts pins that they agree. They differ only for an id without an ins-/clu- prefix, which no entity has.

🤔 Should the skip also apply when a self-hosted cluster is removed?

Yes: signOutEntities shares buildLogoutClient, so removing a cluster now skips a proxied sign-in too. There is no /Logout/ on that path. There was never anything on the instance for the proxied logout to end either. A terminated cluster's proxy answers 400. Narrowing the skip to the app sweep is a one-line move if you disagree.

🔧 Changes

✅ Verification

  • npx vitest run: 566 files, 5,855 tests passed (1 expected fail, 11 skipped). tsc -b, oxlint and dprint check clean.
  • Mutation check: with the predicate disabled, both new tests fail (the sweep's and signOutEntities'); every existing direct-Bearer, corrupt-storage, timeout and race test stays green.
  • Not observable end to end from the repo: it needs a signed-in Fabric cluster. Rollout evidence is RUM: POST /Cluster/*/operation and /HDBInstance/*/operation within 3 s before POST /Logout/ should drop to zero after the next production deploy.

🤖 Generated by Claude Code (Claude Mythos 5.1); posted via @dawsontoth.

Related PRs: #1966 overlaps (added the shared buildLogoutClient this guard lives in), 4 others independent
Complexity: easy

Deferred findings

Review-Coverage: authored=claude; ran=gemini,codex,cursor-grok,cursor-muse; adjudicated=domain; blocked=claude(fallback)(out-of-budget),cursor-composer(out-of-budget); declined=cursor-kimi,muse; rounds=3; full=1 @ 1d7404f

Review-Attention: study ~9m (sensitive: authStore.ts; raised: degraded review) @ 1d7404f

Studio's sign-out posts `logout` to every remembered sign-in before the
central-manager `/Logout/`. For an entity reached through the Fabric
Connect proxy that POST cannot end anything of the user's: the host
manager calls the instance over its socket with no cookie or token, so
Harper's `logout` has no session to end and answers 500 — 16 of 24
proxied logouts in the 30 days to 2026-10-15, each a round trip the
`/Logout/` waited on. The sweep now skips an entity that
`connectsThroughProxy`; local clears and direct logouts are unchanged.

Co-Authored-By: Claude Mythos 5.1 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request prevents sending logout requests to instances connected through the Fabric Connect proxy during app sign-out or cluster removal, as these proxied instances do not hold user credentials and would otherwise return 500 errors. The AuthStore has been updated to skip creating a logout client for these connections, and corresponding unit tests and design documentation have been updated to reflect this change. There are no review comments, and I have no additional feedback to provide.

@dawsontoth dawsontoth self-assigned this Oct 15, 2026
@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 79.99% 14917 / 18647
🔵 Statements 79.95% 15831 / 19801
🔵 Functions 75.43% 3977 / 5272
🔵 Branches 74.67% 11572 / 15497
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/features/auth/store/authStore.ts 94.76% 85.88% 97.16% 94.63% 138, 281-282, 291-294, 342, 363, 394-405, 413, 418-421, 528-531, 847, 967, 972, 1101, 1126
Generated in workflow #2389 for commit 1d7404f by the Vitest Coverage Report Action

@dawsontoth
dawsontoth marked this pull request as ready for review October 15, 2026 17:57
@dawsontoth
dawsontoth requested a review from a team as a code owner October 15, 2026 17:57
@dawsontoth
dawsontoth merged commit 6b054a9 into stage Oct 15, 2026
7 checks passed
@dawsontoth
dawsontoth deleted the fix/skip-proxied-logout-at-sign-out branch October 15, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant