feat(lobby): implement bounded WebSocket sessions and countdown

This commit is contained in:
2026-09-04 02:13:26 +03:00
parent b10c7f5972
commit 996bda9567
21 changed files with 2040 additions and 64 deletions
+56
View File
@@ -0,0 +1,56 @@
# maze32 WebSocket protocol v1
## Limits and ordering
- Endpoint: `/ws`.
- At most six WebSocket connections are accepted: two players and four
observers.
- A text frame is at most 512 bytes. Binary frames are rejected.
- Each connection may submit at most 20 messages in a one-second monotonic
window.
- The gateway uses a fixed 12-entry outgoing queue with 768 bytes per entry.
- Client sequence numbers start above zero and strictly increase for the life
of one WebSocket connection. Replayed or decreasing values are rejected.
- Server sequence numbers strictly increase until reboot. Clients discard
stale server messages.
All messages use this envelope:
```json
{"v":1,"type":"message_type","seq":1,"requestId":"optional","payload":{}}
```
Envelope keys may appear in any order except that `type` must precede
`payload`. Unknown and duplicate keys are rejected. `requestId` is optional and
is only echoed for correlation; it grants no authority.
## Client messages
- `join`: `{"role":"player","name":"..."}` or `{"role":"observer"}`.
Player names contain 1–32 UTF-8 bytes, have no control bytes or outer spaces,
and are unique within the current lobby.
- `restore`: `{"token":"32 lowercase hexadecimal characters"}`.
- `suggest_name`: `{}`.
- `start`: `{}`. Only connected Player 1 may use it, and both player slots must
be connected.
- `heartbeat`: `{}` after a session has been joined or restored.
No Milestone 005 maze or movement messages are implemented by this milestone.
## Server messages
- `session`: the private role result containing `role`, `slot`, and temporary
`token`. The token is never included in a shared snapshot.
- `name_suggestion`: an available humorous Russian player name.
- `lobby`: the authoritative phase, revision, readiness, public player slots,
connected observer count, and limits.
- `countdown`: the single authoritative `[3,2,1]` event with common monotonic
`startedAtMs` and `activationAtMs` values. It is sent to both players.
- `active`: the exact authoritative activation instant.
- `ack`: successful heartbeat correlation.
- `error`: a stable English `code` and Russian player-facing `message`.
An observer session can receive snapshots but cannot issue `start`. Player
tokens reserve their original slot after disconnection so a refresh can restore
it. A disconnected observer token may be restored until its bounded slot is
reused by a new observer.