4.0 KiB
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:
{"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.move:{"direction":"north|east|south|west"}. Only a player in an active, unpaused match may submit movement intent.drop_key:{}. Only a player in an active, unpaused match may submit the key-drop intent.restart:{}. Only connected Player 1 may reset a finished match, and both players must be connected. Sessions are preserved while a new authoritative maze and game state are created.heartbeat:{}after a session has been joined or restored.
Server messages
session: the private role result containingrole,slot, and temporarytoken. 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 monotonicstartedAtMsandactivationAtMsvalues. It is sent to both players.active: the exact authoritative activation instant.view: a bounded chunk of a role-specific authoritative game projection. Observer chunks contain the complete maze and both player records, including their connection state; player chunks retain the fog-of-war boundary.pause: identifies the disconnected player slot and its monotonic reconnect deadline.resume: reports that both players are attached and authoritative gameplay has resumed.match_result: reports the terminal winner or draw.reset: reports the authoritative return from a finished match to the waiting lobby.ack: successful heartbeat correlation.error: a stable Englishcodeand Russian player-facingmessage.
An observer session can receive snapshots but cannot issue start, move, or
drop_key; attempts are rejected with read_only where applicable and logged
by the gateway. Player tokens reserve their original slot after disconnection
so a refresh can restore it. A player disconnect pauses the game for at most 60
seconds; restoration reattaches the same state, while expiry produces a draw.
A disconnected observer token may be restored until its bounded slot is reused
by a new observer, and observer disconnects never pause the match.
Runtime diagnostics
GET /diagnostics returns bounded operational counters and internal-memory
samples without exposing session tokens, Wi-Fi credentials, or hidden maze
state. Counters cover connection and queue high-water marks, sent/dropped/
failed messages, malformed and rate-limited input, accepted game commands,
match cycles, maximum WebSocket handler/send duration, and current/minimum
internal free heap and largest block. The response also publishes the fixed
limits used by the Milestone 010 physical stress client.