Chio/Docs
LOGIN · JOIN

Coordination Contract

Run three trust-control nodes as one control service, and know which state they share and which each node keeps.

Concept chio@5f63e6e

On this page

Three trust-control nodes can serve one operator’s kernels as a single control service. Each node picks a leader from the peers it can reach and sends covered writes there, while a sync loop repairs every node’s stores from its peers.

The guarantee class is leader-local: deterministic leader selection, single-writer local truth, eventual repair. The figure follows three nodes, A, B, and C, as one of them stops and another is cut off.

Each node routes covered writes to the leader it computes

A node sorts its own URL together with its healthy, unpartitioned, freshly contacted peers. Once that set is a majority of the configured cluster, the lowest-sorted URL is the leader.

Leader termsChoose a scenario.
term 1 · leaderterm 1 · follows Aterm 1 · follows AnAnode AnBnode BnCnode Cterm 1leaderterm 1follows Aterm 1follows AnAnode AnBnode BnCnode C

The lowest-sorted node a quorum can see leads

Each node counts itself and the peers it reached within the lease TTL, then selects the lowest-sorted URL once that set is a majority of the configured cluster. All three nodes see each other, so all three select A at term 1. Every computation that holds quorum restamps the node’s lease to three sync intervals ahead. Leader & Failover.

Leader selection on three trust-control nodes over twelve sync rounds at the default 500 ms interval, so a lease lasts three rounds. The rounds and writes are illustrative; forwarding from followers to the leader is left out.Leader & Failover

Quorum is peers.div_ceil(2) + 1, so a three-node cluster needs two. A lease is three sync intervals, clamped between 500 ms and 5 s, and every computation that holds quorum restamps it. Any change of leader, including a change to no leader, advances that node’s local term.

A node below quorum names no leader and answers a covered write with 503 before its handler writes. Its reads still answer from its own stores, so a read can succeed while the next covered write is refused. After a partition heals, the node selects the majority’s leader again and catches up from a snapshot.

Selection names a route only: whether the leader’s stores are current and whether it holds the active signing seed are separate checks, covered in Replication & Convergence and Authority & Rotation.

Read more in Leader & Failover.

A node joins as a peer, as a client, or stands alone

Membership comes from configuration. What a process is started with decides whether it pulls replication, takes part in leader selection, and counts toward a budget witness.

  • Trust-control peer. chio trust serve with --peer-url, --advertise-url, and an authority database. It keeps peer state, pulls replication data, selects a leader from its own view, and can witness a budget event.
  • Kernel using remote stores. Started with --control-url and --control-token set to the admin service token, it makes authenticated client requests. It receives no peer deltas and contributes no budget witness.
  • Standalone service. With no effective peer URLs, the service uses its local state and runs no cluster runtime.

Each peer URL is normalized, and a node removes its own URL from its peer set. Local or private peer addresses need --allow-local-peer-urls. Clustered authority lives in --authority-db; a peer configuration with --authority-seed-file is rejected at startup.

Read more in Trust Control Plane, which starts a node.

Replication shares state; each node keeps its own rules

Peers replicate the state an admission reads. Policy, guard code, and node configuration load on each node and stay there.

StateShared across peersHeld by each node
Trust controlleader selection, forwarded writes, repairits stores and local term
Budget exposuremutation history, per-event witnessexposure it admitted before a merge propagates
Receiptssigned receipts, child receipts, lineagesequence positions, claim-log checkpoints
Policy and guardsnonepolicy files, guard modules, configuration

Sharing an authority identity says nothing about which rules each node loaded. Roll policy out with a coordinated policy rollout and check each deployment on its own. The guarantee classes come from CHIO_BOUNDED_OPERATIONAL_PROFILE.

Versioned holds under /v1/budgets/holds/ run on the joint budget-and-revocation authority that --session-db selects, and a peer-URL configuration rejects that flag. On a peer cluster the hold routes answer 503 and the exposure routes carry budgets. Choose the budget architecture before you add peers; Budgets Across Nodes compares the two.

A budget write commits when peers acknowledge its exact event

A clustered budget write shows every part of coordination in four steps.

  1. Select. The receiving node computes its leader from its own reachable view, as above.
  2. Gate and forward. A leader-forwarded handler refuses with 503 when quorum, the lease, or a leader is missing. The gate covers the handlers that call it.
  3. Record and witness. The leader records the mutation, then waits until enough peers acknowledge the write’s origin through a contiguous event sequence.
  4. Repair. The sync loop pulls budget history, receipts and lineage, and revocations from every peer.
Replicated logChoose a view.
replicated on each nodeBbudget pool BnAnode AwriternBnode BpeernCnode Cpeerorigin A · budget mutation events55charge USD 2.0056settle USD 1.4057charge USD 0.6058charge USD 1.20writes 58ack 58ack 572 of 3 hold 58 · quorum 2 · committedBpool BnAnode AnBnode BnCnode Corigin A · budget mutation events55charge56settle57charge58charge585857write, acks2 of 3 hold 58 · quorum 2 · committed

A budget write commits when a quorum holds its own origin’s event

Node A writes event 58 to pool B’s mutation log and counts itself. Node B has acknowledged origin A through 58 and counts; node C has acknowledged only through 57 and waits. Two of three meet the quorum of two, so the write reports quorumCommitted. A head is the last event before the first gap, and only an acknowledgment for the write’s own origin counts. Budgets Across Nodes.

One origin’s log on three trust-control nodes: each row is an entry with its index, and a filled dot is a row that node holds. Indices, amounts, and capability ids are illustrative; tool receipts, child receipts, and lineage, whose sequences may contain gaps, are left out.Replication & Convergence

An acknowledgment head is the last same-origin event before the first gap, so a peer counts only once it holds that event. A peer awaiting a forced snapshot never counts. Pulls take dense pages from the cursor’s successor, up to 64 pages and 200,000 records per peer visit, and revocations get a fresh allowance so budget churn cannot starve them.

On a witness timeout, a new exposure authorization attempts a compensating local reversal. Replayed or already-captured authorizations keep their admission, and capture, release, and reconcile can answer 503 with the local mutation still applied. Treat a failed response as unknown and read the budget write lifecycle before retrying. A successful witness check describes replication of that one event; the clustered guarantee stays advisory_posthoc.

Coordination health is read beside process health

A responding service can have no leader. GET /health reports ok: true on a node that has lost quorum, so read its cluster object too. This node is the partitioned one in the figure.

Terminalbash
curl -s http://127.0.0.1:8940/health \
  | jq '{ok, clustered, cluster: .cluster
        | {role, hasQuorum, quorumSize, reachableNodes, leaderUrl, electionTerm}}'
Output
{
  "ok": true,
  "clustered": true,
  "cluster": {
    "role": "candidate",
    "hasQuorum": false,
    "quorumSize": 2,
    "reachableNodes": 1,
    "leaderUrl": null,
    "electionTerm": 2
  }
}

Alert on hasQuorum, role, and leaderUrl, gated on clustered: a healthy standalone service also reports hasQuorum: false.

A reachable peer can still be ineligible to witness. When budget writes time out with every peer reachable, read forceSnapshot, snapshotAppliedCount, and the acknowledgment heads on the authenticated /v1/internal/cluster/status route.

A kernel on remote stores stalls on the service

A kernel using --control-url depends on remote receipt writes, revocation reads, and authority responses. Its sidecar readiness probe checks its own attached receipt store and leaves those remote calls unexercised. Budgeted remote receipt writes use a bounded worker pool and queue; other remote operations use the HTTP client’s timeout. A caller that timed out cannot conclude its submitted write was canceled.

Monitor remote failures and latency as well as local readiness. Node State explains the bounded writer and why a write can complete after its caller’s deadline.

Nodes can disagree for a while, inside one operator’s domain

Coordination keeps each node’s records and repairs replicated state under the contracts above. There is no single global transaction history: for a while, nodes can disagree about leadership, revocation visibility, or budget exposure, and receipt replication leaves each node’s checkpoints local.

Until a merge propagates, exposure admitted independently on each node is bounded by overrun <= max_cost_per_invocation × node_count. The bound is arithmetic over a worked scenario and covers admitted exposure; realized external spend is a separate quantity. Read its assumptions in Budgets Across Nodes before planning capacity with it.

A cluster serves one operator’s trust domain. Work between independently operated identities belongs to Swarms and Federation.

Internal control-plane routes

Peers call these routes for status, replication, and partition controls. The list is generated from the Chio router; kernels and operator tools use the public routes instead.

RouteMethodsHandlers
/v1/internal/admission-authority
POST
handle_admission_authority
/v1/internal/authority/snapshot
GET
handle_internal_authority_snapshot
/v1/internal/budgets/delta
GET
handle_internal_budgets_delta
/v1/internal/cluster/partition
POST
handle_internal_cluster_partition
/v1/internal/cluster/snapshot
GET
handle_internal_cluster_snapshot
/v1/internal/cluster/status
GET
handle_internal_cluster_status
/v1/internal/lineage/delta
GET
handle_internal_lineage_delta
/v1/internal/receipts/children/delta
GET
handle_internal_child_receipts_delta
/v1/internal/receipts/tools/delta
GET
handle_internal_tool_receipts_delta
/v1/internal/revocations/delta
GET
handle_internal_revocations_delta

Peers authenticate under their own scheme, chio.cluster.peer.v1, and the operator credential opens none of these routes. A peer credential authenticates membership in the operator’s trust domain; evidence of which peer wrote a record comes from the signed receipts. Cluster Peer Auth documents the request binding and credential checks.

Next: watch a leader change hands