Quickstart — stand up a coalition
audience: operators
This runbook brings up a minimal coalition: one
CoalitionConfig referencing two existing citizens (two
block-building lattices, two standalone organisms, or one
of each) and shipping one module — an Atlas — that
publishes a per-coalition directory. Assumptions:
- The citizens to be referenced exist. If any are block- building lattices not yet run by the operator, follow the builder operator quickstart first; if any are standalone organisms not yet run, follow the organism crate’s runbook.
- Familiarity with the builder operator workflow: systemd units, published handshake pages, committee bring-up, MR_TD publication. The discipline is identical for any organism committee.
- The coalition meta-crate (
coalition) exists in a form sufficient to deriveCoalitionConfigfingerprints. Until v0.2 lands, this is a paper exercise; the steps below are the target shape.
Estimated time to first CoalitionConfig: two engineer-
days, assuming referenced citizens and the Atlas crate
are already running.
Step 1 — enumerate the citizens to reference
Record, for each citizen, the canonical stable id (and optional content hash, if you choose to pin it) as published by its operator.
citizen kind stable_id (hex) content_hash ticket-issuance root
-----------------------------+---------+---------------------+------------------+----------------------
ethereum.mainnet lattice 0x… (unpinned) 0x…
unichain.mainnet lattice 0x… (unpinned) 0x…
price-feed.eur organism 0x… 0x… 0x…
Do not invent stable ids locally. Always use the per-
citizen operator’s authoritative value. A per-citizen
operator’s stable id that cannot be reproduced from its
published Config definition is a citizen-level issue;
do not paper over it in the coalition.
Step 2 — pick the coalition name
Short, stable, namespaced. Examples:
ethereum.superchainmev.mainnet-q2oplabs.testnetsignals.euro-fx
The name is folded into the coalition fingerprint; a typo propagates through every module derivation. Pick once. Rename via a new instance name, never via in-place edit.
Step 3 — decide which modules to ship
One module suffices for a minimal coalition. Atlas is the usual first choice:
- Small state machine — one
CitizenCardcommit per referenced citizen. - Low trust requirement — usually non-TDX, majority- honest.
- High utility — integrators pin the Atlas in their own docs as the canonical coalition-composition reference.
Ship Almanac and Chronicle on their own schedules. Specifications in basic services.
A concrete cross-citizen problem (paired-bundle auctions, cross-chain attribution, oracle/lattice correlation) motivates commissioning a relevant confluence beyond the modules. Each confluence is a separate crate and committee; confluences are coalition-independent, so the same confluence may also be referenced by other coalitions.
Step 4 — draft the CoalitionConfig
use builder::LatticeConfig;
use coalition::{CoalitionConfig, ConfluenceConfig, OrganismRef};
pub const ETHEREUM_MAINNET: LatticeConfig<'static> = /* from ethereum.mainnet operator */;
pub const UNICHAIN_MAINNET: LatticeConfig<'static> = /* from unichain.mainnet operator */;
pub const EUR_PRICE_FEED: OrganismRef<'static> = OrganismRef {
role: "oracle",
stable_id: /* from the price-feed operator */,
content_hash: None,
};
pub const SUPERCHAIN_ATLAS: ConfluenceConfig<'static> = ConfluenceConfig {
name: "atlas",
lattices: &[ETHEREUM_MAINNET, UNICHAIN_MAINNET],
organisms: &[EUR_PRICE_FEED],
content: /* atlas content params */,
acl: /* TicketValidator composition */,
};
pub const ETH_SUPERCHAIN: CoalitionConfig<'static> = CoalitionConfig {
name: "ethereum.superchain",
lattices: &[ETHEREUM_MAINNET, UNICHAIN_MAINNET],
organisms: &[EUR_PRICE_FEED],
confluences: &[SUPERCHAIN_ATLAS],
ticket_issuer: None,
};
Note: a ConfluenceConfig does not fold a coalition root;
confluence identity is independent. For a module like
Atlas, the meta-crate’s derivation routes the identity
under COALITION_ROOT.derive("module").derive("atlas")
internally when the helper atlas() returns the matching
ConfluenceConfig.
Step 5 — freeze the fingerprint
The derivation order is:
- Compute
COALITION = blake3("coalition|" || SCHEMA_VERSION_U8 || "|" || name). - Compute
COA_LATTICES = ordered stable ids. - Compute
COA_ORGANISMS = ordered stable ids (plus content hashes if pinned per-organism). - Compute
COA_CONFS = ordered ConfluenceConfig fingerprints. - Compute
COA_TICKETS = TicketIssuerConfig fingerprint if present, else 0 bytes. - Compute
COALITION_ROOT = blake3(COALITION || COA_LATTICES || COA_ORGANISMS || COA_CONFS || COA_TICKETS). - Module identities are derived from
COALITION_ROOTviaCOALITION_ROOT.derive("module").derive(name).
Once the fingerprint is frozen, record its hex in
release-notes.md. Integrators verify that hex against
the struct they compile.
Step 6 — stand up the Atlas (and any other modules)
Every module is a mosaik-native organism (specifically, coalition-scoped). To bring up the Atlas committee:
- Install the Atlas binary on committee hosts (default N = 3; scale up as needed).
- Bootstrap Raft peers on the shared universe using the
Atlas’s
GroupIdderived from itsConfluenceConfigunderCOALITION_ROOT.derive("module").derive("atlas"). - Publish the Atlas’s MR_TD (if TDX-gated) or the committee roster (if not).
Bring-up details are in the Atlas crate’s runbook and in Running a confluence. Atlas does not require TDX.
Step 7 — publish the handshake
Collect everything integrators need:
CoalitionConfigRustconst(or the hex fingerprint paired with the struct definition).- The ordered list of referenced
LatticeConfigs with links to each lattice operator’s handshake. - The ordered list of referenced
OrganismRefs with role names, stable ids (plus content hashes if pinned), and a link to each organism operator’s handshake. - The ordered list of referenced confluences — each
ConfluenceConfigwith MR_TDs, state-machine signature, a short description, and a pointer to the confluence operator’s handshake. - Each module’s
ConfluenceConfigwith MR_TDs, state- machine signature, and a short description. - A statement of which modules the coalition ships and which it does not — silence is ambiguous.
- The coalition-scoped ticket issuer root, if any.
- An initial peer hint for the shared universe.
- Your change channel (email, feed, repo).
Post as a single page on the operator site or handshake repo. Link integrators to it.
Step 8 — notify integrators
A message on the change channel announcing the
coalition’s first CoalitionConfig fingerprint is
sufficient. Waiting integrators compile in the constant
and open handles.
Ongoing operations
Day-to-day work is covered by the other operator pages:
- Running a confluence for operating each committee (including modules).
- Federating under a coalition for coordinating with other per-citizen and per-confluence operators.
- Rotations and upgrades for key rotations, MR_TD bumps, and citizen retirements.
Failure modes
- Integrators report
ConnectTimeout. Either the publishedCoalitionConfigdrifted from the live deployment, or a referenced citizen retired and the coalition operator has not republished. Recompile the struct, freeze the fingerprint, publish. - A module’s committee lost majority. Standard mosaik recovery. Referenced citizens and referenced confluences continue; integrators reading the module temporarily see no new commits.
- A referenced citizen retired silently. The per-
citizen operator should have notified the coalition
operator. File an anomaly with them, publish a new
CoalitionConfigagainst the new stable id, and tighten change-channel discipline with that operator.