# 0008 — One log per customer, and four witnesses that verify them all **Status:** Accepted; built 2026-10-13 except the roster's logged admission events (below) **Supersedes in part:** [0003](0003-witness-policy-is-the-readers.md) — its *mechanism* (each reader names its own witnesses) is replaced by a standard policy over a formulaic roster; its *purpose* (no log names its own witnesses; no witness set anyone can change unnoticed) is kept whole and is the test this decision is written to pass. **Reverses one judgement in:** [0005](0005-pooling-is-an-optimisation-never-a-gate.md) — "pools of pools: no measured need exists." The need is measured here. **Builds on:** [0007](0007-a-witness-is-paid-for-the-watch-never-for-what-it-saw.md), whose formulaic roster is the roster here, and [0006](0006-ingest-is-an-interface-not-an-appliance.md), whose per-tenant publisher becomes the owner of a per-tenant log. ## Decision Two commitments, made together because each is what makes the other safe. ### One log per customer Every customer's publisher writes to its **own transparency log**, with its own checkpoints, witnessed separately. A witness refusal on one customer's log touches that customer's receipts and nobody else's. The per-customer log roots are pooled **one level up** into a single root anchored once per epoch — the "pool of pools" decision 0005 said composes and declined to build. Chain writes stay at one per epoch regardless of customer count. Each receipt carries one more inclusion proof, from its own log's checkpoint to the anchored super-root, and that is the whole of the added cost. The anchored super-root is a backstop, never the witnessed thing. A customer's receipt is valid on the strength of *its own log's* witnessed checkpoint; the super-root is only where that checkpoint's digest was written down somewhere nobody controls. A refused checkpoint on customer A's log is a bare digest in the pool like any other — pool leaves carry no attribution and the pool verifies no witnessing, per 0005 — and customer B's path from record to witnessed checkpoint never passes through it. ### Four witnesses verify every log There is **one published roster of four witnesses**, and it is the witness set for every customer's log. It is not a body. There is no organisation, no membership, no governance, and nothing for anyone to join or run — four parties, each with no role in the energy market, each running the verification function against every log. Nobody chooses them: 1. **The roster is formulaic**, exactly as 0007 already requires. A witness that passes `scripts/check_witness.py`, meets the no-role-in-the-energy-market test, and stays within the published availability and probe-accuracy formula is on the roster. Nobody admits a witness and nobody removes one; the criteria do. 2. **Every admission and removal is a logged, public event** carrying its measured cause. The roster is itself a record in the substrate's own terms: append-only, checkable, and impossible to alter without it showing. 3. **The standard policy is two of the four, from distinct operators.** A checkpoint is witnessed when two witnesses, not run by the same operator, have cosigned it. Never one alone. Four is the whole roster — a single witness follows two hundred logs with sixteen milliseconds of CPU an hour, so the count is set by the policy and not by load. Why two and not four: at the 99.5% availability gate each witness is down about 44 hours a year, and requiring all four would leave the substrate without a witnessed checkpoint for about seven days a year; two-of-four leaves it under a minute. Why four and not three: three has no headroom — one departure leaves two with both required and the quorum-absent time jumps to 88 hours a year — while four survives a departure at two-of-three and under 40 minutes. Two is also the number Certificate Transparency policies settled on, for the same reason. 4. **Readers adopt the standard policy by contract**, and a contract that adopts the receipt adopts the roster with it. Neither party to an agreement picks a witness. A reader may *add* named witnesses to the standard — 0003's right survives as a floor — and may never go below it. `WitnessPolicy(required, quorum)` in `service/deployment.py` already expresses a named set plus a quorum. The standard is that mechanism with the roster as the set and two as the quorum, applied per log. The change is what the set defaults to, not the shape of it. ## What prompted this Three things, in the order they arrived. **Favouritism.** Under 0003, the offtaker in a tolling agreement names the witnesses whose signatures it will accept. In a dispute, the operator's first line is now available: *of course your witness signed against me.* The record becomes one more contested item, which is the condition the record exists to end. Four witnesses that neither party chose remove the line. **Coordination.** A receipt that is *the rule both counterparties live by* — the growth model in business-model.md — spreads as a standard, and a standard with a negotiable witness list is a negotiation. Every contract would carry its own roster, every verifier its own keyring, and the thing being sold would be different in every deal. **Blast radius, checked against the code.** The deployment has one `log`, and a checkpoint is a signed tree head over every entry in it. A witness refusal is therefore log-wide — and it should be, since every reason to refuse (rollback, equivocation, rewritten history) is a fault in the log, not in a record. But it means one customer's incident freezes witnessed receipts for every customer on the substrate until it is resolved. A customer buying a receipt is buying evidence about *its* performance. It should not lose that evidence because of somebody else's publisher. ## The reasoning **Why the roster does not fail 0003's test.** Decision 0003 rejected "a protocol-level witness registry" for one stated reason: it "would make the set an operator or a governance body could change without any reader noticing." The objection was never to a shared list. It was to *control* and *invisibility*. A roster that nobody controls, because admission is a published formula, and that nobody can change quietly, because every change is a logged event, has neither property. Whoever wrote the formula stops mattering once the formula is public and versioned — the same move 0007 made about the payer. **Why "four witnesses" and not a body.** A body has members, and members have an interest in the body's standing, which is a stake by another name; a body has governance, and governance is a chooser, which is what 0003 forbids. Four witnesses on a formulaic roster have neither. Nothing exists between the witness and the log but the published criteria. The word *consortium* was used in an earlier draft of this record and withdrawn for exactly this reason: it named an organisation the design must not have. **Why two of four is not the "quorum alone" 0003 dismissed.** 0003 said a bare quorum is satisfiable "by any *n* parties the operator can produce," and it was right. That objection dies the moment the operator cannot produce roster witnesses — which is what formulaic membership means. What remains is the weakest-link problem: if one witness suffices, compromising one validates every receipt. Certificate Transparency reached the same place and requires SCTs from logs run by distinct operators. So: two of four, distinct operators, never one. **Why the standard helps 0007, not only 0003.** Under two-of-four no single witness can protect the substrate's revenue by rubber-stamping, because one signature validates nothing. The pressure toward assent that 0007 is built against moves off the individual witness and onto the four collectively — and a refusal that the honest witnesses agree on is a refusal that is supposed to bite. The structure does part of the work the payment formula was doing alone. **Why per-customer logs, and why they need the standard roster.** With one shared log, per-customer receipt independence is not achievable by policy: a receipt's validity rests on a witnessed checkpoint, and a checkpoint covers the whole log. Separate logs are the only way. But separate logs under 0003's mechanism would be separate *witness negotiations* — two hundred logs with two hundred reader-chosen witness sets. The standard roster is what makes two hundred logs one system: the same four witnesses, the same quorum, the same verifier configuration, for every one. **Why the anchor cost does not return.** Phase 2 measured it: one publisher anchoring an hourly root is 8,760 chain writes a year and $7 to $6,174 at observed fees; a thousand publishers each anchoring their own is 8.76 million writes and back in the untenable range. Two hundred customer logs each anchoring separately would be 1.75 million writes, $7,000 to $1.2 million. Pooled one level up, it is 8,760 again. Decision 0005 built the first pooling level and said the second could be built when there was a measured need. This is the measured need. **Why the extra proof level is acceptable.** Every receipt gains one inclusion proof — a handful of digests — from its own log's checkpoint to the super-root. 0005 named this as the cost of any additional level. Against per-customer isolation it is cheap, and it is paid once per receipt rather than once per epoch. ## What was rejected **Any one witness suffices.** Weakest link. Rejected above. **A witness body of any kind** — a consortium, an association, anything with membership and governance, whether admitted by the log operator or self-governed. Both reintroduce a chooser, which is what 0003 forbids and what 0007's formulaic roster was designed to remove; a self-governing body additionally has an interest in its own standing, which is a stake. **Three witnesses.** Enough for load — one is enough for load — and no headroom: one departure leaves two-of-two and 88 hours a year without a quorum, while admission is formulaic and takes time. Four costs one more witness at the 0007 base and buys the headroom. **Per-customer receipt independence on the shared log, by policy.** Not possible; see above. **Per-customer logs each anchored separately.** 0005's arithmetic. Rejected. **Keeping one shared log and accepting log-wide refusals.** They *are* the correct behaviour for a log that rewrote history. But a customer should not be exposed to another customer's publisher, and with per-customer logs the correct behaviour and the isolation are both had. **Reader-named witness sets as the default.** Retained only as an addition a reader may make on top of the standard. As the default it is the favouritism and coordination problem this decision exists to remove. ## What this changes **Code.** `DeploymentSpec.log` becomes a log per publisher; `publisherd` writes to its own; `poold` gains the second level; `receipt.py` carries the extra proof; the standard policy becomes the default `WitnessPolicy`. `witnessd` already follows many logs and needs nothing. Built 2026-10-13; see the section at the end. **Documents.** Every place that describes a reader choosing its witnesses now describes a reader adopting the standard roster. That is [specification.md](../specification.md), deployment.md, [witness-quickstart.md](../witness-quickstart.md), witness-outreach.md, business-model.md and the public site. They were rewritten when the code was built, 2026-10-13. **The product statement.** What Contubernium sells is a receipt log verified by four independent witnesses, which helps counterparties minimise contractual disputes. The witnesses are the product, not the plumbing, and decision 0004's first independent witness is the first of the four. ## What this does not settle **Diversity criteria beyond "distinct operators."** Jurisdiction, institution type and code build are all plausible terms in the admission formula. Four witnesses in one country running one build have one operator's worth of independence whatever the count says. Open, and to be set from what the first four actually are. **One super-pool or several.** Regional pools, or pools by segment, would bound the anchoring dependency further at the cost of more roots. Not needed at two hundred customers. **Witness load at scale.** Two hundred logs is trivial for a container. At tens of thousands the fetch pattern needs measuring, and the answer may be that the four witness the super-root as well as the leaves. **Reversal conditions.** If formulaic admission cannot produce four witnesses from distinct operators, the standard policy cannot be met and reader-named sets return as the default, with the reason recorded. If probes show correlated failure across witnesses — the same wrong answer from the same bug — the diversity criteria tighten before anything else changes. If the extra proof level proves costlier in receipt size or verification time than the isolation is worth to customers, collapse to one log and accept log-wide refusals as the correct behaviour they are. ## Built — 2026-10-13 **What exists.** `PublisherSpec.log` gives a publisher its own log, and the shared log becomes the anchor log. `poold.SuperPoolService` is the second pooling level: a customer log's checkpoint digest is a bare leaf, the root is anchored once per epoch in the anchor log, and the roster is asked to cosign that anchoring. A publisher submits its checkpoint after it has published and never waits on the answer, so the super-pool is a backstop and cannot gate; a receipt whose epoch was sealed carries the bundle as `contubernium.receipt.v2`, and a fourth verification link, *backstop*, checks it offline. `monitor.standard_policy` and `DeploymentSpec.policy()` are the standard: two of the roster from distinct operators, additions allowed, a lower quorum refused or read as the standard. The demonstration has four witnesses, two customer logs and a super-pool, and `tests/test_customer_logs.py` shows each claim above: a rewritten customer log is refused by every witness while the other customer's reads still establish; two customers cost one anchor write; a doctored backstop fails its own link and nothing else; a dead super-pool leaves publication and a complete receipt intact. One change was forced rather than chosen. A log restamped its checkpoints after a restart, which did not matter while nothing anchored a checkpoint; with checkpoint digests as super-pool leaves, a restart would have re-anchored history. A log now keeps the instant each tree size was first stamped beside its entries. **What does not exist yet, stated so nobody reads the code as more than it is.** - *The roster is the deployment's witness list plus its external witnesses.* Admission by the published criteria and **every admission and removal as a logged, public event** are not built. Until they are, the roster can be changed by whoever edits the description, which is the property 0003 forbids, and that is the first thing to build next. - *Distinct operators are counted only outside a demonstration.* With one operator running every node the standard cannot be met, so the demonstration counts witnesses and says why. - *Monitors follow the anchor log only.* Customer logs are audited by the four witnesses, which check consistency on every cosignature; a monitor following every customer log is not built. - *On a restart the super-pool may seal a republished epoch afresh*, with the customer log's then-current checkpoint. That is a true statement rather than a duplicated record, and the persisted-restart check counts customer logs for that reason. - No outside party runs any of the four witnesses. Decision 0004's third condition is no nearer discharged by this build than it was before it.