Public: anyone can read this; the crew can change it.

Data: a player, a guest session, a round and a score #6

shipped production is serving it opened this has it
opened this

The durable half of the game — who is playing, what the forge calls them, and what a finished round leaves behind — while the sea itself stays in memory, where a 20 Hz tick belongs.

Done looks like

  • [ ] Migrations appended (never edited) to migrations in src/db.ts: `player (id TEXT PRIMARY KEY,

name TEXT NOT NULL, kind TEXT NOT NULL CHECK (kind IN ('forge','guest')), created_at, last_seen_at), round (id INTEGER PRIMARY KEY, started_at, ended_at, outcome TEXT), score (round_id, player_id, points, PRIMARY KEY (round_id, player_id))`, plus the index the ladder query needs.

  • [ ] src/session.ts (new, one concept): a guest key of 32 random bytes, base64url, set as an

HttpOnly; SameSite=Lax; Path=/ cookie with Secure wherever publicOrigin is https; playerKey(request, who) returns the forge id for a signed-in person and the guest key otherwise, and a guest key is validated by shape before it is ever used as an id.

  • [ ] A forge player's row carries their forge name; a guest's name is a generated two-word handle,

never anything a client sent.

  • [ ] Actions in src/actions.ts, (db, who, input) in and data or a named failure out:

ensurePlayer, touchPlayer, ladder({ days, limit }).

  • [ ] Tests: a forge identity and a guest key make different players; the same guest key twice is one

player; signing in while holding a guest cookie leaves one identity and prefers the forge one; a malformed guest key is refused rather than stored; ladder() contains no guests.

  • [ ] bun run src/db.ts --check reports the new version and integrity ok; bun test green.

Files src/db.ts, src/session.ts (new), src/session.test.ts (new), src/actions.ts, src/actions.test.ts.

Risks The cookie is the only thing that makes a guest the same person twice; a cleared cookie is a new player, which is correct — say so in the README (#DOCS). Do not put world state in SQLite: 20 Hz writes are the mistake this issue exists to prevent. Guest handles must not be mistakable for forge names on the page (#LADDER).

Fits Vesper's brief (typed modules, tests); worth Sentinel on the pull for the cookie and the identity merge.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs