Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

lazily-spec

Language-agnostic wire protocol specification for the lazily reactive signals family.

This site is the rendered companion to the lazily-spec repository. It defines the canonical message schemas shared across every lazily implementation:

  • lazily-rs (Rust)
  • lazily-py (Python)
  • lazily-zig (Zig)
  • @lazily/signaling (TypeScript / Cloudflare Worker)

Cell Model

Upstream of every transport, the Cell Model fixes how a cell’s value converges. A cell is either single-writer (local/direct, no merge) or multi-write, and a multi-write cell carries a pluggable merge: <mechanism> attribute. CRDT is the first multi-write merge mechanism (merge: crdt), not the only one — lww, ot, lease, and custom are reserved alongside it. All transports below carry cells classified by this model.

Protocol Layers

LayerSpecSchema
IPC (Snapshot + Delta)Wire Protocol § IPCsnapshot.json, delta.json
Cross-language FFIWire Protocol § FFIffi.json
Signaling (WebSocket)Wire Protocol § Signalingsignaling.json
Distributed (CRDT)Wire Protocol § Distributeddistributed.json
Capability negotiationWire Protocol § Capability Negotiationinline

Every layer in this matrix is required of every binding. The Distributed CRDT row and the required keyed cell collections layer are unconditional. The C-ABI FFI row is required by default with a narrow platform carve-out (a binding whose runtime cannot host a native in-process C ABI — e.g. browser/Worker JS — declares ffi = none and interops over the wire instead). The thread-safe and async reactive contexts are required where the platform supports them (a platform that structurally lacks threading or suspendable async declares thread_safe = none / async = none); the shared-memory payload path is required where the platform supports it, with an I/O-channel fallback (Inline payloads over IPC/WebSocket/WebRTC) when it does not. See the Binding Conformance Matrix for the full MUST/MAY breakdown and the carve-out terms.

Wire Format

All messages use JSON with serde-compatible tagging ("type" discriminant). Future binary codecs (bincode, postcard, protobuf) encode the same schemas — the JSON representation is normative.

Schema Format

Schemas are provided as JSON Schema (Draft 2020-12). Each implementation must validate against these schemas. See JSON Schemas.

Scope & non-goals

This repo extracts the cross-language, wire-protocol, and behavioral sections from lazily-rs/SPEC.md into a standalone reference. Every lazily-rs feature area is accounted for here exactly once: either normatively specified (with a link below) or explicitly marked Rust-specific. Rust-specific internals remain in the Rust crate and are intentionally out of scope.

Covered (normative, cross-language)

lazily-rs areaSpec
Cell / Slot / Effect / Signal (reactive core)Reactive Graph, Cell Model, Wire Protocol § Eager Signals
ReactiveMap (CellMap / SlotMap, keyed collections)Cell Model § Keyed cell collections
CellTree (ordered keyed tree)Cell Model § Ordered keyed tree
reconcile (LIS keyed reconciliation)Cell Model § Keyed reconciliation
SemTree (memoized semantic tree)Cell Model § Memoized semantic tree
stable_id (manufactured text identity)Cell Model § Manufactured identity
TextCrdt (free-text CRDT + re-parse)Cell Model § Free-text CRDT
SeqCrdt (move-aware sequence order)Cell Model § Move-aware sequence order
Tombstone GCCell Model § Tombstone garbage collection
StateMachine (flat FSM)State Machine
StateChart (Harel/SCXML)State Charts
ThreadSafeContext (thread-safe reactive graph)Reactive Graph § Context layers, Wire Protocol § Concurrency layers are required
AsyncContext (async reactive graph)Async Reactive Context, Wire Protocol § Concurrency layers are required
IPC Snapshot/Delta + ShmBlobArenaWire Protocol § IPC, Wire Protocol § Shared-memory payload path is required, Conformance Fixtures
FFI boundaryWire Protocol § FFI, ffi.json
Signaling (WebSocket)Wire Protocol § Signaling, signaling.json
Distributed CRDT plane (CrdtSync/WireStamp)Wire Protocol § Distributed, distributed.json
Permission boundary (RemoteOp/PeerPermissions)Wire Protocol § Permission Boundary
Capability negotiationWire Protocol § Capability Negotiation
Transport abstraction (IpcSink/IpcSource/DataChannel)Wire Protocol § Cross-language channels

Out of scope (Rust-specific implementation)

These lazily-rs features are implementation choices, not cross-language contracts. Other bindings pick their own; they MUST meet the normative contracts above but need not mirror Rust’s approach.

lazily-rs areaWhy out of scope
Context / ThreadSafeContext lock strategy (ReadStrategy, inline seqlock, typed cache fast-path)Internal scheduling/locking; each binding picks its own concurrency strategy. The existence of the thread-safe and async context surfaces is required where the platform supports it (Wire Protocol § Concurrency layers are required); only the lock internals are out of scope
SlotId internal representationVolatile internal handle; the wire-stable identity is NodeId / NodeKey
instrumentation (lock-site tracking)Rust diagnostics
str0m_backend / str0m_netConcrete Rust WebRTC backend (str0m crate); only the transport abstraction is cross-language
Performance benchmarksRust-specific measurement
lazily-serde type-erasure internalsRust serialization approach; the wire shape, not the codec implementation, is normative

Versioning

Protocol versioning follows the IPC capability negotiation: each session exchanges { protocol_id, protocol_major_version, codec } before any graph state flows. A major version bump is a breaking change; minor additions are additive.