Rebasely Beta: data may be purged

examples/live-notes Public

Markdown · 1.6 KiB · at 70b1506

id: wire-protocol
type: concept
owner: justin
reviewed: 2026-10-14
component: ops
describes:
  - src/protocol.ts

Wire protocol

Editors and a room exchange JSON text frames over the WebSocket at /notes/:id/ws. Versions are the room's: the number of ops it has applied to the note.

From an editor:

{ "type": "op", "base": 41, "op": { "type": "insert", "pos": 4, "text": "oat " } }
{ "type": "op", "base": 41, "op": { "type": "delete", "pos": 0, "count": 3 } }

From the room:

type fields when
snapshot text, version, reason on connect, and when an editor's op can't be used
ack version your op was applied, or turned out to change nothing
op version, op someone else's op, already transformed
error message the frame was not an op message

reason is only set when the room refused an op the editor had already applied, for example one that would take the note past 100,000 characters. The page shows it in the status line.

parseClientMessage() checks every field and copies only the ones it knows, so a frame with extra fields still works and a malformed one is answered with error and changes nothing.

An editor sends its next op only after the ack for the previous one; see [[conflict-strategy]] for why that keeps the room's job simple.