Full peer
The Rust crates implement protocol state, routing, reliability, MLS and service discovery. Platform code supplies transport I/O and persistent storage. Use a full peer when the device must manage sessions, route traffic or host the complete coordination stack. Start from the versioned SDK workspace, its architecture and transport bridges.Built-in file stores
A host without a platform keystore can use the stores inoffline-protocol from v0.28.0, behind the default file-store feature:
A wrong key is refused at open with
FileStoreError::WrongStoreKey before any record is read. Each store locks its directory while open; a second engine over the same directories fails with FileStoreError::InUse. The replicated_notes example runs on them. Bindings reach the same stores through initialize_mls_with_file_stores; Python exposes them as store_key options.
Constrained leaf
offline-protocol-leaf is a firmware component for a constrained device. It processes protocol frames and participates in MLS as a member that never issues commits. A full peer creates the group and performs membership commits; the leaf joins, receives, responds and persists its state.
Two leaves cannot establish a session with each other on their own. Pair the device with a phone, Linux host or another full peer over a compatible radio path.
Build targets
The leaf builds without default features for bare-metal targets. This table is the crate’s own, from its README. CI builds and lints the crate for the first four rows:
The two ESP32 RISC-V rows and the Cortex-M0 row are new in v0.28.0. Compiling is all this table claims. Nothing has been linked into a firmware image or run on a board. The ESP32-C3, ESP32-C2 and Cortex-M0 targets have no atomic compare-and-swap, so firmware on them must link a critical-section implementation; build the store handle with
shared_store, which works on every target.
WASI
The leaf also builds forwasm32-wasip1, and CI gates both halves: the no_std build without bare-metal-rng, where getrandom reads the runtime’s random_get, and the std build through the wasi_host_shim example. The shim takes the time and the frames from the runtime over its standard streams and prints the frames the device owes. It has been run natively; nothing has run under a WebAssembly runtime. wasm32-unknown-unknown is not supported.
From an SDK checkout:
Firmware responsibilities
The MCU does not inherit the phone or Python relay client. For internet transport, implement a firmware client with connection, authentication and address proof, or use a companion full peer that already has the client. An existing direct upload from the MCU to its own backend can remain unchanged.
Qualify the target
Measure flash, RAM, latency, power, storage endurance and restart behaviour on the selected part and radio stack. Define the full-peer/leaf topology before quoting device capacity or transport support. See the leaf source and contract and commercial integration route.Install the Rust crates
Use Rust 1.87 or newer. The twelveoffline-protocol crates are published to crates.io at 0.28.0. For a full peer:
bare-metal-rng with the default std feature. Register getrandom::register_custom_getrandom! with the device’s hardware entropy source; enabling the feature alone does not supply randomness. A missing or predictable entropy implementation makes key generation unusable or unsafe. The leaf API centers on LeafDevice and LeafStore; a leaf requires a compatible full peer for session establishment. Two leaves cannot establish that session with each other.
