protocol.md · non-normative

Protocol reference

Generated from packages/core/src/net/ by scripts/build-protocol-ref.mjs. Do not edit by hand — regenerate. 05-multiplayer.md MP-180 requires this document to be public, versioned, and "sufficient for third-party clients and self-hosted servers to interoperate", and a reference that drifts from the code is worse for an implementer than no reference at all, because they will build against it.

Version

PROTOCOL_VERSION is 1. Every message carries it in its envelope (MP-260); a receiver that does not speak the offered version refuses the connection rather than negotiating down (MP-1220).

Framing and size

Messages are JSON objects. The transport is WebSocket over TLS, and RFC 6455 framing discharges the message-boundary obligation of MP-260 — the protocol adds no length prefix of its own. A stream-oriented transport added later must define its framing here.

The maximum accepted message size is 4,194,304 bytes, stated here because MP-260 requires it "stated in that reference and derived from the largest legitimate payload class — an observation stream (MP-240) or an AR-500 ViewCheckpoint — rather than left as an unstated implementation constant". It is checked before the payload is parsed: an over-long message is refused without being decoded, because a receiver that parses first to find out how big something was has already done the work the limit exists to prevent.

A malformed, truncated, or over-long message is refused with a typed rejection (below) and never parsed partially.

Authority modes

What a client may receive depends on the mode. Authoritative-mode clients never receive the canonical order log, RefereeView data, or full-state snapshots under any circumstance — including fast start and reconnection, even on explicit request (MP-250). A RequestSnapshot from such a client is answered with a ViewCheckpoint (MP-270).

Upstream — client to authority

Message Fields beyond kind
Hello protocol, engine
Auth token
JoinGame (none)
ClaimSeat seat
LeaveGame (none)
Resume lastMsgSeq
SubmitOrders turn, seat, orders, clientBatchId
CommitOrders turn, seat
RevokeCommit turn, seat
ActivationOrderHash turn, hash
TurnHash turn, hash
RequestCheckpoint (none)
RequestSnapshot (none)
Chat text, to
LobbyChat text
RequestLobbyInfo (none)
Ping nonce
Concede turn, seat

No client may submit anything during the Cascade or the Reckoning; the authority refuses what arrives and does not queue it (MP-235). Session plumbing and the pre-Cascade digests cross that boundary; a submission does not.

Downstream — authority to client

Message Fields beyond kind
GameInfo mode, protocol, engine, rulesVersion, viewSchema, initiativeTier, contentHashes, seats, aiSeats, game
PhaseBegin turn, phase
OrdersClosed turn, commitMarkers
Observations turn, events
ViewCheckpoint turn, viewHash, view
ViewDelta turn, baseViewHash, viewHash, delta
OrderResults clientBatchId, results
ActivationOrderHash turn, hash
TurnHash turn, hash
Presence seats
ChatRelay from, text, turn
LobbyChatRelay from, text
LobbyInfo listing
Control notice
LogTail records
Snapshot stateHash, state
Rejected reason

The observation stream is one payload per seat per turn, dispatched for every seat together, and an empty stream is dispatched at the same moment as a full one (MP-1125) — a transport that treats "no observations" as "nothing to send" turns silence into a signal.

Typed rejections

Bundle format (infrastructure-free play)

A turn bundle is a file, so bundle mode needs no network at all (MP-080). Phases:

A packet is refused for exactly these reasons, kept distinct because a caller that cannot tell them apart cannot tell a replay attempt from a version skew from a malformed file:

The closer commits to its own packet in the turn-opening bundle and reveals the key only in the closing bundle (MP-845), which makes the closer's unavoidable early sight of every other packet worthless — their own orders were fixed before anyone else's existed.

Server API

Not yet specified: @everylastcity/server does not exist. 03-architecture.md AR-020 names it in the dependency graph, and 08-services-platform.md owns its surface. This section is deliberately empty rather than absent, so that an implementer reading MP-180's three obligations can see which of them this document currently discharges: the wire protocol and the bundle format, and not the server API.


Built from source 47fa2827eff0 · VERSION.json