Skip to content

fix(auth): client-side resilience for the 503 infra path - #15

Merged
arcabotai merged 1 commit into
mainfrom
fix/auth-client-resilience
Jun 22, 2026
Merged

arcabotai merged 1 commit into
mainfrom
fix/auth-client-resilience

Conversation

@felirami

Copy link
Copy Markdown
Collaborator

Follow-up to #14 (server-side isAuthenticated infra 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

SupercastUserStateProvider

  • Exposes isReconnecting() and hasLoadError() derived from the /api/user/state query.
  • Retries 5xx (not 401/403) on that query, with backoff.
  • Stops persisting a null/guest state to localStorage during 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-After interceptor (src/lib/axiosRetryAfter.ts)

  • Client-only, registered once via ReactQueryProvider. On a 503 with Retry-After, waits and retries the request once.
  • Uses a header marker (not a config property) to cap at one retry — config properties can be dropped when axios merges config for the retry, which would risk an infinite loop on a persistent 503.

Consumers — Layout + OnboardingPage

  • On a transient outage (Privy-authenticated but user/state errored), show a ReconnectingScreen ("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.
  • Respects 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 ✅ and npm run build ✅.
  • Adversarial review (React correctness + happy-path invariant):
    • Happy/guest/logged-out paths unaffected — genuine guests get a 200 (not an error), so the new gates never misfire on them; logged-out visitors short-circuit before any reconnecting state.
    • Fixed two real findings before commit: the localStorage guard was too broad (would drop switchAccount during an outage), and the interceptor's loop-guard moved from a config property to a header marker.
    • Note: react-query v3 here — a disabled query is 'idle' (not isLoading), so the v4/v5 "disabled-query isLoading" trap doesn't apply.

Notes

  • The other ~50 GET read routes could also adopt 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.

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.
@vercel

vercel Bot commented Jun 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
castora Ready Ready Preview, Comment Jun 22, 2026 10:54am

@arcabotai
arcabotai merged commit 3f9a7fb into main Jun 22, 2026
6 checks passed

This branch was successfully deployed

1 active deployment
Preview — 4da9a3a7 Deployed Jun 22, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants