The 140+ operation WebSocket API: message framing, JSON and binary codecs, connection lifecycle, subscription model, and rate limiting — the complete integration surface for building clients and tools.
Xudanu's wire protocol is a WebSocket-based request-response protocol with server-push subscriptions. Every operation has a typed request and response, identified by a numeric operation code.
The protocol is defined in src/server/transport/protocol.rs (~2,969 lines) with codecs in codec.rs (~2,902 lines) and dispatch in dispatch.rs (~2,667 lines). Together these ~8,500 lines define the entire API surface.
/ws?version=2 query parameterEvery message follows a consistent structure:
{
"op": "work_list", // Operation name
"request_id": 42, // Client-assigned correlation ID
"payload": { ... } // Operation-specific parameters
}
Responses echo the request_id and include a value or error:
{
"op": "work_list",
"request_id": 42,
"value": {
"works": [
{ "work_be_id": 1004, "title": "Alice's Document", ... }
]
}
}
The 140+ operations are organized into these categories:
| Category | Example Operations | Op Code Range |
|---|---|---|
| Session | Login, logout, public login, session info | 0x0001–0x000F |
| Work CRUD | Create, list, get, delete, search, outline | 0x0100–0x011F |
| Edition / Content | Get edition, revise, get text, goto, search content | 0x0200–0x021F |
| Club Management | Create club, name club, add/remove members, set credential | 0x0300–0x031F |
| Stars / Favorites | Star, unstar, is starred, starred list | 0x0335–0x0337 |
| Trails | Create, delete, rename, add stop, remove stop, reorder, list, get | 0x0339–0x0340 |
| Document Map | Work graph (nodes + edges for visualization) | 0x0338 |
| Transclusion | Content watch, find content, shared content, content match | 0x0400–0x041F |
| CRDT Sync | Text delta, awareness update, sync session | 0x0500–0x051F |
| Links & Labels | Create/delete link, get links, set/get label | 0x0600–0x061F |
| Blobs | Upload, get, info, exists, stats | 0x0700–0x071F |
| Annotations | Create, delete, list, update annotation | 0x0800–0x081F |
| Endorsements | Endorse, unendorse, list endorsements | 0x0900–0x091F |
| Federation | Add/remove peer, federated query, replicate | 0x0A00–0x0A1F |
| Governance | Propose, vote, seal, get proposals | 0x0B00–0x0B1F |
| Attribution | Get attribution, verify attribution log | 0x0C00–0x0C1F |
| Versioning | Get revision, revision count, compare revisions | 0x0D00–0x0D1F |
| LLM | Narrate diff, auto-title, writing feedback | 0x0E00–0x0E1F |
| Admin | Preflight check, verify log, checkpoint | 0x0F00–0x0F1F |
The protocol supports two wire formats:
Human-readable, easy to debug. Used by the web UI and third-party integrations. Messages are UTF-8 text frames.
{
"op": "work_star",
"request_id": 7,
"payload": {
"work_be_id": 1004
}
}
Compact, fast. Uses postcard serialization (serde-compatible) with LEB128 varint encoding. Messages are binary WebSocket frames. Typically 3-5x smaller than JSON.
[varint: op_code] [varint: request_id] [postcard: payload]
Figure 1: WebSocket connection lifecycle from upgrade through authentication to active session and cleanup.
Beyond request-response, clients can subscribe to real-time events:
| Subscription | Trigger | Push Data |
|---|---|---|
| Status | Work created, deleted, or metadata changed | Work list update |
| Revision | Work content revised by any session | New revision number + text delta |
| Fill | Recorder triggered (transclusion match found) | Fossil ID + matched content |
| Content Watch | New content matching watched fingerprints | ContentMatch with work/edition info |
| Awareness | Another user's cursor/selection/typing state changes | OtreeAwarenessState relay |
--csrf-token flag)catch_unwind to prevent server crashes from client requests