Raw seat tokens no longer touch disk or long-lived memory: rooms store
sha-256 hashes, joins compare timing-safely, sessions keep the raw
token they authenticated with only for minting transfer phrases, and
legacy plaintext room files still load (hashed on read). Verified:
rejoin and transfer both work, and the room file contains only
hostTokenHash — no raw token anywhere.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every room is now an append-only JSONL file (data/rooms/CODE.jsonl):
a birth-certificate meta line, then every join, start, and command.
Because the engine is deterministic, seed + log IS the game — on boot
the server replays each file and reconstructs the exact state, hands,
deck order, and chronicle. Verified live: create, join, play, KILL
the server, restart ("restored 1 room(s) from disk"), rejoin with the
seat token — identical positions, deck count, and hand, with the
chronicle history redelivered redacted per player. The client
remembers its seat (name, room, token) in localStorage and walks back
to the table automatically on connect, clearing the memory if the
seat is stale; a quiet "leave table" control forgets it on purpose.
This is the foundation phase 2 (play-by-turn) sits on: games now wait
indefinitely for their players — and debugging restarts cost nothing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>