feat(ui): extract auth to auth-store + harden authFetch (W5.3) - #434
Merged
Conversation
added 3 commits
June 15, 2026 12:27
Security-critical core of the auth extraction, built standalone + proven by
tests before the App.tsx wiring. Cross-model (Codex) reviewed.
auth-store.ts (Zustand, not persisted; isAuthenticated seeded from the
localStorage flag): login/verifyMfa/performLogin/logout/expireSession +
setup/recovery state + checkStatuses. Module-level authFetch for RQ queryFns.
Hardening over the previous inline implementation:
- single-flight refresh (concurrent 401s share one in-flight refresh)
- cancelQueries() THEN clear() on teardown (no late request can repopulate
cross-session cache)
- 401: refresh+retry; only refresh-failure or a still-401 retry expires —
a retried 5xx/4xx returns to the caller
- 403: {code:PERMISSION_DENIED} (authz denial, valid session) returns to the
caller; any other 403 (CSRF/unknown, plain-text) expires the session
- credentials:'include' always; tokens never read; FormData/signal preserved
14 unit tests cover all of the above (single-flight, cache purge, retry
semantics, 403 branching, request-shape). tsc + biome clean.
Part 2 (App.tsx wiring) follows; this commit is intentionally unused until then.
Always-latest bump across the JS/Go toolchain: - Biome 2.4.16 -> 2.5.0 (biome migrate: recommended->preset + nursery renames) - TypeScript build: tsc -b -> tsgo --build (@typescript/native-preview); drop typescript dep - Vite 8.0.14 -> 8.0.16, Vitest 4.1.7 -> 4.1.8 - Node 26.2.0 -> 26.3.0, npm pinned 11.17.0 (+ packageManager) - golangci-lint golden config v2.12.1 -> v2.12.2 - commitlint 20.5.3 -> 21.0.2, lint-staged 17.0.7; exact-pin remaining ^ ranges
Complete the auth decomposition: App.tsx reads auth state via auth-store selectors and dispatches flows through store actions; the module-level authFetch backs the React Query queryFns. - Replace inline login/MFA/logout/setup/recovery handlers + the local authFetch/expireSession/refresh stack with thin store dispatches. - Add cancelMfa store action (+ unit test) for the MFA 'Use different account' path; drop the dead setState shims, AUTH_FLAG_KEY, the local Setup/RecoveryStatus interfaces, and now-unused imports. - Fix two breakages from the in-progress migration: SetupWizard onLogin pointed at a removed performLogin (-> handleSetupLogin); queryFns used module authFetch without importing it. - connected stays App-local, reconciled off isAuthenticated + the interfaces query; queryFns thread the React Query abort signal. Validated: biome 2.5.0 clean, tsgo typecheck clean, vitest 198/198, vite build green.
Contributor
License Compliance ReportAll dependencies pass license compliance checksGo Dependencies
npm DependenciesSee full report in workflow artifacts Allowed Licenses: MIT, Apache-2.0, BSD-*, ISC, CC0-1.0, MPL-2.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Wave 5.3 of the stem App.tsx decomposition: extract all authentication state and flows out of the god component into a dedicated Zustand
auth-store, and bundle the always-latest toolchain sweep that landed alongside it.Two commits (squash-friendly but separated for review):
1.
chore(tooling)— toolchain to latestbiome migrateapplied:recommended→preset, nursery-rule renames)tsc -b→tsgo --build(@typescript/native-preview;typescriptdep dropped). Types/language unchanged — only the typecheck+build binary.^ranges2.
feat(ui)— auth-store wiring (part 2/2)Part 1 (
auth-store.ts+ hardened moduleauthFetch+ 14 tests) landed in58bc4fd. This wiresApp.tsxto it:authFetch/expireSession/refresh/retry stack removed (now module-level in the store).cancelMfastore action (+ unit test) for the MFA "Use different account" path.AUTH_FLAG_KEY, localSetup/RecoveryStatusinterfaces, unused imports.SetupWizard onLoginpointed at a removedperformLogin(→handleSetupLogin); queryFns called moduleauthFetchwithout importing it.connectedstays App-local, reconciled offisAuthenticated+ the interfaces query; queryFns thread the React Query abortsignal.Validation
biome check src/— clean (2.5.0)tsgo --build --noEmit— cleanvitest run— 198/198 (incl. newcancelMfatest)vite build— green, embedded tointernal/api/ui/Notes for review
authFetchsemantics (single-flight refresh, cancel-then-clear cache, 401 refresh+retry, 403PERMISSION_DENIEDvs CSRF branching) were cross-model reviewed in part 1 and are unchanged here.tsc → tsgoswap is a dev-preview compiler now driving the build — worth a deliberate look.🚫 Auto-merge intentionally NOT armed — owner sign-off gate.