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, Ð_SUPERCHAIN.lattices[0].offer ).await?;
let uni_bid = offer::Offer::<Bundle>::bid (&network, Ð_SUPERCHAIN.lattices[1].offer ).await?;
let eth_tally = tally::Tally::<Attribution>::read(&network, Ð_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:
-
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.
-
Every public primitive of every referenced standalone organism, unchanged. Each organism’s own book is the reference.
-
Every module’s public surface (Atlas, Almanac, Chronicle — whichever are shipped), specified in basic services.
-
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:
| Component | Write-side primitives | Read-side primitives |
|---|---|---|
atlas | (committee-only) | Atlas map (MemberId → MemberCard) |
almanac | (committee-only) | Ticks stream |
intents | Publish<Intent> stream | RoutedIntents 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 byOrganismRef. - 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’sunseal::UnsealedPool, commits per- slotRoutedIntentskeyed by target lattice).ledger— a shared-refund aggregator (reads from each lattice’stally::Refunds, commitsSharedRefundskeyed 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
CoalitionConfigitself. 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
Sonethereum.mainnetis unrelated to slotSonunichain.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 currentalmanac_tickas an additional alignment key. - Each member’s pipeline is unchanged. The
intentscomposite organism injects routed-intent entries into a lattice’sofferinput via a subscription, not a cross-Group command. Eachofferdecides whether and how to include routed intents in its auction. Non- slotted organisms likeprice-feed.eurcontinue 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:
-
atlascommitsMemberCardupdates. The state machine merges operator-submitted cards (signed by the contributing per-member operator, or by the coalition operator in single-operator coalitions) into theAtlasmap. -
almanaccommits a monotonic tick. The state machine runs a deadline-driven Raft round; winner’s tick becomesTicks[K+1]. -
intentscommits a routed-intents entry per slot per target lattice. State machine reads cross-chain intents from each spanned lattice’sUnsealedPool, applies the routing policy, commits{member_id, slot, intents[]}intoRoutedIntents. -
ledgercommits a shared-refund entry per origin member per slot. State machine reads each spanned lattice’stally::Refunds, performs attribution across origin members, and commits{origin_member, slot, shares[]}intoSharedRefunds.
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 theCoalitionConfigdoes not change. -
Member retirement (stable id changes). The per- member operator publishes a new identity. Coalitions that reference this member must re-publish their
CoalitionConfigwith the new stable id. Every module’s identity bumps becauseCOALITION_ROOThas 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.
| Component | Committee members (v1) | Stream bytes / event | Notable bonds |
|---|---|---|---|
| Per lattice (×3) | see builder sizing | see builder sizing | see builder sizing |
price-feed.eur | see organism sizing | see organism sizing | committee + publishers |
atlas (module) | 3 members | O(members × card size) | committee + coalition op |
almanac (module) | 3–5 members | O(1) per tick | committee only |
intents composite | 3–7 TDX members | O(intents × lattices) | committee + each lattice |
ledger composite | 3–5 members | O(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.