When the operator has a valid HttpOnly catalyst_session cookie but no
JS-side `catalyst:authed` sessionStorage marker (fresh tab, refresh
after sessionStorage cleared, deep-link paste into a fresh window),
the synchronous rootBeforeLoad gate redirected them to /login despite
holding a valid session. Caught on console.omantel.biz when deep-link
loads of /dashboard from a sibling tab kept bouncing back to the PIN
page even after a successful PIN verify in another tab.
Root cause: hasCatalystSession() reads sessionStorage only — the
catalyst_session cookie is HttpOnly so JS cannot see it. The marker is
set by VerifyPinPage on PIN verify and SovereignConsoleLayout on
whoami 200, but a fresh-tab navigation neither runs VerifyPinPage nor
mounts the layout before the gate fires, so the gate never sees the
operator as authed.
Fix: keep the sync fast-path (marker present → allow), but on missing
marker fall through to an authoritative GET /api/v1/whoami. On 200
cache the marker and allow through. On 401 redirect to /login with
deep-link preserved as ?next=. On 5xx/network error fail open so the
layout's own probe surfaces the failure with proper context.
Per memory feedback_per_issue_playwright_verification.md: live-verified
the full PIN flow + 6 deep-link routes (/dashboard, /cloud, /apps,
/jobs, /users, /settings) on console.omantel.biz both before and after
the fix. The closed-session hard gate
(session_2026_05_09_closed_unverified.md) is satisfied: incognito
PIN flow → /dashboard renders fully + 5 sibling surfaces render.
Files:
- products/catalyst/bootstrap/ui/src/app/auth-gate.ts
+ probeWhoamiAndCacheMarker(): authoritative async cookie check
- products/catalyst/bootstrap/ui/src/app/router.tsx
rootBeforeLoad async; falls through to whoami probe when marker missing
- products/catalyst/bootstrap/ui/src/app/auth-gate.test.ts
+5 tests covering 200/401/5xx/network/credentials-include
Refs: qa-loop iter-2 cluster spa-route-guard-rejects-pin-session
Refs: session_2026_05_09_closed_unverified.md
Co-authored-by: hatiyildiz <hati.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>