Skip to main content

Documents and collaborative text

Documents accept structured changes and collaborative plain text into one durable state resource. An editor's tentative change, a mergeable candidate and an accepted revision are distinct states. The fenced writer and current resource policy still decide acceptance; mergeability never grants write permission.

Start with the Document example and service guide. The shared-notebook recipe shows revision-bound field reads. Path/sequence access and separately versioned search/analytical projections are architectural priorities; arbitrary search is not part of the current Document interface. See workloads and performance for the planned structures and measurement limits.

Identities and merge rulesโ€‹

Document identity, replica ID, operation ID, accepted revision and merge epoch are separate from PID or worker generation. Changes name their replica predecessor and explicit observed operation/anchor dependencies. Missing dependencies reject as not accepted; resubmit after obtaining the prerequisite. There is no unbounded hidden pending queue. Reusing an identity for different content conflicts.

Map fields are observed-remove multivalue registers. An assignment removes only the assignments it explicitly observed. Concurrent unseen values remain visible as conflicts; resolution is a new assignment naming the values it replaces. Missing and null are different. No wall clock picks a winner.

Maps, lists and editable text have immutable object identities. Replacement creates a new object. Removing a parent detaches its descendants; concurrent descendant edits remain history but cannot resurrect the removed parent. Move/reparent and cycles are unsupported.

Lists and text use stable element IDs and a predecessor relation, with deterministic descending-ID order for concurrent siblings. Deletion marks the named element; insertion after a deleted anchor remains ordered. Text elements are Unicode scalar values, not graphemes; there is no normalization. A scalar UTF-8 string value is different from growing editable text.

Acceptance and boundsโ€‹

A change contains up to eight operations. Inline strings/binary are limited to 96 bytes, and a field has an eight-unresolved-assignment quota. Refusal does not accept a prefix or silently expire old conflicts. Exact encoding and all bounds are in the Document contract.

Immutable index nodes and change bytes are staged through bounded publication. Only the final validated Document head accepts the change and binds its index root, versions and history floor. Intermediate node publication is not partial acceptance. Interrupted jobs recover or receive explicit disposition.

Checkpoint roots preserve causal and deletion evidence as well as visible values. Default history is unlimited. An opted-in finite merge window advances the epoch/floor only through validated checkpoint publication. Old replicas receive a resynchronization requirement; stale edits cannot resurrect deleted values.

Read, query and recoverโ€‹

An accepted reference fixes resource, Document, epoch, type and accepted revision. Bounded path reads distinguish missing, null, value, object and conflict. Sequence reads return an item, continuation/progress or end; keep the exact snapshot and bound traversal work, including steps that do not yield a visible element.

Each disclosure checks current policy and history/lifecycle bounds. Retaining an old reference does not bypass compaction or retirement. Unified query v1 reads declared accepted projections with five-state cells; it does not include tentative edits or convert conflicts into arbitrary winners.

The remote caller guide binds an allowed replica, frozen request and original reply route. All ten non-Zig SDK targets support Document changes and reads. The service runs locally, in Compose and in the reference deployment. It uses the Transit Document format; external CRDT wire formats are unsupported. See the package for exact APIs.