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

Anatomy of a coalition

audience: contributors

This chapter is the concrete instantiation of the pattern described in Designing coalitions on mosaik. It walks one example coalition end-to-end: the fingerprint derivation, the public surface each component exposes on the shared universe, the subscription graph across member boundaries, and the way an integrator binds handles through one CoalitionConfig.

The reader is assumed to have read the topology intro, the basic-services spec, and the builder architecture chapter.

Coalition identity recap

  COALITION       = blake3("coalition|" || SCHEMA_VERSION_U8
                           || "|" || coalition_name)
  COALITION_ROOT  = blake3(
                      COALITION
                      || ordered lattice stable ids
                      || ordered organism stable ids
                         (including any composite organisms)
                      || optional ticket-issuer fingerprint
                    )

  // Lattice IDs: NOT re-derived by the coalition.
  LATTICE_i       = <builder's own derivation for lattice i>
  ORGANISM_IN_i   = <builder's own derivation for each organism in lattice i>

  // Standalone-organism IDs: NOT re-derived by the coalition.
  STANDALONE_j    = <the organism's own derivation>

  // Composite-organism IDs: derived independently of any coalition.
  ORGANISM_c    = blake3("organism|" || SCHEMA_VERSION_U8
                            || "|" || name
                            || spanned members
                            || content
                            || acl)

  // Module IDs: the coalition-scoped components.
  ATLAS_ROOT      = COALITION_ROOT.derive("module").derive("atlas")
  ALMANAC_ROOT    = COALITION_ROOT.derive("module").derive("almanac")
  CHRONICLE_ROOT  = COALITION_ROOT.derive("module").derive("chronicle")

  // Optional coalition-scoped ticket issuer.
  TICKETS_ROOT    = COALITION_ROOT.derive("tickets")

Member identity travels with the member; a composite organism’s identity travels with the organism. Only module identity (and the optional ticket issuer) is coalition-bound. See topology-intro — Membership-by-reference and topology-intro — Composite organisms as a recurring pattern.

Integrators bind via the CoalitionConfig they compile in from operator-published release notes:

use std::sync::Arc;
use mosaik::Network;
use builder::UNIVERSE;
use coalition::CoalitionConfig;

const ETH_SUPERCHAIN: CoalitionConfig<'static> = /* operator-published */;

let network = Arc::new(Network::new(UNIVERSE).await?);

// Lattice organism handles — identical to the builder book.
let eth_bid   = offer::Offer::<Bundle>::bid (&network, &ETH_SUPERCHAIN.lattices[0].offer ).await?;
let uni_bid   = offer::Offer::<Bundle>::bid (&network, &ETH_SUPERCHAIN.lattices[1].offer ).await?;
let eth_tally = tally::Tally::<Attribution>::read(&network, &ETH_SUPERCHAIN.lattices[0].tally).await?;

// Standalone-organism handles — same shape, concrete crate on the right.
let eur_feed  = oracle::Feed::<Price>::read(&network, ETH_SUPERCHAIN.organisms[0].config()).await?;

// Module handles — resolved via typed helpers.
let atlas     = atlas::Atlas::<MemberCard>::read(&network, ETH_SUPERCHAIN.atlas().unwrap()).await?;
let almanac   = almanac::Almanac::<AlmanacTick>::read(&network, ETH_SUPERCHAIN.almanac().unwrap()).await?;

// Composite-organism handles — the same shape as any other organism.
let intents   = intents::Router::<Intent>::publish(&network, ETH_SUPERCHAIN.organisms_by_name("intents").unwrap()).await?;
let ledger    = ledger ::Shared ::<Refund>::read  (&network, ETH_SUPERCHAIN.organisms_by_name("ledger").unwrap()).await?;

An integrator only opens the handles they need. A cross- chain searcher typically holds bid for several lattices and intents::publish; a shared-ledger analytics consumer typically holds ledger::read only; a cross-feed correlator holds one oracle handle plus one composite organism handle; an observability operator holds atlas::read and opens per-member handles from there.

Public surface summary

The coalition’s outward-facing primitives decompose into:

  1. Every public primitive of every referenced lattice, unchanged. The builder book’s lattice public surface table applies without modification — the coalition does not touch lattice primitives.

  2. Every public primitive of every referenced standalone organism, unchanged. Each organism’s own book is the reference.

  3. Every module’s public surface (Atlas, Almanac, Chronicle — whichever are shipped), specified in basic services.

  4. One or two public primitives per referenced composite organism, following the same narrow-surface discipline as every other organism.

For an example coalition containing two composite organisms — an intent router and a shared ledger — plus Atlas and Almanac as modules, the coalition’s own added surfaces might look like:

ComponentWrite-side primitivesRead-side primitives
atlas(committee-only)Atlas map (MemberIdMemberCard)
almanac(committee-only)Ticks stream
intentsPublish<Intent> streamRoutedIntents collection (per slot, per target lattice)
ledger(internal commits only)SharedRefunds collection (keyed by origin member)

“Committee-only” and “internal commits only” mean the primitive is ticket-gated to the organism’s committee peers. It still lives on the shared universe; the ticket gate supplies access control.

Names above are illustrative. The blueprint specifies Atlas/Almanac/Chronicle by role; all other composite organism names are per-commission choices.

An example coalition: ethereum.superchain

Concrete walk-through of one plausible coalition. None of the composite organisms or services below are shipped; the sketch shows how the composition composes.

Composition

  • Lattices: ethereum.mainnet, unichain.mainnet, base.mainnet — all three referenced by stable id, none re-derived.
  • Standalone organisms: price-feed.eur — an oracle feed publishing EUR/USD prices on the shared universe, referenced by OrganismRef.
  • Modules shipped: Atlas (directory), Almanac (tick beacon). Chronicle not shipped in this example; the operator can add it later without reshuffling members.
  • Composite organisms referenced:
    • intents — a cross-chain intent router (reads from each lattice’s unseal::UnsealedPool, commits per- slot RoutedIntents keyed by target lattice).
    • ledger — a shared-refund aggregator (reads from each lattice’s tally::Refunds, commits SharedRefunds keyed by origin member).

Fingerprint sketch

  ETH_SUPERCHAIN = blake3("coalition|" || SCHEMA_VERSION_U8
                           || "|ethereum.superchain")

  COALITION_ROOT = blake3(
    ETH_SUPERCHAIN
    || LatticeConfig.stable_id(ethereum.mainnet)
    || LatticeConfig.stable_id(unichain.mainnet)
    || LatticeConfig.stable_id(base.mainnet)
    || OrganismRef.stable_id(price-feed.eur)
    || OrganismRef.stable_id(intents)
    || OrganismRef.stable_id(ledger)
    || (no ticket issuer)
  )

  ATLAS_ROOT      = COALITION_ROOT.derive("module").derive("atlas")
  ALMANAC_ROOT    = COALITION_ROOT.derive("module").derive("almanac")

  // Composite organisms derive independently of the coalition.
  INTENTS_ID      = blake3("organism|" || SCHEMA_VERSION_U8 || "|intents"
                           || [ethereum, unichain, base]
                           || intents_content
                           || intents_acl)
  LEDGER_ID       = blake3("organism|" || SCHEMA_VERSION_U8 || "|ledger"
                           || [ethereum, unichain, base]
                           || ledger_content
                           || ledger_acl)

  // Per-component committee derivations follow the usual pattern.

A composite organism’s spanned-member set may be a subset of the coalition’s member set. An intents composite organism might span all three lattices while a feed-oracle composite organism spans price-feed.eur and one lattice. Each composite organism chooses its own span.

Participants

Not every component is operated by the same entity. The coalition distinguishes six classes of participant.

  • Lattice operator — the team responsible for a referenced LatticeConfig’s identity, its committees, and its ACL. One or more lattice operators per coalition; each operates independently.
  • Standalone-organism operator — the team responsible for a standalone organism (e.g. price-feed.eur). Operates independently.
  • Composite-organism operator — the team responsible for one composite organism’s committee members. Composite-organism operation is independent of any referencing coalition.
  • Module operator — the team responsible for Atlas, Almanac, or Chronicle’s committee members. Often the coalition operator themselves; may be delegated.
  • Coalition operator — the team responsible for publishing and maintaining the CoalitionConfig itself. Often coincides with one of the above; does not have to. Has no technical authority over the referenced members or composite organisms.
  • Integrator — external dev, runs no committee members, binds handles against the coalition from their own mosaik agent.

Data flow across one slot

The canonical happy path for one slot through this example coalition. Each step is a commit into one organism’s state machine; transitions between steps are stream/collection subscriptions. No arrow represents an atomic multi-Group commit.

  integrator                    organism                   commit / effect
  ----------                    ----------------------     ----------------------------

  wallet       ──► zipnet[eth]           ───► Broadcasts grows (sealed envelopes for slot S)
                   unseal[eth]           ───► UnsealedPool[S] populated

  (same for uni, base)

  (publisher) ──► price-feed.eur         ───► Price[tick T] committed (async, no slot clock)

  (internal)  ──► almanac                ───► Ticks[K] committed (shared time axis)
  (internal)  ──► atlas                  ───► MemberCard updates (any time)

  composite  ──► intents               ───► RoutedIntents[S] committed per target lattice
                                                 (sees cross-chain intents, routes them)

  searcher     ──► offer[eth]            ───► AuctionOutcome[S] (incorporates routed intents)
  searcher     ──► offer[uni]            ───► AuctionOutcome[S]
  searcher     ──► offer[base]           ───► AuctionOutcome[S]

                   atelier[eth]          ───► Candidates[S] committed
                   atelier[uni]          ───► Candidates[S]
                   atelier[base]         ───► Candidates[S]

                   relay[eth]            ───► AcceptedHeaders[S]
                   relay[uni]            ───► AcceptedHeaders[S]
                   relay[base]           ───► AcceptedHeaders[S]

  (chain inclusion watchers observe each lattice independently)

                   tally[eth]            ───► Refunds[S]
                   tally[uni]            ───► Refunds[S]
                   tally[base]           ───► Refunds[S]

  composite  ──► ledger                ───► SharedRefunds[S] committed per origin member

  wallet / searcher ◄──  ledger              refunds + attestations stream (aggregated)
  dashboard        ◄──  atlas                directory of members (for observability)
  correlator       ◄──  almanac              shared tick axis (for cross-member joins)

Two properties of this flow:

  • The slot number remains the foreign key for block- building lattices but is per-member. Slot S on ethereum.mainnet is unrelated to slot S on unichain.mainnet. Composite organisms crossing member boundaries key commits by (member_id, slot) pairs (or (member_id, tick) for non-slotted standalone organisms). If the coalition ships an Almanac, composite organisms may optionally carry the current almanac_tick as an additional alignment key.
  • Each member’s pipeline is unchanged. The intents composite organism injects routed-intent entries into a lattice’s offer input via a subscription, not a cross-Group command. Each offer decides whether and how to include routed intents in its auction. Non- slotted organisms like price-feed.eur continue publishing on their own clock; composite organisms read their ticks as they appear.

Where each composite organism commits

The rule from the builder book — “what decision is the organism actually making at commit time” — carries to composite organisms and modules:

  • atlas commits MemberCard updates. The state machine merges operator-submitted cards (signed by the contributing per-member operator, or by the coalition operator in single-operator coalitions) into the Atlas map.

  • almanac commits a monotonic tick. The state machine runs a deadline-driven Raft round; winner’s tick becomes Ticks[K+1].

  • intents commits a routed-intents entry per slot per target lattice. State machine reads cross-chain intents from each spanned lattice’s UnsealedPool, applies the routing policy, commits {member_id, slot, intents[]} into RoutedIntents.

  • ledger commits a shared-refund entry per origin member per slot. State machine reads each spanned lattice’s tally::Refunds, performs attribution across origin members, and commits {origin_member, slot, shares[]} into SharedRefunds.

The same discipline every organism in every lattice observes: one decision per commit, state-machine-local, no cross-organism transactions.

Internal plumbing (optional derived private networks)

Same pattern zipnet established and builder reaffirmed: the public surface lives on UNIVERSE; high-churn internal plumbing may move to a derived private network keyed off the organism’s root.

For composite organisms and modules:

  • Per-member subscription fan-in. Gossip between committee members about per-member cursor state may live on <component>_root.derive("private").
  • Attestation gossip. Committee members signing off on a commit can exchange signatures privately before the public commit lands.

Committee Groups themselves stay on UNIVERSE. The argument is unchanged across every rung.

Identity under member upgrades

Member identity splits into a stable id and a content hash; each moves on a different cadence.

  • Member internal rotation (stable id unchanged, content hash bumps). TDX Measurements rotation or ACL change. Invisible to COALITION_ROOT. Commissioned composite organisms that pin content hash redeploy; composite organisms that pin stable id only continue as-is. The coalition publishes an advisory if the change matters to downstream components, but the CoalitionConfig does not change.

  • Member retirement (stable id changes). The per- member operator publishes a new identity. Coalitions that reference this member must re-publish their CoalitionConfig with the new stable id. Every module’s identity bumps because COALITION_ROOT has changed; composite organisms do not re-derive unless they themselves span the retired member and pin its reference.

This is a material clarity win over a design where every member change ripples into composite-organism identity: a coalition referencing ten members rotating TDX monthly sees module identity stable unless a retirement happens.

A coalition operator insulating integrators from member retirements carries a version-stable alias in the coalition name (ethereum.superchain-v2026q2). See Roadmap — Versioning.

Sizing — Phase 1 coalition

Order-of-magnitude targets for an illustrative coalition with three lattices, one standalone organism, two modules, and two composite organisms. Indicative, not binding.

ComponentCommittee members (v1)Stream bytes / eventNotable bonds
Per lattice (×3)see builder sizingsee builder sizingsee builder sizing
price-feed.eursee organism sizingsee organism sizingcommittee + publishers
atlas (module)3 membersO(members × card size)committee + coalition op
almanac (module)3–5 membersO(1) per tickcommittee only
intents composite3–7 TDX membersO(intents × lattices)committee + each lattice
ledger composite3–5 membersO(refunds)committee + each lattice

“v1” here means the coalition-level Phase 1 shape. Phase 2 adds more composite organisms as cross-member problems arise; Phase 3 introduces multi-operator composite organisms where committee members span organisations.

What this chapter deliberately does not cover

  • Per-organism state machines. Each organism owns its own spec in its own crate once commissioned.
  • Per-organism wire formats. Same.
  • Chain-specific nuance inside a lattice. The builder book covers this; coalitions do not touch it.
  • Organism-specific nuance inside a standalone organism. Each organism’s own book covers that.
  • A canonical list of composite organisms or organism categories. See topology-intro — What a coalition is not.
  • Deferred-primitives space (enforcement, taxation, judiciary). Deferred; see topology-intro — Fixed shapes, open catalogs.