🪪 Identity

Lifecycle: CURRENT
Guest-first Nakama identity with one request-boundary owner and one versioned cookie pair is the platform rule.
Dual-corpus note: older material under dev/docs/content/_attic/legacy-wiki-funday-gg/ is historical and Quartz-ignored.

Request lifecycle

frontend/src/hooks.server.ts is the only ordinary-request identity owner. It delegates to resolveRequestIdentity() before route code runs:

  1. Parse funday-identity v1 and the independent funday-device-id recovery cookie.
  2. Require agreement among JWT claims, session user ID/username, account ID/username, and the owned device.
  3. Hydrate or refresh the existing Nakama session; otherwise restore the same device.
  4. Create a guest only after Nakama explicitly reports device_not_found.
  5. Populate event.locals; routes consume those locals instead of parsing cookies or provisioning identity.

Both cookies use Path=/, HttpOnly, SameSite=Lax, a one-year maximum age, and Secure on HTTPS. SvelteKit subrequests may hydrate a valid canonical identity, but they never provision, reconcile, rotate, or write identity cookies. The sole explicit rotation path is /api/auth/ensure-session?fresh=1.

Nakama unavailability is an explicit 503. There is no local_fallback, synthetic account, or degraded identity success.

Mutation rule

Identity mutations are paired and sequential, not a cross-system transaction:

  1. Update the Nakama account.
  2. Rewrite the complete validated funday-identity + funday-device-id pair.

A failed Nakama write must not mutate local identity or report success. Evidence: frontend/src/routes/api/user/display-name/+server.ts, frontend/src/routes/api/user/username/+server.ts, and frontend/src/routes/api/user/avatar/+server.ts.

Handles

  • New guest username and initial displayName values use the same alphabetic three-word name from a measured 30,483,706-name namespace. Device-derived collision attempts remain alphabetic and never append numeric/hash suffixes.
  • Guest usernames are fixed policy. Registered users may change username through the username API.
  • displayName remains a mutable persona value.

Profiles and leaderboards

  • /profile without userId resolves the authenticated viewer. A supplied ID must be a valid real Nakama user: malformed targets return 400, missing users return 404, and dependency failure returns 503; the viewer is never substituted.
  • Profile activity and friend data call shared server-domain helpers directly. Same-app HTTP self-fetches are prohibited.
  • Leaderboard IDs/defaults come from game manifests. Reads use the isolated Nakama system-reader session. Empty boards, unavailable boards, and unknown IDs are distinct; mock leaderboard rows are prohibited.

Source inventory: funday-codex.yml under identity.

ClaimProof
Single request-boundary owner and subrequest no-write lawfrontend/tests/unit/hooks.identity.test.ts, frontend/src/lib/server/auth/requestIdentity.test.ts
Versioned pair validation, migration, and token-claim agreementfrontend/src/lib/server/identityCookieHelper.test.ts, frontend/src/lib/server/auth/sessionHydration.test.ts
Device restore/create boundary and collision policyfrontend/src/lib/server/auth/guestSessionEngine.test.ts, frontend/src/lib/utils/usernameGenerator.test.ts
Stable browser identity across reloads/routes/tabs and distinct contextsfrontend/tests/e2e/identity-persistence.spec.ts
Real target profile status lawfrontend/src/routes/profile/page.server.test.ts
Manifest-derived Nakama leaderboard readsfrontend/src/lib/server/leaderboards.test.ts, frontend/src/routes/api/leaderboards/[id]/server.test.ts
Isolated system-reader lifecyclefrontend/src/lib/server/auth/systemSession.test.ts
Custom Node adapter preserves repeated Set-Cookie headersfrontend/server/requestOrigin.test.ts

Ask Docs

AI assistant to help answer questions about the documentation. Answers are read-only and cite docs/source.

Hi! How can I help you with the documentation today? Answers are read-only and cite docs/source.

Ctrl+Enter to send