OpenMLS-backed implementation of the CgkaEngine trait.
This crate owns the local group state machine. It sits above OpenMLS, governs commit sequencing, enforces MIP-03 admin rules, and returns typed outcomes for every ingest path.
- Wraps
MlsGroupfor each joined group and manages itsEpochStatelifecycle (Stable,PendingPublish,Merging,Recovering,Unrecoverable). - Translates
SendIntents (app-message, invite, remove-members, leave, update-app-components, update-group-data) into MLS commits — group creation and capability upgrade are separate trait calls (create_group,upgrade_group_capabilities); translates inboundTransportEnvelopes into typedIngestOutcomes andGroupEvents. - Stores inbound payloads as typed raw-transport or peeled-OpenMLS records so peel-deferred messages can be retried without polluting convergence replay.
- Retains a small, configurable OpenMLS past-epoch window for delayed application messages.
- Maintains a per-leaf capability cache so
feature_statuslookups do not walk the ratchet tree. - Stages SelfRemove-only commits for eligible remaining members and returns that work as publish-before-apply obligations; keeps durable local leave requests gated and re-proposes stale SelfRemove proposals for newer epochs.
- No transport (no Nostr, no relays). Plug in a
TransportPeelerimpl. - No persistence beyond what
StorageProviderexposes. Pair withstorage-sqlitefor SQLCipher-backed persistence; tests can use its in-memory SQLite mode. - No CLI, no FFI, no application logic.
cargo test -p cgka-engineThese tests cover the engine boundary directly. They use one or a few Engine<SqliteAccountStorage> instances with in-memory
SQLite storage and a mock peeler. They are the right place for local rules: command validation, snapshot persistence,
processed-message idempotency, restart behavior, and the exact outputs from a single engine call.
Run the simulator when you change convergence, delivery, branch selection, group data, or anything that depends on more than one client:
cargo test -p cgka-conformance-simulator
cargo test -p cgka-conformance-simulator --features conformance-slowThe simulator is the integration and conformance layer for this engine. It wraps real engine instances with the Nostr peeler, drives them through an in-memory transport bus, and checks that clients converge after realistic delivery weirdness. Its README explains the scenario format, vector fixtures, generated families, reports, and property tests:
Use this crate's tests to prove that an engine method does the right thing. Use the simulator to prove that many engines still agree after the world gets messy.
See tests/AGENTS.md for the test file map.
upgrade_group_capabilities only promotes state-bearing app components whose
optional state already exists in the GroupContext. Use two published commits:
- send
SendIntent::UpdateAppComponentsto install the optional component state, then confirm that commit was published; - call
upgrade_group_capabilities, then publish and confirm its promotion commit.
The upgrade fails closed without staging a commit when required state is missing. MDK does not currently expose an atomic require-and-populate API.
- Target architecture:
../../docs/marmot-architecture/overview/target-architecture.md ../../docs/marmot-architecture/cgka-engine-spec.md— the current engine spec- Detailed post-peeling contract:
../../docs/marmot-architecture/cgka-engine-canonicalization-contract.md - Branch-selection and convergence model:
../../docs/marmot-architecture/distributed-convergence.md AGENTS.md— module-by-module map of this crate, design deviations, where to look for what
For the Marmot app-component model now used by new groups, see
marmot-protocol/marmot and src/app_components.rs.
0.9.0, single internal consumer, not semver-stable. For current readiness and open production work, start with
../../docs/marmot-architecture/overview/current-state.md.