fix(auth): client-side resilience for the 503 infra path - #15
Merged
Merged
Conversation
Follow-up to the isAuthenticated infra-error fix. When Privy says the user is
signed in but /api/user/state can't be loaded (a transient 503), the client now
degrades to a retry state instead of silently treating it as guest / dropping
into connect-account onboarding.
- SupercastUserStateProvider: expose isReconnecting()/hasLoadError(); retry 5xx
(not 401/403) on the user/state query; stop persisting a null/guest state to
localStorage during an outage without dropping real updates (e.g. switchAccount).
- Global axios Retry-After interceptor (client-only, registered once) that honours
a 503 Retry-After and retries the request once. A header marker caps it at one
retry so a persistent 503 can't loop.
- Layout + OnboardingPage gate on the new signals: a transient outage shows a
ReconnectingScreen ("try again") instead of guest UI / the account-creation flow
(which could otherwise write duplicate prod records).
Also adds docs/dev-environment-isolation.md — a ready-to-run runbook for the
(deferred) dev/prod environment-isolation roadmap item.
Verified: typecheck + build green; adversarial review (React correctness +
happy-path invariant) — guest/normal/logged-out paths unaffected.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
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.
Follow-up to #14 (server-side
isAuthenticatedinfra fix). That change made a transient DB/Privy outage surface as a retryable 503 instead of a false 401 / silent guest-200. This PR makes the client handle that 503 gracefully instead of collapsing it into a confusing state.Changes
SupercastUserStateProviderisReconnecting()andhasLoadError()derived from the/api/user/statequery.localStorageduring an outage — but still persists real updates (e.g.switchAccount), so a returning user's good cached state isn't clobbered and account selection isn't lost.Global axios
Retry-Afterinterceptor (src/lib/axiosRetryAfter.ts)ReactQueryProvider. On a 503 withRetry-After, waits and retries the request once.Consumers —
Layout+OnboardingPageuser/stateerrored), show aReconnectingScreen("try again") instead of falling through to guest UI or the account-creation / connect flow — the latter is the path that could write duplicate prod records.ALWAYS_ACCESSIBLE_PAGES(Cast/Profile/Channel stay public).Docs
docs/dev-environment-isolation.md— a ready-to-run runbook for the dev/prod environment-isolation roadmap item, which the owner has deferred for now (no user base yet; not worth paying for a second Railway DB + Privy app). Captured so it's one command away when scaling.Verification
npm run typecheck✅ andnpm run build✅.switchAccountduring an outage), and the interceptor's loop-guard moved from a config property to a header marker.'idle'(notisLoading), so the v4/v5 "disabled-query isLoading" trap doesn't apply.Notes
withAuthInfra()for 503s (vs the honest-500 they return today); deferred as low-value since the client treats 500/503 the same. The wrapper + a prioritized list are ready if we want to widen coverage later.