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

A seat in the sea: decide what one is, before `join` invents it #57

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`docs/wake.md` gains a section, **A seat**, that decides admission before `join` exists: a seat is a mote, and it belongs to the player key from #6 — the forge id, or the guest id derived from the HttpOnly cookie — and explicitly never an address, since behind the forge every guest arrives from the forge's. `SEATS_PER_PLAYER` is 1, so a second connection under one key steers that key's own mote ra…

shipped production is serving it deploy feb7d92

opened this

docs/wake.md gains a section, A seat, that decides admission before join exists: a seat is a mote, and it belongs to the player key from #6 — the forge id, or the guest id derived from the HttpOnly cookie — and explicitly never an address, since behind the forge every guest arrives from the forge's. SEATS_PER_PLAYER is 1, so a second connection under one key steers that key's own mote rather than being refused; a request carrying no session gets no mote (join believes only a key the request already carried, never one minted on the way out); signing in releases the guest seat in the same tick the forge id takes one, inheriting the mote's place and momentum. A seat is held by swimming: IDLE_SECONDS = 60 for one that stops being steered, UNSTEERED_SECONDS = 20 for one never steered at all. The overflow answer is stated once for both the cap and the per-key rule — the 25th swimmer, the client with no session, anyone arriving into a full sea is a spectator who sees the whole round and steers nothing, told so in a sentence the record quotes and SPECTATOR in src/concept.ts carries word for word.

Three attacks are answered in #38's shape: the cookieless script (it cannot hold a seat at all, and the honest limit is stated — guest keys are free, so twenty-four kept jars that actually swim are twenty-four players and are #38's problem, not the door's), one person with six tabs (one key, one mote, nothing refused), and the walked-away seat (the 60 s eviction #8 already builds to, argued as a third of a round). Invariant 7 — "One key, one seat: the number of live motes never exceeds the number of distinct player keys in the roster" — is appended, never reordered, so #8 and #9 can cite it by number, and the record says where each proves it. The record also pins what the cookie is not: a seat and a handle, and nothing else may ever hang on it.

Worth looking at: the four new rows in the numbers table and the assertions in src/concept.test.ts that hold them, the spectator sentence, and the README's two count fixes ("seven invariants", and the sea's tests prove the invariants about the sea). No round code, no socket code, no page change — how a spectator's page differs is #10's and #11's. bun run test is green (93 pass); the new tests were checked to fail when the record and the module drift apart.

🤖 Generated with Claude Code

Closes #49

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs