Skip to main content

blockworx/doc_ng/
mod.rs

1//! The commit log: the document's only authoritative representation.
2//!
3//! A document is an append-only history of typed ops. Everything else —
4//! the editor's document state, routed geometry, spatial indexes — is
5//! derived from it and can be thrown away and rebuilt. That inversion is
6//! what makes several people editing at once tractable: histories
7//! compose, whereas two documents can only overwrite each other.
8//!
9//! The layering is strictly one-way:
10//!
11//! ```text
12//! commit log  ──fold──▶  document  ──solve──▶  derived  ──▶  caches
13//! ```
14//!
15//! Order comes from a **process, not a protocol**: one server accepts
16//! commits and assigns each the next [`Rev`](rev::Rev), so the total order
17//! on writes is arrival order and no client participates in establishing
18//! it. That is the whole of the concurrency design, and it is why there
19//! are no clocks, no actor ids, no content-addressed history, and no
20//! merge/repair pass here.
21//!
22//! Five rules keep it honest, and every one of them is load-bearing:
23//!
24//! 1. **All state is last-write-wins registers, creates, and tombstones.**
25//!    The merge is `max` over [`WriteOrder`](write_order::WriteOrder) —
26//!    associative, commutative, idempotent — which is what lets a client
27//!    re-fold its unacknowledged commits above a moving confirmed head and
28//!    reach the answer the server will. An op that does not reduce to
29//!    those three breaks it.
30//! 2. **The fold is pure, and it is the only writer.**
31//!    [`try_apply`](document::Document::try_apply) folds into a *new*
32//!    document, so a refused commit cannot leave a partial write behind
33//!    and consumes no rev. No I/O, no clock, no randomness, and no
34//!    re-running of the logic that produced an op — ids are minted before
35//!    an op is recorded, never during replay.
36//! 3. **Nothing derived is ever stored in the log.** Solver output cannot
37//!    be merged, so it must be recomputable instead.
38//! 4. **Unknown encodings are refused, never skipped.** Half-loading a log
39//!    written by a newer build forks the document silently. The decode
40//!    boundary is also a trust boundary in production — the server
41//!    deserializes payloads from arbitrary clients — so values arriving
42//!    through it are range-checked and refused, never clamped.
43//! 5. **Global invariants are ingress preconditions, not repairs.** One
44//!    apply point means a cycle or a dangling reference can be refused
45//!    before it is sequenced, rather than voided after the fact.
46//!
47//! A prediction is a different type from the authority's copy
48//! ([`Provisional`](rev::Provisional) against
49//! [`Confirmed`](rev::Confirmed)), because a prediction's rev is scratch
50//! that every rebuild re-mints, and reporting or storing one as a log
51//! position would be a lie the compiler can prevent.
52//!
53//! Per-kind structure is generated, not transcribed: one field list per
54//! entity in [`block_model`] expands through the `entity!` macro to the
55//! struct, its total init, its update vocabulary, and the
56//! [`Entity`](entity::Entity) impl — so a register cannot exist without a
57//! way to write it, and neither can drift from the other.
58//!
59//! See `docs/collab-architecture.md` for the design,
60//! `docs/doc-ng-design-notes.md` for why each piece is shaped as it is,
61//! and `docs/collab-migration-playbook.md` for how the editor is being
62//! moved onto it.
63
64pub mod block_model;
65pub mod commit;
66pub mod document;
67pub mod encode;
68pub mod entity;
69#[cfg(test)]
70pub mod fixtures;
71pub mod geometry;
72pub mod hash;
73pub mod id;
74pub mod opcode;
75pub mod reconcile;
76pub mod register;
77pub mod rev;
78pub mod session;
79pub mod values;
80pub mod write_order;