SESSION-CARRYOVER — Students never log in twice

Decided by Ravneet, 6 Oct 2026: when Cetking moves to the new Vercel app, a student who is logged in today must not have to log in again, and a student who comes back the next morning must be logged in automatically.

Read with AUTH-CONTRACT.md (how login works today).

Step 0 — The Universe moves to https://ai.cetking.com (10 Oct 2026)

Decided by Ravneet, 10 Oct 2026: WordPress is not used for the Universe at all. The Universe lives on Vercel at ai.cetking.com now; later cetking.com itself moves to Vercel.

  • Live since 10 Oct 2026 (PR #179). The same day Ravneet chose to keep cetking-platform.vercel.app live as well (old links), so the forward to ai.cetking.com was removed again (PR #181). See RELEASES.md.
  • Nothing else in the code names the site address: login, OTP, Google callback and the same-origin check all use the address the request came in on.
  • Done by Ravneet: Vercel → Domains → Add Existing ai.cetking.com (Production); DNS for cetking.com is on the webhostbox hosting (cPanel → Zone Editor): CNAME ai → c0f1d52d4114c068.vercel-dns-017.com.; Supabase Auth → Redirect URLs → added https://ai.cetking.com/api/auth/google/callback?ck_state=* (Google login on ai.cetking.com tested OK, 10 Oct 2026).
  • Students: IDs, coins, profiles and ticks are all in Supabase, untouched. Anyone logged in on the old vercel.app address logs in once more on ai.cetking.com (a browser never sends a cookie to a different address).
  • The login cookie stays __Host-ck_session (this address only). It is deliberately NOT widened to all of .cetking.com: today the WordPress cetking.com server would then receive every Universe login. When cetking.com moves to Vercel (our own app on both addresses), a one-time silent hop between ai.cetking.com and cetking.com carries the login over — no WordPress needed.

Step 1 — Rolling login on the Universe (built 6 Oct 2026)

Status: live since 6 Oct 2026 (PR #144).

Before: every Universe login ended after 30 days even for daily users, and after 7 days without a visit.

Now: once a day, a returning student's login is quietly swapped for a fresh 30-day one. A student who visits at least once a week never sees the login screen.

  • Database (Cetking Learn): public.ck_identity_renew(p_old_token_hash, p_new_token_hash), service role only. Migrations ck_identity_session_renew, ck_identity_sessions_allow_renewed_reason (adds 'renewed' to revoked_reason).
  • Rules inside the function: only active, non-shared sessions at least 1 day old are swapped; the new session copies person, student, device and login method; the old token keeps working for 2 minutes (so a second open tab is not logged out) and is marked renewed so it can't be swapped twice; each swap writes session_renewed to ck_identity.audit_log.
  • Shared-computer logins are never renewed (they still end after 12 hours).
  • Logout, device limit (5) and the 7-day idle rule are unchanged.
  • Site: lib/identity/renew.ts, app/api/auth/renew/route.ts (POST, same-origin only), called once per browser tab by components/auth/NavAccount.tsx after it confirms the student is signed in. Tests: tests/identity/renew.test.ts.
  • Tested in the database on a made-up session (all undone): swap ✓, second tab no double swap ✓, old token valid 2 min ✓, new token ✓, fresh login left alone ✓, new limit 30 days ✓.

Step 2 — Carry cetking.com logins into the new app (plan, not built)

The one fact that decides everything

A browser sends a login cookie only to the exact address that created it. A cetking.com cookie is never sent to cetking-platform.vercel.app, and no code can change that. Moving the database is not the problem: identity, students and coins already live in one place (Cetking Learn), so nothing is copied.

The plan: same address, same cookie, same database check

  1. Audit first (no guessing). Read the cetking.com plugin (plugins/cetking-one, branch chatgpt/cetking-one-welcome-campaign) and the ck_one_auth database functions. Write down the exact cookie names, flags, lifetimes, and the database function that checks a cookie. Confirm the live plugin version (0.6.2 recorded vs 0.6.4 in code).
  2. Teach the new app to read the old cookie. When a request arrives with no Universe session but with a valid cetking.com session cookie, the new app checks it through the same database function cetking.com uses (hash only, never stored in plain), then opens a normal Universe session for the same person. The student sees nothing.
  3. Test on a hidden address on cetking.com (for example a test sub-address) with Ravneet's pilot number, logged in on the old site first.
  4. Move cetking.com to the new app (DNS to Vercel). The browser keeps sending the existing cookie to cetking.com, the new app accepts it, everyone stays logged in.
  5. Keep reading the old cookie for at least 60 days after the move, then retire it.

Until cetking.com moves: optional "silent hop"

If students should share one login before the move, add a small cetking.com endpoint that, for a logged-in visitor, issues a one-time, 60-second pass and sends the browser back to the Universe, which trades the pass for its own session. The student sees a brief flicker, never a login screen. Needs a WordPress plugin change (ChatGPT uploads plugins). The pass is single-use, hashed in the database, bound to the Universe address, and never placed in a visible link longer than one hop.

Rules that must not break

  • One person, one permanent ID, one wallet (AUTH-CONTRACT.md). Carrying a login never creates a new person or student.
  • Never loosen cetking.com's refusal of requests from other websites; the hop is a redirect the student's own browser makes, not a cross-site call.
  • Never copy cookie values into the database, a link or a log. Hashes only.

Known risks (so nobody is surprised)

  • Students who cleared their browser or changed phones log in once with OTP — unavoidable on any site.
  • Old Arena login bridge (legacy_until) ends 10 Oct 2026, ~04:20 IST. After that, old Arena logins must sign in again with OTP. If that is not wanted, ChatGPT must extend it before then.
  • A mistake in step 2 would log people out, which is why it is tested on a hidden address first.

Source: GitHub cetking-one/docs/SESSION-CARRYOVER.md. Edit the file there; this page updates on the next release.