fix(web): confirm session before rendering and recover concurrent 401s - #152
Merged
Merged
Conversation
Two symptoms, one root cause: the SPA trusted any access token in localStorage, but the server keeps tokens in memory (15 min TTL, wiped on restart). Slow table population: after token expiry every startup request 401s, but only the first refreshed and retried; the rest waited for their next poll (2s queue, 5s history) or never retried (servers, categories). All 401s now share one in-flight refresh and retry; a request sent with an already rotated token retries without spending another single-use refresh token. Token expiry is persisted so an expired token is refreshed up front. Content flash before login bounce: the guard passed on a stale token, so the chrome and Downloads page rendered until the API rejected it. The guard now confirms the session with the server once per page load, and chrome follows a reactive session signal (plus route: login/welcome stay full-screen) instead of a 2s localStorage poll. The login page uses the same check so a stale token no longer leaves it stuck on "Checking status...". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
Fixes two UI bugs with one root cause: the SPA trusted any access token in
localStorage, but the server keeps tokens in memory (15 min TTL, wiped on restart).1. Slow initial table population. After token expiry every startup request (
/queue,/status,/history,/config/servers,/config/categories) 401s together. Only the first refreshed and retried; the rest waited for their next poll (2s/5s) or never retried (servers, categories).2. Unauthenticated user briefly sees content before the login bounce. The guard passed on a stale token, so the chrome and Downloads page rendered until the API rejected it; chrome also tracked auth via a 2s
localStoragepoll.authGuardconfirms the session with the server once per page load (refresh if expired, else probe/api/status) and redirects viaUrlTreeif rejected./login+/welcomestay full-screen.Trade-off: a cold page load waits one extra round trip before the first protected view renders.
Testing
npm test -- --watch=false: 100 passed (new regression tests for shared refresh, concurrent 401 recovery, non-auth retry failure keeping the session, guard redirect, stale-token clearing, bare routes)npm run build -- --configuration=production: OK (existing 128-byte style budget warning onqueue-view, untouched)./ci/run e2e: 90 passed. An earlier run caught a first-boot/welcome→/downloadsrace, which the bare-route change fixes.🤖 Generated with Claude Code