Basic services
audience: contributors
Atlas, Almanac, Chronicle, Compute.
A basic service (also called a module) is a
coalition-scoped component whose role is specified once in
this blueprint so every instance means the same thing
across coalitions. This chapter specifies the four basic
services. Mechanically each is an organism with a narrow
public surface, derived under
COALITION_ROOT.derive("module").derive(name).
None of the four is mandatory. A coalition may ship zero, one, two, three, or all four. If a coalition ships a service named “Atlas”, it must have the shape on this page. A service named “Atlas” with a different shape is a bug, not a variant — the point of the catalog is that integrators and other services depend on the shape without reading per-coalition operator prose.
Guiding discipline:
Fix the shapes, leave the catalogs open.
The four basic services, the CoalitionConfig structure,
and the ConfluenceConfig structure are shapes. Which
of them any given coalition ships, and what confluences it
references, and what citizens it composes, are open.
Atlas
Problem. Integrators need a canonical list of the coalition’s citizens with operator metadata: role name, fingerprint, endpoint hint, ticket-issuance root, MR_TD pins, subscription schema version. Every coalition currently invents its own handshake table; standardising the shape lets a dashboard, analytics agent, or failover service read any coalition’s directory without per- coalition parsing.
Shape. Atlas is a module whose public surface is a
Map<CitizenId, CitizenCard>. Each card is co-signed
by the Atlas committee:
#[non_exhaustive]
pub struct CitizenCard<'a> {
/// The citizen's full 32-byte fingerprint
/// (LatticeConfig or OrganismRef stable id with
/// optional content hash).
pub citizen_id: UniqueId,
/// Role name ("lattice", "oracle", "attest", ...).
pub role: &'a str,
/// Endpoint hints for cold-start bootstrap.
pub endpoint_hints: &'a [EndpointHint<'a>],
/// Ticket-issuance root of the citizen's per-
/// operator ACL.
pub ticket_issuance_root: UniqueId,
/// MR_TD pins for TDX-gated organisms inside the
/// citizen (if any).
pub mrtd_pins: &'a [Mrtd],
/// Free-form metadata the operator surfaces.
pub metadata: &'a [(&'a str, &'a str)],
}
#[non_exhaustive]
pub struct EndpointHint<'a> {
pub proto: &'a str,
pub addr: &'a str,
}
CitizenId in cross-citizen commit keys is truncated to
the first 20 bytes of the blake3 fingerprint — the full
32-byte value lives in the Atlas card and in evidence
pointers. See
composition — Two keys.
Config signature. An Atlas’s ConfluenceConfig
folds:
- the coalition root (via
COALITION_ROOT.derive("module").derive("atlas")); - the ordered list of citizen references the Atlas catalogues (usually identical to the coalition’s, but may be a subset);
- the Atlas committee’s ACL.
State machine. One command per card write, one command per card retirement. Applies produce card updates in deterministic order.
Trust shape. Usually majority-honest, non-TDX. A TDX- attested Atlas is a natural v1+ refinement if the coalition requires signed provenance of the directory itself.
When to ship. Almost always. Atlas is the cheapest module to operate and the highest-leverage for integrators.
When to skip. A single-citizen coalition does not need a directory.
Almanac
Problem. Confluences correlating facts across citizens need a shared time axis. Each citizen’s clock is local — a block-building lattice has slots, an oracle has ticks, an analytics pipeline has batches. Without a shared monotonic beacon, every correlator re-invents its own tolerance window.
Shape. Almanac is a module whose public surface is a
single append-only Stream<AlmanacTick>. Each tick is co-
signed by the Almanac committee:
#[non_exhaustive]
pub struct AlmanacTick {
pub seq: u64,
/// Per-member wall-clock observations captured at
/// the moment each committee member voted to commit
/// the tick. Consumers compute median, bracket, or
/// spread themselves; `seq` is the sole ordering
/// authority.
pub observed_at: Vec<(MemberId, SystemTime)>,
}
observed_at is advisory: a vector of per-member
timestamps lets consumers detect outliers (a member’s
skewed clock shows as a one-sided tail) and bracket
cross-citizen events without trusting a single wall-
clock. Ordering is entirely in seq.
Config signature. An Almanac’s ConfluenceConfig
folds:
- the coalition root (via
COALITION_ROOT.derive("module").derive("almanac")); - the tick cadence (target inter-tick interval; state- affecting);
- the Almanac committee’s ACL.
State machine. A per-cadence-deadline Commit
command. Committee members propose ticks with their local
SystemTime::now(); the one that wins the Raft round
commits the per-member timestamp vector; others observe.
Trust shape. Majority-honest committee; optionally
TDX-attested if the coalition requires observed_at
entries to carry an attested source.
When to ship. When more than one confluence needs cross-citizen timing, or when a standalone organism without a slot clock participates in cross-citizen correlation.
What it is not. Almanac is not a consensus clock for the universe; it is not synchronised across coalitions; it is not a substitute for each citizen’s own local clock. Ticks are ordering markers; the timestamp vector is a correlation hint.
Chronicle
Problem. A coalition operator makes decisions that
outlive any one CoalitionConfig — publications,
rotations, retirements, membership changes, module
upgrades. Integrators, auditors, and future operators
need a tamper-evident record. Operator-published release
notes are insufficient; they can be edited in place.
Shape. Chronicle is a module whose public surface is
an append-only Stream<ChronicleEntry>. Each entry
carries both a quorum signature and per-member
signatures, and the committee periodically commits a
rolling blake3 digest of the stream to an external
settlement contract:
#[non_exhaustive]
pub struct ChronicleEntry<'a> {
pub seq: u64,
pub kind: ChronicleKind,
/// The coalition fingerprint at the moment of entry.
pub coalition_root: UniqueId,
/// Structured payload per kind.
pub payload: ChronicleBody<'a>,
pub observed_at: SystemTime,
/// Per-member signatures in addition to the
/// committee's quorum signature. An honest ex-
/// member's signed archive is a cryptographic
/// witness against a later compromised-majority
/// forgery.
pub member_sigs: Vec<(MemberId, Signature)>,
}
#[non_exhaustive]
pub enum ChronicleKind {
CoalitionPublication, // new CoalitionConfig fingerprint
CitizenAdded, // new lattice / organism reference
CitizenRemoved,
ConfluenceReferenced, // new ConfluenceConfig reference
ConfluenceUnreferenced,
ConfluenceRetired, // confluence itself retired (see retirement markers)
ModuleAdded,
ModuleRetired,
TicketIssuerRotated, // coalition-scoped issuance root changed
MembershipChanged, // operator added / removed
Retirement, // coalition retirement announcement
Other,
}
Config signature. A Chronicle’s ConfluenceConfig
folds:
- the coalition root (via
COALITION_ROOT.derive("module").derive("chronicle")); - the Chronicle committee’s ACL;
- the schema version of
ChronicleEntry; - the external settlement-contract address used for on- chain anchoring.
State machine. One command per entry. Applies
maintain a strictly monotonic seq. Retention is
operator-configured but must be substantial (years, not
days) — the point is longevity.
The Chronicle committee additionally commits
blake3(ChronicleEntry[0..N].serialized) to the declared
external contract on a committed cadence. The cadence is
an operator decision; a plausible default is one anchor
per week plus one per ChronicleKind::CoalitionPublication.
Trust shape. Tamper-evidence of past entries holds while at least one of:
- (a) the on-chain anchor path is uncompromised, or
- (b) at least one honest ex-member’s signed archive survives.
Retroactive rewriting requires compromising both. See threat model — Chronicle trust.
When to ship. When the coalition has more than one operator, a contested lineage (retirements, splits, forks), or a real need for externally verifiable provenance.
What it is not. Chronicle is descriptive, not prescriptive. It records decisions; it does not ratify them.
Compute
Problem. Coalition members — including AI-agent organisms — routinely need compute: to run a workload, retrain a model, execute a transient experiment, or bring up a short-lived companion organism. Every coalition currently re-invents compute acquisition via out-of-band contracts. Standardising the shape gives agents and organisms a uniform, auditable mechanism for acquiring compute, and gives coalition operators a well-known surface for publishing capacity.
Compute is the one basic service whose work is discharged off-module: the module is a registry and scheduler — it commits the grant — but the actual compute runs on a separate provider whose identity is published in the grant. The split is deliberate: the coalition’s trust boundary ends at the scheduling commit; the provider is bonded separately through mosaik’s normal ACL.
Shape. Compute is a module whose public surface is:
- a write-side
Stream<ComputeRequest>through which coalition members submit requests; - a read-side
Collection<RequestId, ComputeGrant>— the committee’s scheduled allocations; - an optional
Collection<ProviderId, ProviderCard>— capacity providers that have registered with the module; - an optional
Stream<ComputeLog>— usage attestations emitted by providers after a workload runs.
Image model — pre-hash and post-hash
A workload is identified by two fingerprints:
- Image pre-hash. The blake3 of a canonicalised
ComputeManifestdeclaring source crate, minimum hardware, TDX requirement, network policy, and duration hint. Known before the image is built; used inComputeRequestto state intent. - Image post-hash. The blake3 of the built image
itself (for TDX workloads, this is the MR_TD the
provider will run). Known after the build; used in
ComputeGrantto commit the scheduler to a specific build, and matched by the provider at startup.
The pre-hash / post-hash split mirrors the citizen stable-id / content-hash split (topology-intro — Citizen reference shape): a request that pins only the pre-hash survives reproducible rebuilds; a request that pins the post- hash commits to one specific binary.
Self-contained TDX images are produced per the mosaik TDX builder; the Compute module does not specify the build pipeline, only the fingerprints.
#[non_exhaustive]
pub struct ComputeManifest<'a> {
/// Source crate identity: name, version, and the
/// commit hash the image was built from.
pub crate_ref: CrateRef<'a>,
/// Minimum hardware requirements the image declares.
pub min_cpu_millicores: u32,
pub min_ram_mib: u32,
/// TDX requirement.
pub tdx: TdxRequirement,
/// Optional storage and network declarations.
pub min_storage_gib: u32,
pub network_policy: NetworkPolicy,
/// Non-binding duration hint the scheduler may use
/// to bin-pack.
pub duration_hint_sec: u32,
}
#[non_exhaustive]
pub struct CrateRef<'a> {
pub name: &'a str,
pub version: &'a str,
pub commit_hash: UniqueId,
}
#[non_exhaustive]
pub enum TdxRequirement {
NotRequired,
Optional,
Required,
}
#[non_exhaustive]
pub enum NetworkPolicy {
None, // no outbound
Mosaik, // only the shared universe
Allowlist, // specific endpoint hints
}
/// Pre-hash: folds the manifest only. Stable across
/// rebuilds as long as the manifest is stable.
pub const fn image_prehash(m: &ComputeManifest<'_>) -> UniqueId { /* ... */ }
/// Post-hash: folds the pre-hash with the built image
/// bytes and, for TDX, the MR_TD measurement.
pub const fn image_hash(
prehash: UniqueId,
built_image_digest: UniqueId,
mrtd: Option<Mrtd>,
) -> UniqueId { /* ... */ }
Request, grant, log
#[non_exhaustive]
pub struct ComputeRequest<'a> {
/// Requester — an agent organism, a confluence, or
/// an integrator identity bonded via a ticket the
/// module recognises.
pub requester: CitizenId,
/// Image pre-hash (what you want to run).
pub image_prehash: UniqueId,
/// Optional pinned post-hash if the requester has a
/// specific build they require.
pub image_hash: Option<UniqueId>,
/// Duration requested.
pub duration_sec: u32,
/// Settlement evidence — a payment receipt hash, a
/// reputation-card reference, or a coalition-scoped
/// credit token, per the module's policy.
pub settlement: SettlementEvidence<'a>,
/// Deadline by which the requester needs the grant;
/// unmet requests expire silently.
pub deadline: AlmanacTick,
}
#[non_exhaustive]
pub struct ComputeGrant<'a> {
pub request_id: UniqueId,
pub provider: CitizenId,
/// Endpoint hint for the actual compute. The
/// requester opens the endpoint out-of-band.
pub endpoint_hint: EndpointHint<'a>,
/// Bearer credential pointer (a blake3 of the
/// bearer token published by the provider via an
/// encrypted out-of-band channel; the scheduler
/// commits only the pointer).
pub bearer_pointer: UniqueId,
/// Post-hash of the image the provider commits to
/// running. Matches the request's prehash or
/// pinned post-hash.
pub image_hash: UniqueId,
/// Validity window in Almanac ticks.
pub valid_from: AlmanacTick,
pub valid_to: AlmanacTick,
/// Expected MR_TD on the provider side for TDX
/// workloads. None for non-TDX.
pub expected_mrtd: Option<Mrtd>,
}
#[non_exhaustive]
pub struct ComputeLog<'a> {
pub grant_id: UniqueId,
pub provider: CitizenId,
pub window: AlmanacRange,
/// Provider-signed usage attestation: cpu-seconds,
/// ram-mib-seconds, network bytes, storage bytes.
pub usage: UsageMetrics,
/// Evidence pointer to the workload's own output
/// stream, if any.
pub evidence: Option<EvidencePointer<'a>>,
}
Config signature. A Compute module’s
ConfluenceConfig folds:
- the coalition root (via
COALITION_ROOT.derive("module").derive("compute")); - the scheduler’s content parameters (accepted settlement evidence shapes, minimum grant duration, maximum image size);
- the Compute committee’s ACL.
State machine. Three command kinds:
SubmitRequest— a member submits aComputeRequest; accepted if the settlement evidence verifies.CommitGrant— the committee’s scheduler commits aComputeGrantmatching a request against a registered provider.AppendLog— a provider commits aComputeLogfor a completed grant (bonded under the module’s provider- side ACL).
Trust shape. Majority-honest committee for
scheduling integrity. Provider-level trust is separate
and carried in each provider’s own TicketValidator
composition; the Compute module does not vouch for
provider correctness beyond committing the match. A
malicious provider failing to actually run the image is
detectable by the requester (the workload’s own output
never appears) and can be scored into a reputation
organism orthogonally.
When to ship. When the coalition has citizens — AI agents in particular — that need programmatic compute acquisition. Agent populations benefit disproportionately: agents that can request compute on demand can top up their own resources and schedule their own experiments. See ai/compute for the agent-facing investigation.
When to skip. A coalition whose members bring their own compute out-of-band and never need dynamic allocation does not need a Compute module. An integrator-only coalition with no agent organisms typically does not need one.
What it is not.
- Not a compute provider. It is a scheduler-and- registry committing allocations; the compute runs on separate infrastructure.
- Not a payment rail. Settlement is folded into the request as evidence; actual value transfer happens off-protocol (on-chain, via a reputation/credit organism, via an external ticket authority).
- Not a guarantee of provider honesty. A provider can accept a grant and never run the image; the grant is the scheduler’s commitment, not the provider’s. Use a reputation organism to score provider behaviour.
- Not a cross-coalition marketplace. A Compute module is coalition-scoped; providers registered in one coalition are not visible to another unless they also register there.
Retirement markers
A cross-cutting primitive every commissioned confluence,
module, and coalition supports: before its committee
shuts down, the component commits a RetirementMarker to
its own public stream so integrators observing the stream
upgrade cleanly rather than receiving ConnectTimeout.
#[non_exhaustive]
pub struct RetirementMarker<'a> {
/// The Almanac tick (if the coalition ships one) or
/// wall-clock at which the committee ceases to
/// produce commits.
pub effective_at: RetirementInstant,
/// Optional pointer to the replacement component.
/// Integrators resolve it and rebind.
pub replacement: Option<ComponentRef<'a>>,
}
A retirement marker is the last commit on the stream. A
Chronicle entry records it at the coalition level as
ChronicleKind::ConfluenceRetired or
ChronicleKind::ModuleRetired.
Deriving a module’s identity
Every module is an organism; its derivation folds the
coalition root under a "module" segment:
ATLAS_ROOT = COALITION_ROOT.derive("module").derive("atlas")
ALMANAC_ROOT = COALITION_ROOT.derive("module").derive("almanac")
CHRONICLE_ROOT = COALITION_ROOT.derive("module").derive("chronicle")
COMPUTE_ROOT = COALITION_ROOT.derive("module").derive("compute")
<module>_committee = blake3(
<module>_root
|| ordered citizen references (if any)
|| module_content_fingerprint
|| module_acl_fingerprint
).derive("committee")
The "module" segment distinguishes coalition-scoped
components from commissioned confluences (which derive
without a coalition root). An operator reading peer-
discovery gossip can tell which is which at a glance.
CoalitionConfig helpers
Because modules have well-known names, the coalition
meta-crate ships typed helpers returning their
ConfluenceConfigs from a CoalitionConfig:
impl CoalitionConfig<'_> {
pub const fn atlas(&self) -> Option<&ConfluenceConfig<'_>> { /* ... */ }
pub const fn almanac(&self) -> Option<&ConfluenceConfig<'_>> { /* ... */ }
pub const fn chronicle(&self) -> Option<&ConfluenceConfig<'_>> { /* ... */ }
pub const fn compute(&self) -> Option<&ConfluenceConfig<'_>> { /* ... */ }
}
Each helper looks up a ConfluenceConfig in the
coalition’s confluences slice by name ("atlas", etc.)
and returns Some if found, None otherwise. A
coalition that ships the module names its
ConfluenceConfig accordingly; a coalition that does not
ship it omits the entry.
Integrators use these helpers to stay forward-compatible:
a coalition adding Almanac later does not break an
integrator that did not use it before, and the integrator
can start using it simply by re-reading
coalition.almanac().
Deliberately unspecified
- Chronicle retention policy and storage layout.
Operator-configured. The spec requires durability and a
monotonic
seq; it does not prescribe how operators achieve them. - Chronicle anchoring cadence and chain choice.
Per-coalition; the spec requires the anchor contract
address be folded into
ChronicleConfig.content. - Almanac tick cadence. The spec allows any state- affecting cadence; different coalitions will pick substantially different rates.
- Atlas metadata schema. Free-form
(key, value)pairs beyond the required fields. Operators add what they need; standardisation emerges from patterns over time. - Whether a module is required for any downstream
confluence. Confluences may depend on a module (e.g.
a correlator aligning to Almanac ticks), but the
blueprint does not require it; a confluence that needs
a module declares the dependency in its own
ConfluenceConfig. - Heavy-coalition extensions. Law, taxation, enforcement, mandatory citizenship — all deferred, all requiring a fresh proposal.
Cross-references
- topology-intro — rationale for the coalition rung.
- architecture — basic services in an example coalition.
- ticket issuance — the optional coalition-scoped issuance root.
- confluences — the generic shape every module inherits.
- composition — how a module’s subscriptions compose with the rest of the coalition.
- threat model — trust composition when a confluence depends on a module.