Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 derive CoalitionConfig fingerprints. 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.superchain
  • mev.mainnet-q2
  • oplabs.testnet
  • signals.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 CitizenCard commit 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:

  1. Compute COALITION = blake3("coalition|" || SCHEMA_VERSION_U8 || "|" || name).
  2. Compute COA_LATTICES = ordered stable ids.
  3. Compute COA_ORGANISMS = ordered stable ids (plus content hashes if pinned per-organism).
  4. Compute COA_CONFS = ordered ConfluenceConfig fingerprints.
  5. Compute COA_TICKETS = TicketIssuerConfig fingerprint if present, else 0 bytes.
  6. Compute COALITION_ROOT = blake3(COALITION || COA_LATTICES || COA_ORGANISMS || COA_CONFS || COA_TICKETS).
  7. Module identities are derived from COALITION_ROOT via COALITION_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:

  1. Install the Atlas binary on committee hosts (default N = 3; scale up as needed).
  2. Bootstrap Raft peers on the shared universe using the Atlas’s GroupId derived from its ConfluenceConfig under COALITION_ROOT.derive("module").derive("atlas").
  3. 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:

  • CoalitionConfig Rust const (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 ConfluenceConfig with MR_TDs, state-machine signature, a short description, and a pointer to the confluence operator’s handshake.
  • Each module’s ConfluenceConfig with 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:

Failure modes

  • Integrators report ConnectTimeout. Either the published CoalitionConfig drifted 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 CoalitionConfig against the new stable id, and tighten change-channel discipline with that operator.

Cross-references