The Gate That Bounced Every Deep Link Before the Profile Loaded
A signed-in user loading /discover landed on the wrong home — because the invite gate decided before the profile existed
Published Nov 5, 2026
Executive Summary
On a cold load, the client builds a session from the auth token before the server profile has been fetched. That incomplete session carries default invite/onboarding flags, and the invite gate compared those defaults as if they were facts. A signed-in fan deep-linking to /discover was bounced /discover → /invite-gate → /audience. The fix marks the session as synced-or-not, never decides the gate on an unsynced session, and retries a failed bootstrap once after 5 seconds.
The Prompt
“Add an invite gate that redirects users who haven't redeemed their invite to the right persona home.”
The Flaw
On a cold load the session is built from the token before the server profile has been fetched, so `inviteRequired` and `inviteRedeemed` hold their defaults. The gate compared those defaults as if they were facts: `inviteRequired` defaulted truthy and `inviteRedeemed` falsy, so `needsInviteGate` fired and routed the user through `/invite-gate`. By the time the real profile landed, the router had already forwarded to the persona home — the requested deep link was lost. The agent treated 'not loaded yet' as 'not authorized'.
Risk & Impact
[Correctness] A signed-in fan loading /discover was bounced /discover → /invite-gate → /audience. Every cold deep link to a protected page landed on the wrong screen until the profile sync happened to win the race.
Cost: Dead deep links and a confusing first-run experience for every returning user on a cold load.
Code Comparison
❌ Vulnerable (AI generated)
❌ Vulnerable (AI generated)
✅ Hardened (production ready)
The Fix
Mark the session as synced-or-not; never decide the invite gate on an unsynced session; retry a failed bootstrap once after 5 seconds and return to the originally requested path.
Prevention
- [manual] Any guard that reads async-loaded state must distinguish 'not loaded yet' from 'not authorized'.
- [ci] E2E tests must cold-load deep links and assert the user lands on the requested route, not the persona home.
Why This Happened
Root cause: the prompt omitted Rule 5 — the guardrails that would have caught this. See the full guide →
