Overall architecture
Workspace-level view of the CBCL Rust implementation. The workspace is a strict purity-zoned Cargo workspace: pure deterministic core crates (cbcl-core, cbcl-parser) under #![forbid(unsafe_code)] + no_std + alloc, surrounded by effectful shell crates (cbcl-cli, cbcl-wasm, cbcl-ffi, cbcl-erl, cbcl-arena). Parallel to the Rust workspace lives lean-cbcl/, a Lean 4 formalization that machine-checks safety properties of the core algorithms.
graph LR
cbcl-core["cbcl-core\ncrates/cbcl-core/src/"]
cbcl-parser["cbcl-parser\ncrates/cbcl-parser/src/"]
cbcl-cli["cbcl-cli\ncrates/cbcl-cli/src/"]
cbcl-wasm["cbcl-wasm\ncrates/cbcl-wasm/src/"]
cbcl-ffi["cbcl-ffi\ncrates/cbcl-ffi/src/"]
cbcl-erl["cbcl-erl\ncrates/cbcl-erl/src/"]
cbcl-arena["cbcl-arena\ncrates/cbcl-arena/src/"]
lean-cbcl["lean-cbcl\nlean-cbcl/"]
cbcl-parser -->|"types, R1-R5, pipeline deps"| cbcl-core
cbcl-cli -->|"parse, verify, agent REPL"| cbcl-parser
cbcl-cli -->|"agent + gossip simulation"| cbcl-core
cbcl-wasm -->|"parse_message, verify_dialect"| cbcl-parser
cbcl-wasm -->|"agent, dialect"| cbcl-core
cbcl-ffi -->|"parse, agent send/free"| cbcl-parser
cbcl-ffi -->|"agent, evaluator"| cbcl-core
cbcl-erl -->|"verify_dialect NIF"| cbcl-parser
cbcl-erl -->|"core types"| cbcl-core
cbcl-arena -->|"messages, dialects"| cbcl-core
cbcl-arena -->|"pipeline parsing"| cbcl-parser
lean-cbcl -.->|"machine-checked proofs of"| cbcl-core
The crates
Pure core
cbcl-core — crates/cbcl-core/src/ · ~17k LoC. 23 modules covering S-expressions, messages and performatives, dialect registry, runtime agents, the message evaluator, template expansion, pattern matching, canonical serialization, the five safety constraints (R1–R5), blame attribution, shape and causal-protocol verification, deterministic message tagging, gossip propagation, policy engine, and message store. Largest modules: agent.rs (1669), store.rs (1694), protocol.rs (1715).
cbcl-parser — crates/cbcl-parser/src/. Hand-rolled recursive-descent parser (ADR-001) and the verified pipeline. Five parsers (S-expr, message, dialect, protocol, shape) feed into one pipeline (parse → parse_message → validate → expand → causal verify → shape check). Pure (no_std + alloc, #![forbid(unsafe_code)]). Mirrored by lean-cbcl/LeanCbcl/Parser.lean and Pipeline.lean.
Effectful shells
cbcl-cli — crates/cbcl-cli/src/main.rs, ~400 LoC. clap-based subcommand dispatch. Subcommands: parse, verify, agent (interactive REPL), simulate (gossip). See Command surface.
cbcl-wasm — Two-tier API (ADR-003): pure WASM exports always available on wasm32, plus wasm-bindgen JS interop behind the bindgen feature. API surface: parse_message, verify_dialect, create_agent, send_message. Provides its own no_std allocator and panic handler for wasm32 cdylib builds.
cbcl-ffi — C FFI bindings via cbindgen. Public API: cbcl_parse_message, cbcl_verify_dialect, cbcl_agent_new, cbcl_agent_send, cbcl_agent_free, cbcl_string_free. Returns CbclResult { data, error } where the caller frees data with cbcl_string_free.
cbcl-erl — Erlang/BEAM NIF binding (SPEC-009). BEAM module name cbcl_erl, loaded from libcbcl_erl.{so,dylib} via rustler 0.36. Each NIF is split into a #[rustler::nif] wrapper and an env-free *_pure helper carrying the real logic — the pure helpers are the only testable surface under cargo test.
cbcl-arena — SPEC-011 multi-agent arena challenge simulator. Three challenges (PSI, Yao’s Millionaire, Dining Cryptographers), two agent strategies (CBCL-disciplined, Vanilla NL-chat), three attacker categories. Has its own internal purity boundary inside the crate.
Proof
lean-cbcl — lean-cbcl/. Lean 4 formalization. Zero sorries; standard axioms only (propext, Classical.choice, Quot.sound); 300+ declarations across 16 files. Each safety-critical Rust module pairs with one Lean file (e.g. r1.rs ↔ R1NoRecursion.lean). Headline theorems: decidable_preserved, dcfl_preserved, agentDetParser_agrees, r1_mutual_sound + dfsNoCycle_complete, pipeline_success_grammar.
Maintaining the Rust ↔ Lean correspondence
Differential tests in crates/cbcl-parser/tests/differential.rs run both implementations on shared test vectors. Drift between the two — e.g. a fix to r3.rs without updating R3CorePreservation.lean — silently invalidates the paper’s claims and breaks artefact integrity.