The Wire
decided in shape, draft in detail.
The Wire half of XTXP defines how operations get from one node to another. It is a small sync protocol that doesn’t depend on any one transport, plus a few bindings that carry it.
What the core needs from a transport
Section titled “What the core needs from a transport”Very little. Xmesh operations can be applied in any order, and applying one twice does no harm. So a transport only has to deliver operations eventually, at least once, in any order. It doesn’t need ordering guarantees, exactly-once delivery or a durable message queue.
Recovering from a dropped connection is part of XTXP itself, not something borrowed from the transport:
Messages
Section titled “Messages”The sync messages follow the Yjs sync protocol. XTXP adds its own messages for identity and access alongside them.
One wire format, to start
Section titled “One wire format, to start”draft · enough to build M1 on; needs further work (decision 21)
- Peers exchange Yrs binary updates, in Yrs’s v1 encoding, inside XTXP frames. v1 is Yrs’s default, and what the Yjs sync protocol and y-sweet speak. The more compact v2 encoding is a later optimisation.
- XML Patch never travels between peers. It’s how edits come in from a UI or go out to a tool (see The Math).
- HTTP is for browsers. A client that wants the live stream asks for a WebSocket upgrade on the same address.
| Message | Purpose | Stored? |
|---|---|---|
hello / challenge / prove |
Authenticate a connection by public key. The proof signs the host, session and nonce under a domain tag. See Identity and access. | No |
bind |
Signed: “public key P owns client ID 7 on this session.” | Yes |
sync-1 |
“Here is my state vector.” | No |
sync-2 |
“Here are the operations you’re missing.” | Yes, as operations |
update |
New operations, as they happen. | Yes |
grant / revoke |
Signed changes to who may read or write a session. | Yes |
awareness |
Cursors, selections, presence, tied to the authenticated connection. Fire-and-forget, overwritten, never archived. | No |
Cursors and presence travel separately from operations. A 60 Hz cursor stream should never be archived, wrapped in anything heavy, or replayed to a late joiner.
Bindings
Section titled “Bindings”| Binding | Used by | Notes |
|---|---|---|
| WebSocket, binary frames | Wasm muppets in the browser, the Inkscape fork, CLI peers | The primary binding, chosen for raw speed. Hosts serve it directly. |
| HTTP forms and redirects | Browsers with no JavaScript, through a server-side muppet | See Addressing. |
| XMPP, through a bridge | Mobile and chat clients such as Conversations, and federation | A bridge in front of a host, not the core transport. |
The XMPP bridge
Section titled “The XMPP bridge”XMPP is good at things a browser tab isn’t: holding messages while a phone sleeps, waking it with a push, and fitting into chat apps people already use. The bridge keeps those strengths for the clients that need them:
- XEP-0198 stream management and XEP-0313 message archive for flaky mobile links
- XEP-0352 client state and XEP-0357 push, to save battery
- chat interop: canvas comments mirrored as room messages, and replies turned back into comments (open question 7)
- OMEMO end-to-end encryption for rooms that want it
Behind the bridge, everything is ordinary XTXP to a host. Inkboard’s old problem of XML getting damaged inside XMPP stanzas is now one bridge’s concern, not the core wire format’s (see prior art).
Encryption
Section titled “Encryption”Every binding runs over TLS. A session can also be end-to-end encrypted, so that its host only sees ciphertext. The host can still admit operations, because client bindings and grants are metadata it can check. It can’t compact the session into a full state or render previews, though, so those move to the clients. A server-side muppet can still take part as one of the user’s own devices.
Still open
Section titled “Still open”- How XTXP’s own messages (identity, grants) are framed alongside the Yjs sync messages.
- The wire format as a whole: decision 21 is a starting point to build on, not the final word.
- Whether
xtxp://names the WebSocket binding directly, or resolves to it through a muppet disco. - How the XMPP bridge is built: for example as a component plugged into an existing XMPP server, speaking XTXP to a host.