Real-time multi-user editing with O-tree CRDT, Ed25519-signed author attribution, awareness state (cursors/selections), automatic three-way merge fallback, and LLM-assisted change narration.
Xudanu supports real-time collaborative editing: multiple users can edit the same document simultaneously, seeing each other's changes live. The system is built on an O-tree CRDT (Conflict-free Replicated Data Type) with Ed25519 cryptographic attribution for every character.
The implementation lives in src/server/otree_crdt.rs (~2,030 lines) and provides:
The OtreeCrdt struct manages collaborative editing state for all works on the server. Each work has its own CRDT "document" that tracks:
When a client sends a text edit, the CRDT applies it as a delta:
TextDeltaOp with the full replacement textEvery edit creates a new revision. The CRDT maintains:
revisions: HashMap<BeId, Vec<String>> — per-work revision historycached_text: HashMap<BeId, String> — memoized current textwork_authors: HashMap<BeId, HashMap<SessionId, OtreeAuthorIdentity>> — per-session author trackingAwareness is the real-time presence system. Each editing session broadcasts its state to all other sessions on the same work:
| Field | Type | Purpose |
|---|---|---|
session_id | u64 | Unique session identifier |
user_name | String | Display name |
cursor | Option<OtreeCursorPosition> | Cursor position (character index) |
selection | Option<OtreeSelectionRange> | Selected text range |
is_typing | bool | Whether the user is actively typing |
club_id | Option<BeId> | The user's personal club |
author_public_key | Option<Vec<u8>> | Ed25519 public key for attribution |
When a session updates its awareness, the server relays it to all other sessions editing the same work via OtreeAwarenessRelayResult, which contains the list of (SessionId, OtreeSyncSessionId) pairs to notify.
Every edit is cryptographically signed. The OtreeSignedUpdate contains:
update_text — the new document contentsignature — Ed25519 signature over the textsigner_public_key — the author's 32-byte public keyThe OtreeAuthorIdentity struct ties the public key to a human-readable name and club:
public_key: [u8; 32] — Ed25519 verifying keydisplay_name: String — shown in attribution panelclub_be_id: BeId — the author's personal clubAuthors are classified into types that affect attribution coloring in the UI:
Direct user input, signed with the user's club key. Shown in green in the attribution panel.
AI-generated text from Ollama/OpenRouter. Signed with the server's key. Shown in purple.
Imported texts (Project Gutenberg, etc.). Signed with the importing user's key. Shown in amber.
Content without provenance. Occurs in legacy data or anonymous edits.
When CRDT state diverges beyond what can be reconciled (e.g., two users make conflicting edits to the same paragraph), the system falls back to three-way merge:
LastWriterWins strategy (based on timestamp)The three-way merge engine (src/edition/three_way.rs, ~1,889 lines) produces:
Edition combining both inputsMapping objects showing how positions in each input map to the merged resultThe CRDT integrates with the LLM subsystem (src/server/ollama.rs) for:
LLM-appended text is attributed with a separate OtreeAuthorIdentity marked as LLM type, ensuring the attribution panel correctly shows it in purple.
Figure 1: Collaborative editing protocol. Edits flow through the server with attribution; awareness is relayed between sessions.
| Aspect | Udanax-Gold | Xudanu |
|---|---|---|
| Concurrency model | Single-user; grab/release locks with queuing | Multi-user CRDT with awareness state |
| Conflict resolution | Manual: last writer wins by default | Automatic: three-way merge with LWW fallback |
| Attribution | Club-based ownership of entire works | Per-span Ed25519-signed attribution with author types |
| Real-time updates | Poll-based; no push notifications | WebSocket relay for edits and awareness |
| Version history | Flat revision list per work | Same, plus revision diffing and comparison |
| AI assistance | None | Ollama/OpenRouter integration for narration and auto-titling |