OCBC 2FA login not restored after page refresh (deployed)
Goal / bug¶
On the DEPLOYED web app, after completing the OCBC Velocity 2FA handshake (login), a PAGE REFRESH does not return the user to the connected account view β the connection appears lost on reload. Find the root cause (session persistence vs status-check-on-mount vs a deployed-only serverless/cookie issue) and where the fix belongs.
Root cause β CORRECTED (2026-06-13) + FIXED¶
The first diagnosis (empty orgId/userId) was a RED HERRING β those fields are never
consumed by the OCBC API calls (grep of pages/api/ocbc + lib/ocbc found no reads; the
calls use accessToken + cookies + e2eeKeys). The REAL cause is a serverless load-once
cache: lib/ocbc/velocity-session-store.ts loadSessionsFromFirestore() loads ALL
sessions once and sets globalThis.__velocitySessionsLoaded = true, then
if (sessionsLoaded) return forever. On Vercel a warm lambda that ran that load BEFORE
the 2FA session was written never re-reads it β on refresh a different warm instance
reports "not connected" even though the session IS in Firestore. Matches "works right
after 2FA, lost on refresh" exactly.
FIX (committed): getVelocitySessionAsync / hasValidVelocitySessionAsync now do a
direct PER-USER Firestore read (loadOneSessionFromFirestore(userId): doc(userId).get β
decrypt β expiry-check β cache) instead of trusting the load-all-once cache. Typecheck
clean. Could not browser-verify (needs a live OCBC 2FA session) β owner to confirm on deploy.
Cosmetic leftover (NOT the bug): orgId/userId still '' at login.ts:148-149 β unused, left
as-is. expiresAt is 30 min β fine for now; widen later if longer sessions are wanted.
Log¶
- 2026-06-13 created + investigated. FIRST diagnosis (empty orgId/userId) was WRONG β corrected to the load-once session cache. Fixed via per-user Firestore read; typecheck clean. Awaiting a deploy to confirm live.