Criteria for the Integrity of Transaction Processing
The written definition of what “behaving correctly” means, against which
an independent practitioner can perform procedures and report findings.
Short title Integrity Criteria
Subject matter tx-rails transaction processing, peer discovery, deployment boundary and origination
Criteria groups 6 worked · 34 criteria · 10 exclusions
Version 0.4 — draft
Status not yet adopted
Subject matter tx-rails transaction processing, peer discovery, deployment boundary and origination
Criteria groups 6 worked · 34 criteria · 10 exclusions
Version 0.4 — draft
Status not yet adopted
How to use this document
§4 to §10 are worked in full with real entries. Every check ID, registration, status and gap
The six criteria groups are drawn from different places, and the difference matters when reading a
§4 to §10 are worked in full with real entries. Every check ID, registration, status and gap
in them was verified against the code, not illustrated. §1, §2, §11 and §12 remain
sample content, marked as such, and are meant to be rewritten by whoever adopts this.
Appendix A is a blank section to copy for each further criteria group.
The six criteria groups are drawn from different places, and the difference matters when reading a
finding:
- §4 Initialisation and §5 Evidence integrity come from the live check set and from
defects already found and fixed on this estate. - §6 Peer discovery, §7 Integration mode and data visibility,
§8 Federation boundary and settlement regime and §9 Machine origination come from the
four parts of the platform’s own architecture material — peer discovery and minimal DNS;
integration modes and the data-visibility ladder; the federation trust model, deployment shapes and
the three transaction regimes; and machine-originated transactions. Each claim there was read back
against the code before it was written as a criterion, which is what §10.4 records.
- Keep the five-column shape. It is what makes a criterion testable rather than merely stated.
- Cite check IDs; never paraphrase what a check does. The code is the definition. A criterion
that restates it will drift from it, and nothing will be comparing the two. - Anything not covered goes in §10. A criteria list with no exclusions section silently asserts it is complete.
- A pitch is not a source. Four criteria groups here were extracted from material written to
persuade. Every sentence of it was checked against the code first, and one claim did not survive
that check (§10.4). Extracting criteria from architecture material is a good way to find out what
the system does; it is not a way to find out what is true.
1 · Purpose and intended users
Sample content — rewrite
This document states the criteria against which the integrity of transaction processing in
The intended users are the engaging party (ITOTCCA), an independent practitioner engaged to
Within the engaging party the officer responsible for this subject matter is the
Nothing here is an opinion about the platform. Each criterion is a statement that is either
This document states the criteria against which the integrity of transaction processing in
tx-rails is to be evaluated. It exists so that a party outside the operator can form a view
of whether the platform behaved correctly without relying on the operator’s assurance
that it did.
The intended users are the engaging party (ITOTCCA), an independent practitioner engaged to
perform procedures against these criteria, and any counterparty to whom the resulting report
is provided. It is not written for the general public and is not a marketing document.
Within the engaging party the officer responsible for this subject matter is the
executive director of cyber-security. That role owns this document — it is the approver
named in §12 — and owns custody of the key material the criteria depend on, including the
validator signing keys held alongside snapshots.
What the role cannot be
The executive director of cyber-security is an officer of the engaging party. That is
Personnel do not cross. The arm’s-length party operating the auditor tiers
The same boundary decides a question that will be asked: whether the auditor tiers could sit
The executive director of cyber-security is an officer of the engaging party. That is
the role’s usefulness here and equally its limit. It can own the criteria, hold the keys,
and answer for the estate’s response to a finding. It cannot supply the independence the
report depends on, because independence under the framework is independence from the
responsible party, and this role is part of it.
Personnel do not cross. The arm’s-length party operating the auditor tiers
holds no role inside ITOTCCA — decided 2026-09-03 on risk-exposure grounds, and recorded here
because it is the kind of arrangement that is easy to concede quietly later. It is also the
load-bearing one: under IAS 24 a person who is key management personnel of both entities makes
them related parties by definition, so a single shared officer would make the words
arm’s length false as a description rather than merely weak as a safeguard.
The same boundary decides a question that will be asked: whether the auditor tiers could sit
under this role. They could, and the criteria in §4 to §9 would be unaffected — but
their findings would remain operator-produced, which is precisely the property EVID-06
exists to name. That is not a defect and it is not a substitute. It means the independence has
to come from the engaged practitioner and from a reader’s ability to reproduce a result
without asking the operator for anything — never from the org chart.
Nothing here is an opinion about the platform. Each criterion is a statement that is either
met or not met on a given date, and the document is written so that the difference is
decidable by someone who did not build the system.
Why this section matters
Under an assurance framework the criteria must be relevant to the intended users’
Under an assurance framework the criteria must be relevant to the intended users’
decision. Naming those users here is what makes relevance assessable rather than assumed —
and it is the section that stops the criteria drifting into things that are merely easy to measure.
2 · Subject matter and scope boundary
Sample content — rewrite
In scope. The processing of transactions by the tx-rails validator mesh: their
Out of scope, deliberately. The correctness of the data supplied to the platform.
Also out of scope. Availability, latency and throughput; the security of participants’
Scope varies by integration mode, and this is the trap worth naming. The platform accepts
The specific misreading to guard against:
In scope. The processing of transactions by the tx-rails validator mesh: their
admission, ordering, commitment to the ledger, and the trace records written as a
consequence. The criteria address whether the mesh’s replicas agree, whether records
are complete, and whether what was recorded can be shown not to have been altered.
Out of scope, deliberately. The correctness of the data supplied to the platform.
tx-rails records what it is given; it cannot establish that a submitted valuation, hazard
report or payment instruction is truthful. A criterion that appeared to cover this would be
the most damaging kind of error in this document, because it would offer a reader assurance
that no mechanism here can support.
Also out of scope. Availability, latency and throughput; the security of participants’
own systems and client devices; and the conduct of the parties whose transactions are recorded.
Scope varies by integration mode, and this is the trap worth naming. The platform accepts
transactions under four integration modes carrying different evidence. Under the hash-only mode
the customer computes a hash of a transaction that already executed in their own system and sends
only that hash; the platform never sees the content. That customer’s executed / committed /
aborted lifecycle is therefore not merely unrecorded but structurally unknowable, and no
criterion below reaches it.
The specific misreading to guard against: trace.tx_outcome does hold a
committed-or-aborted row for such a transaction. That row records whether our attestation
committed on our chain — not the customer transaction it attests. Reading the first as an
answer to the second would let a criterion appear to cover ground that no mechanism reaches.
Subject matter added in version 0.2 — and the boundary that came with it
Version 0.1 scoped this document to the validator mesh. §6 to §9 extend it outward in three
directions the mesh does not reach: who a node talks to before consensus applies (§6),
which deployment boundary a transaction crosses and what agreement it rests on when it
crosses a border (§8), and what may originate a transaction without a person (§9). §7 sits
across all of them, because what any criterion can reach depends on how the transaction arrived.
These are in scope because a reader forming a view on transaction integrity cannot stop at the
mesh: a transaction admitted by an unverified peer, coordinated across a boundary it should not
have crossed, or originated by a compromised device is not made sound by replicas agreeing about
it afterwards. Every criterion in §4 and §5 assumes those questions were already answered.
What did not come into scope with them. Nothing here evaluates the commercial or
jurisdictional argument the deployment shapes are sold on — that hardware separation satisfies a
given regulator, or that a given topology discharges a transfer obligation. FED-06 states only
that pyramids share no validator, which is a fact about a validator set. Whether that fact
satisfies a data-protection regime is a legal question, and a criterion that appeared to answer it
would be the same error §2 already names, wearing different clothes.
Drafting rule
Scope boundaries cannot be tabulated — a table of criteria implies its own completeness, and
Scope boundaries cannot be tabulated — a table of criteria implies its own completeness, and
only prose can say what was left out and why. Write the exclusions before the criteria,
while it is still obvious what you decided not to attempt.
3 · How to read a criterion
Every criterion is one row. The columns are a contract, and each exists to
prevent a specific failure in the document itself.
| Column | What goes in it | The failure it prevents |
|---|---|---|
| ID | A stable identifier, e.g. INIT-01. Never reused, never renumbered. |
A practitioner must be able to report “criterion 14: performed, no exception”. Renumbering silently invalidates every report already issued. |
| Criterion | One sentence stating what must be true. No justification, no argument. | Prose invites advocacy, and advocacy is what disqualifies criteria as neutral. |
| How it is tested | The check ID that tests it, or the named manual procedure if there is none. | A criterion with no test is an aspiration. Naming the test makes the difference visible. |
| Evidence produced | The artefact a practitioner can inspect and retain. | A test whose result is not retained cannot be reported on after the fact. |
| What a failure looks like | The concrete observable state when the criterion is not met. | The column that does the real work. It is what stops a criterion being written that cannot fail — “the system maintains the integrity of records” passes every year and means nothing. |
Two rules that keep this honest
- Cite, don’t paraphrase. The How it is tested cell names a check ID; the check’s own
source comment remains the definition of what it does. Every citation carries the claim it makes —
data-claim="registered","unregistered"or"vacuous"— and
TestCriteriaCitationsMatchTheRegistryincmd/chubbychecker-joint
verifies each against the live registry on every build.
It checks both directions. A test asserting only that cited checks exist would pass happily
while §10 told a reader something was uncovered long after it was implemented — an understated gap
is still a false statement to the practitioner relying on it. - A registered check is not a working check. Coverage counts are taken from registries, and a
check that returns success unconditionally is counted the same as one that tests something.
§10.2 records where that is currently true, by name — thirteen of the one hundred and thirty. - An unmarked citation is a citation the guard cannot check. Some mechanisms this document
relies on live outside the registry the guard composes — a check in another checker’s set, a
constructor, a build gate. Those are cited in<code>rather than as a claimed
check ID, on purpose. Marking them would assert a verification that never runs, which is worse
than not marking them at all. FED-01 is the case where this matters most, and it says so in place.
4 · Criteria — Initialisation
The state that must hold before the mesh processes any transaction: that nodes are
who they claim to be, that they are running the same schema, that no single party controls
admission to the mesh, and that the machinery which makes later comparison possible was switched
on before there was anything to compare.
Failures here are distinctive because they are silent and retrospective: nothing
alerts, and the consequence only becomes visible much later, when a question is asked that the
records can no longer answer.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| INIT-01 | A transaction is processed by the node its metadata names, and by no other. | cc012 “Node Identities”, a per-transaction check, registered in checks-joint.implemented |
Check verdict stream; the signed finding attestation covering the block-height window. | A committed transaction whose declared node ID differs from the node that processed it. Raised as a check failure naming both. |
| INIT-02 | Every node in the mesh carries an identical database schema. | cc085 “Schema Drift” per block; cc120 “Schema Evolution” in the integrity set. implemented |
Check verdict; the per-node schema comparison the check performs. | Two nodes report different schemas — characteristically after a migration that succeeded on some nodes and not others, which does not otherwise announce itself. |
| INIT-03 | Admission to the mesh does not depend on too few bootstrap peers. | cc010 “Overcentralization”, a block check in the integrity set. implemented |
Check verdict, including the count of distinct bootstrap peers observed. | The distinct peer count falls below the configured threshold, leaving one party able to determine who joins the mesh. |
| INIT-04 | The commitment key is provisioned on every replica before the first trace row is written. | No check. Deployment-time evidence only: TRACE_COMMIT_KEY_FILE set on eachreplica, and a non-zero row count in trace.org_trace_commitment on each.manual procedure — no automated test |
Pod environment as deployed; per-replica commitment row counts, captured together in one pass. | The variable is unset, the committer is absent, and commitments are simply not written. This does not error at start-up by design — unset means off. The only observable is a zero count, so absence must be looked for; it will never announce itself. |
| INIT-05 | Bootstrap peers are addressed by IP literal, not by name. | cc001 “DNS Reliance”, a per-block check. implemented 2026-08-31 — previously registered and returning success unconditionally. |
Check verdict, naming each peer addressed by name and the total examined. | Any bootstrap peer given as a hostname. A peer address is the first thing a joining node trusts — it decides who tells that node what the chain is — and DNS is unauthenticated here, so whoever answers the name chooses that peer before consensus has any say. An unparseable address counts as a finding, not a skip: the one address whose resolution path is unknown must not be the one the check ignores. |
Note on INIT-04
It is deliberately included even though nothing tests it automatically. A criterion that matters
It is deliberately included even though nothing tests it automatically. A criterion that matters
and has no test belongs in the register with that stated, not omitted until someone builds the
test — omitting it would make the gap invisible, which is the opposite of what the register is for.
The How it is tested cell is where that distinction lives.
5 · Criteria — Evidence integrity
Whether a result means anything. These criteria are drawn from defects already found
and fixed on this estate, and they share one shape: status was treated as evidence. A service
was running, a unit was active, a charm said ok — and none of those things had been
earned.
They belong in a criteria document rather than a defect log because each describes a
property a practitioner can test, and because the failures were invisible precisely to the kind of
inspection a reader would otherwise rely on. A chain sat halted for roughly a day with every pod
Running and every unit active. An audit tier streamed zero blocks since the day it was deployed
while reporting BFT mesh active (ok). Nothing was broken in any way that
looking would reveal.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| EVID-01 | A checking cycle that could not run its checks does not report a pass. | RunContinuousChecksSummary, which separates ran / failed / could-not-run /not-applicable. Used by chubbychecker-governance, chubbychecker-registryand — since 2026-08-31 — chubbychecker-joint.implemented on every checker |
The cycle’s own summary line, stating how many of how many checks actually ran. | A tier logs checks passed in the same cycle in which checks failed on missing schemas. The corrected form states it outright: NOT A PASS — 3 of 3 continuous checks could not run, against checks passed (4/4 ran) elsewhere. Same binary, opposite verdicts, both true. |
| EVID-02 | Liveness is established by movement, not by reported status. | audit-liveness-probe.sh — samples every chain and every auditor twice andrequires the position to have advanced. operator script, not in the repository |
Two sampled positions per node with their timestamps, retained together. | The position is unchanged between samples, or the node is unreachable. Unreachable is a failure, never a skip — the original defect was that an unanswered node was simply omitted, and a liveness result over the nodes that answered always looks alive. |
| EVID-03 | Every ABCI application reports its true applied height at handshake. | k3d/ops/abci-info-guard.sh — fails the build if any served ABCI applicationdoes not override Info().implemented as a build gate |
The build gate’s own result, per release. | An application embeds types.BaseApplication and inherits its answer of“height 0”, so consensus replays every committed block on every restart — measured at ~172,900 blocks and about 3.3 hours for a single node — while the service is active, nothing is logged, and the charm reports healthy. The node is simply not committing. |
| EVID-04 | An applied-height watermark never moves backwards. | No automated test. The write uses SQL GREATEST so a replay cannot lower it.construction only — no test |
The recorded watermark, sampled before and after any restart. | A replay re-applies old blocks and overwrites the watermark with its own lower position. Observed: a node seeded at height 66599 was sent back to the start by its own replay. |
| EVID-05 | Independent recorders hold a fingerprint of a submission, never its content. | No automated test — a property of what the interceptor transmits. design property — no test |
The recorder’s stored rows, inspected for payload fields. | A recorder holds the actual business payload. This discloses nothing new to the customer, whose content the platform already holds — the harm is that it places a second copy in a different party’s custody, carrying every disclosure obligation the original carries and worth more to an attacker than the ledger. Detection is unaffected: any change to a field, including renaming or reordering, changes the fingerprint. |
| EVID-06 | What was submitted is attested alongside what the validators recorded. | cc131 “Baseline Commitment Anchored”, a per-block check. registered 2026-08-31 |
The gateway tier’s signed commitment for the slab covering each height, verified against a key resolved by agreement across replicas. |
A transaction reached consensus with no baseline at all — meaning something was executed that the gateway tier never saw. Or the commitment’s signature does not verify, or it is bound to a different slab than the one it was stored against, which is a replay of a genuine signature onto the wrong range. Absence of any commitment is not a failure: two tiers are paired with a baseline recorder — the national gateway tier (gw0–3 with bi0–3) and the overseer tier (overseer0–3 with ovbi0–3, paired 2026-09-01). Elsewhere a missing commitment is recorded as commitment-weak by design, so this criterion bites only where a recorder existed to have seen the submission. |
| EVID-07 | A tier’s application state is bound into the block its validators sign. | The tier’s app-hash function, evaluated in FinalizeBlock and returned asthe block’s AppHash: get_current_aggregator_app_hash,get_current_registry_app_hash, get_current_governor_app_hash,get_current_overseer_app_hash. Enforced by consensus itself rather than by acheck — a validator computing a different digest cannot commit the block. four tiers; overseer tier from height 130,000 |
block_app_hash read from every validator in the mesh at one common height.The values must be non-empty and identical. A digest that is constant across many heights is not a fault: it changes only when the state it covers changes, so an idle tier legitimately repeats one value. |
Two validators hold different application state while agreeing on every block — the divergence every other criterion in §5 assumes it would see, silently absent. The introduction of an app hash is itself the hazard it must survive: adding one changes the digest of an already-running chain, so it is height-gated — every node is given the same future height, rolled inert, and switches together. Whatever the application returns it must also record: an overseer node returned the digest correctly for a day while never persisting it, which left the whole tier unable to restart — the handshake compared the state’s real digest against a hash of nothing and panicked. A tier that runs perfectly and cannot be restarted is one power-cycle from an outage. And a hash that cannot be computed is never returned empty: the node halts instead, because an empty AppHash from one node while its peers send the real one is a fork produced by the safety mechanism itself. |
Why EVID-06 is the load-bearing one
Every other anchoring criterion verifies the validators’ own account of what happened — block
Its key resolution is quorum-based for a specific reason: the check verifies a signature against
Every other anchoring criterion verifies the validators’ own account of what happened — block
hashes, trace roots, slab anchors, all produced by the nodes being audited. The baseline is
captured before any validator sees the transaction, and is the only record in the system not
produced by the party it polices.
Its key resolution is quorum-based for a specific reason: the check verifies a signature against
whatever key it is given, so a single replica able to answer alone could supply an attacker’s
key and make an attacker-signed commitment verify — handing that replica the power to forge the
very attestation the check exists to police. Replicas that disagree about a registered key are
refused rather than resolved to a majority, because the disagreement is itself the finding.
Why these are criteria and not merely history
Each was found by asking a question and following it into the code, not by a check firing. That is
Each was found by asking a question and following it into the code, not by a check firing. That is
the argument for writing criteria down: the failures a running system reports are, by construction,
the ones it was built to notice. A criterion is a claim someone outside can test, including
claims the system has no opinion about.
6 · Criteria — Peer discovery and name resolution
Whether a node or a client is talking to who it believes it is, before consensus has
any say in the matter. A peer address is the first thing a joining node trusts; a bootstrap
resolver is the first thing that decides what a peer address is. Everything in §4 and §5 assumes
these questions were already answered correctly.
Three of the five criteria below have no automated check, and the reason is worth
stating rather than working around: these gates are conditional, and their off state is silent.
A verifier that was never installed and a mesh in which every peer is legitimate produce the same
observable — no rejections. That is INIT-04’s shape again, one layer further out.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| NAME-01 | Every peer admitted to a routing interaction has passed enterprise-CA identity verification. | No check. Construction: applyEnforce in cmd/h3-rpc-gw/dht.gocloses the connection to any peer peerverify has not verified.manual procedure — and the gate is conditional |
The verification layer’s enablement as deployed, captured in the same pass as the gate’s rejection log for that window. |
NewPeerVerifier returns (nil, nil) when disabled, soPeerVerifierActive() is nil and the gate is skipped for every peer.Nothing errors and nothing is logged. The only observable is an absence of rejections, which is precisely what a correctly-gated healthy mesh also looks like. |
| NAME-02 | The bootstrap resolver is authenticated by a pinned key, not by the public CA set. | No check. Construction: dohclient.makePinVerifier compares the leafcertificate’s SPKI SHA-256 against a configured set. manual procedure — and the empty set disables it |
The pinned fingerprint set as deployed, recorded beside the endpoint it applies to. | The pinned set is empty, so the verify callback returns nil and any certificate the system roots accept is accepted. The source names this state “only safe for tests”; nothing enforces that. This is the one DNS dependency the design deliberately keeps, and whoever answers it chooses the bootstrap peers — the same reasoning as INIT-05, one layer down. |
| NAME-03 | A federation’s published settlement identity is signed by the key it announces, and is refused unless the peer serving it is itself verified. |
No check in the audit set. Construction: the announcement is self-signed with the key it publishes as its counter-signing key, and cmd/h3-rpc-gw/regimec_discovery.gorefuses one served by an unverified peer. construction, unit-tested — no continuous check |
The discovery result, retained together with the identity of the peer that served it. | An announcement whose signature does not verify under its own announced key, or one accepted from an unverified peer. The second is the load-bearing half. A self-signature proves only that the publisher holds the key it named — never that the publisher is the federation it claims to be. Without the peer gate, self-signing proves nothing an attacker cannot equally produce. |
| NAME-04 | Discovering a counterparty does not register it. | No check — a property of the call graph. Discovery returns a result to an operator; registering the agreement is a separate, separately-authorised call. design property — no test |
The discovery output and the registration call, retained as two records under two authorisations. |
Any path that registers a discovered announcement as a live trust anchor without a human decision. Finding a legitimate first-time counterparty and registering a fraudulent one would then be one step rather than two — and only the first of those two is cryptographically rigorous. |
| NAME-05 | Node churn is measured, and a node whose churn cannot be measured is not counted as stable. | cc006 “Node Churn”, a per-block check. registered — but returns a pass when its provider is absent |
Check verdict, with the per-node reconnect counts it actually read. | The metrics provider is not configured and the check returns success rather than could-not-run. This is EVID-01’s failure moved inside a single check instead of across a cycle: the value that reports a stable mesh and the value that reports nothing at all are the same value. |
What is not repeated here
INIT-05 (cc001) already covers bootstrap peers
INIT-05 (cc001) already covers bootstrap peers
being addressed by IP literal rather than by name, and it is not restated. Together with NAME-02 it
is the whole of what this document claims about the bootstrap edge: one criterion on how the
address is written, one on who is trusted to resolve it. Neither reaches the question of whether
the resolved peer is the right one — that is NAME-01, and NAME-01 has no test.
7 · Criteria — Integration mode and data visibility
What a criterion can reach depends on which integration mode delivered the
transaction, and on who can read the field it asserts something about. These are two
independent axes, and a criterion that names neither is being asserted for all combinations at once —
and will be wrong for at least one of them.
This is the group most exposed to the misreading §2 warns about, so each row below is
written to be false under conditions a reader can check, rather than true under conditions a reader
has to assume.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| MODE-01 | A transaction’s integration mode is determined from positive evidence, never from an absent field. | No check. checks.ModeOfParameters classifies on the atom name or anon-empty process id and returns unknown otherwise. One classifier serves both the checkers and the baseline interceptor. construction, unit-tested |
The classifier’s verdict per transaction, and the fact that a single implementation produced both consumers’ answers. |
A malformed content-mode transaction — also missing a process id — read as hash-only, which excuses every mode-aware check from examining it. A positive identification cannot be produced by omission; treating absence as hash-only converts a malformation into a licence to skip. A second classifier appearing anywhere is the same failure in slower motion. |
| MODE-02 | A hash-only transaction is not retained carrying business content. | No check. The baseline interceptor drops every parameter outsidechecks.ModeAParameterAllowlist before storage and logs what it dropped.implemented — but the only record is a log line |
The interceptor’s log for the window, captured before it rotates. | A hash-only submission arrives carrying business parameters. The promise itself holds — they are dropped — but the fact that a customer’s system transmitted content it believed was never sent survives only in a log. The mechanism is sound and the evidence is not, which is a different defect from the mechanism being absent, and needs reporting as such. |
| MODE-03 | A check that cannot apply to a transaction reports not-applicable, not a pass. | checks.SkipIfHashOnly returns a not-applicable verdict for hash-onlytransactions. written, and called by nothing — the two checks whose own doc comments prescribe it are both stubs (§10). |
The cycle summary’s not-applicable count — once there is a caller capable of producing one. | A mode-aware check runs against a hash-only transaction, finds no customer-side process state because none was ever sent, and returns success. The verdict is indistinguishable from a real pass and the coverage count includes it. Today every consumer of this guard is a comment. |
| MODE-04 | What was submitted is compared against what the validators recorded. | cc118 “Transaction Parameter Tampering” — compares committed metadata and request type against the pre-registered baseline trace. implemented |
Check verdict; the pre-registered trace the provider returned for that transaction. | Metadata or request type differs between baseline and commit. Note the shape of a defect this check has already carried and had corrected: it compared the legacy, never-populated amount fields rather than the ones the gateway actually fills, so that comparison was a silent no-op on every real transaction. A check can be implemented, registered, running, and still comparing nothing. |
| MODE-05 | A quantitative field is unchanged between submission and persistence, and the comparison survives that field being encrypted. |
cc-bpd-038 “Amounts Constancy Verification” — decrypts both sides and compares plaintext positionally across every configured replica. implemented |
The per-replica comparison the check performs, and the quorum-resolved key it used. | A persisted amount differs from the consensus-agreed submitted amount. The instructive failure is the one this design forecloses: comparing ciphertext instead. A fresh nonce per encryption means an unchanged value never re-encrypts to the same bytes, so a ciphertext comparison reports tampering on every honest transaction — and would have to be switched off to be usable, which is how a check becomes decorative. |
| MODE-06 | Independent replicas agree on the commitment they recorded, without any of them holding a key to the data. |
cc-bpd-039 “Commitment Cross-Replica”, a per-transaction check. implemented |
The replicas’ commitments for the transaction, retained together. | Four distinct states, each refused explicitly rather than allowed to read as agreement: a replica disagrees; a replica cannot be read (a failure, never a skip — a comparison over one replica always agrees with itself); a field present on some replicas and absent on others (a disagreement, because suppression presents as absence); or zero commitments anywhere (could-not-run, not a pass). |
| MODE-07 | Every replica re-derives byte-identical state from the same transaction stream. | TestNoWallClockInActions (orgnodes-core/abci) rejects wall-clockuse in atom code at build time; cc054 “Clock Skew” per block. implemented as a build gate |
The gate’s result per release; the check’s verdict per block. | An atom reads a wall clock. Replicas then diverge for benign reasons, and every divergence finding in this document becomes ambiguous — a state mismatch can no longer be read as a fault. This is the property the whole of §5 rests on, and it is held by a test rather than by review. |
What this group deliberately does not assert
Nothing above claims the customer’s transaction executed, committed, or was aborted. Under
Nor does any row assert a visibility rung. Only the platform-key rung is wired, and only for one
Nothing above claims the customer’s transaction executed, committed, or was aborted. Under
the hash-only mode that is structurally unknowable, and trace.tx_outcome — which does
hold a committed-or-aborted row — answers a different question. §2 states the misreading; these
rows are worded so that none of them can be taken as reaching it.
Nor does any row assert a visibility rung. Only the platform-key rung is wired, and only for one
field; the rungs at which the platform genuinely cannot decrypt are undesigned for every field the
platform validates. MODE-06 is the one criterion here that would survive that change, because it
does not read values at all.
8 · Criteria — Federation boundary and settlement regime
Where a transaction is coordinated, and what agreement it rests on: atomic commitment
within one pyramid, a compensating orchestration within one sovereign, and neither of those across a
border.
The evidence here divides sharply, and the division is the useful part. The
cross-border settlement engine is the best-evidenced mechanism in this document — a predicate
that is a pure function of anchored evidence, a compare-and-swap that model checking found was
missing, a structural refusal to run against a test anchor. The deployment claim sitting above it —
that enterprise data does not cross a pyramid — is the least evidenced, and it is the one the
commercial argument leads with. Both are below, marked.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| FED-01 | A cross-border settlement outcome is a function of anchored evidence alone, and evaluates identically for both parties and any auditor. |
cg04 “Regime C Predicate Divergence Detection”, registered inchubbychecker-governance‘s own check set.implemented — citation deliberately unmarked: this check is in a different binary’s registry, which the §3 guard does not read (see the note below). |
The intents and commitments the check read, and its verdict. | An intent recorded as settled whose anchored evidence does not satisfy the predicate — catastrophic, because settled is terminal and there is no race window that could explain it. Or an intent that has satisfied the predicate for more than five minutes without settling — transient, and may still resolve. |
| FED-02 | Evidence attributed to a counterparty verifies against the key in the registered bilateral agreement. |
No check. regimec.verifyCounterpartyAuthorship rejects counterparty-claimedevidence unless its signature verifies against the agreement’s counter-signing key; a missing key, a missing signature and a bad signature are all hard rejections, not silent skips. construction, unit-tested — no continuous check |
The agreement as registered and the evidence as accepted, retained together. | Forged evidence accepted. And note what is not reached: rejection today is an error returned to the caller, not a state transition. There is no disputed status and no escalation path, so a genuine forgery attempt leaves no durable record that this criterion was ever exercised — the mechanism works and produces no evidence of having worked. |
| FED-03 | A compensated settlement is never returned to settled. | No check. The status write is a compare-and-swap on the from- and to-status. construction only — no test in the audit set |
The intent’s status transitions, retained in order. | A late but genuinely valid commitment overwrites an already-compensated intent back to settled, erasing the record of a real fund reversal. Not hypothetical: the write was unconditional until a model check of the engine’s own concurrency found it. |
| FED-04 | Production settlement cannot run against a test anchor. | No check — a structural property. regimec.NewProductionEngine takes noanchor argument at all; its anchor comes only from the live-credential constructor, which errors rather than falling back. construction — structural, not a convention to remember |
The constructor’s signature, per release. | A signature change reintroducing an anchor parameter. There is presently no call site at which a test anchor could be supplied, because there is nothing to supply it through — the same shape of guarantee as a signature check, rather than a rule someone must remember. This says nothing about whether the anchor itself is sound. That it never forks, reorders or equivocates is the external ledger’s property, not this platform’s; it is permanent residual trust, not an untested item, and a criterion asserting it would be the most damaging error this document could contain. |
| FED-05 | Both legs of a cross-border settlement are judged against one deadline. | No check. The agreement’s timeout is a single value fixed and validated at registration, and a commitment carries no deadline of its own. construction only |
The registered agreement, and the intent and commitment judged under it. | A commitment free to state an independent deadline. A short-deadline intent times out and compensates, while a later commitment carrying a longer, self-chosen deadline still looks satisfiable and settles — one side settled and the other compensated, for the same transaction. The single deadline is what makes the predicate a function of shared evidence rather than of whose clock was asked. |
| FED-06 | Federations carried by different pyramids share no validator. | No check. Deployment-time evidence only: each pyramid’s validator set, compared for overlap. manual procedure — no automated test |
Each pyramid’s validator set, captured in a single pass so the sets are comparable. | A validator appearing in two pyramids’ sets. Read the boundary of this claim carefully. It reaches hardware separation across pyramids only. Federations grouped within one pyramid — the shape most full-scale deployments are expected to land on — share validators by design, and their separation is software: tenant scoping inside one state machine. No criterion in this document tests that software half, and it is the half most deployments will actually rely on. |
Why FED-01’s citation carries no claim attribute
Every other check cited in this document is marked with the claim it makes and verified against the
So FED-01 is the one criterion here resting on inspection rather than on a build gate, and that is
Every other check cited in this document is marked with the claim it makes and verified against the
live registry on each build. cg04 cannot be: it is registered in a different binary’s
check set, which the guard does not compose. Marking it anyway would be worse than leaving it
unmarked — the attribute would assert a verification that never runs.
So FED-01 is the one criterion here resting on inspection rather than on a build gate, and that is
a gap in the guard, not a property of the check. Extending the guard to read the governance
registry as well is the fix; until it does, a practitioner should treat FED-01’s citation as they
would any uncited claim.
9 · Criteria — Machine origination
Sensor fleets and authored contract processes originate transactions without a human in
the loop. The first question a reviewer asks is whether a compromised device can move value across a
border. There is a real answer, it is enforced fail-closed at the point of origination, and it is
narrower than the surrounding documentation states — which is exactly why it belongs here as a
criterion rather than as a quotation.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| ORIG-01 | A device-originated event cannot originate a transaction outside its own pyramid. | No check. origin.Kind.allowedRegime permits only the atomicintra-pyramid regime for a device-kind event, and Originate returns arestriction error before doing any other work. construction, unit-tested — no continuous check |
The origination record, carrying the kind claimed and the regime reached. | A device-originated event accepted into the orchestrated or cross-border regime. Read the restriction precisely: it attaches to the device kind alone. An authored contract atom is not restricted this way — see §10 — so “machine-originated” and “device-originated” are different sets, and only the second is covered by this criterion. |
| ORIG-02 | An origination event is authenticated before anything acts on it. | No check. Originate requires a kind, a regime, an identity and anon-empty signature, verifies the signature against the per-pyramid trust list, and errors on any failure — nothing partial proceeds. construction, fail-closed, unit-tested |
The verified identity recorded against the origination. | An unsigned or unverifiable event accepted. One state to look for specifically: the package ships a no-op verifier that accepts any non-empty signature, documented as test-only. Nothing structurally prevents it being wired to a real trust list, so this criterion is met only if the deployed verifier is the real one — a deployment fact, not a code fact, and therefore one that must be captured per deployment rather than per release. |
| ORIG-03 | A device-originated event carries the consensused block time, not a wall clock. | No check. Originate rejects a device-kind event whose block time isunset. implemented for the device kind only |
The block time recorded on the origination, per event. | For every other origination kind, an unset block time is silently filled from the local wall clock — in the one package whose stated purpose is to make all three origination sources produce the same shape. Contract atoms are not device-kind and may originate into the orchestrated and cross-border regimes, so this fallback is reachable on exactly the paths where two parties must agree about time. It does not error; the value is simply wrong in a way nothing downstream can distinguish. |
| ORIG-04 | A contract atom originating a domestic orchestrated transaction is subject to a standing veto before it executes. |
No check. Kind.minimumMode raises such an origination to at leastsemi-automatic, which the coordination gate turns into a vote a regulator can use to block it. The floor escalates a weaker request and leaves a stronger one alone. construction, unit-tested |
The coordination mode recorded on the origination, against the mode the caller requested. | A contract atom originates a compensating transaction fully automatically, with no veto point before compensation would be needed. There is no equivalent floor for the cross-border regime — the coordination gate does not apply there at all — so this criterion covers the domestic case only, and the cross-border case is uncovered by design rather than by oversight. |
Why this group is worth having despite four “no check” cells
Every criterion above is enforced by construction and none by a running check, which normally
What that cannot establish is whether the restriction is reached in a live deployment. The
Every criterion above is enforced by construction and none by a running check, which normally
argues for §10 rather than a criteria table. They are here because construction of this kind
is testable by an outsider — the restriction, the fail-closed ordering, the floor and the
missing floor are all readable in one function each, and a practitioner can be handed those
functions and a release tag.
What that cannot establish is whether the restriction is reached in a live deployment. The
origination claim travels on the wire and must be populated by whatever produced the event
upstream; a caller that never sets it leaves the whole seam inert while every function above
remains correct. That is recorded in §10, not softened here.
10 · Exclusions and known gaps
Matters that belong to the groups above on their merits but are not claimed as
criteria, because nothing currently establishes them. Each was verified against the code rather than
assumed, and each is stated at the strength the code supports rather than the strength the
surrounding documentation claims.
10.1 · Matters with no mechanism
| Ref | The matter | Why it is not a criterion | What would be needed |
|---|---|---|---|
| INIT-X1 | The initial trust anchor is protected. | cc002 is not implemented and registered nowhere. Since 2026-08-31 it refuses rather than returning success, so registering it can no longer produce silent passes. not covered |
A provider giving each node’s genesis hash, plus the value recorded at chain creation. Agreement between nodes is not sufficient: a rewrite applied to every node leaves them agreeing perfectly and disagreeing with history — a defect of exactly that shape has already occurred here, a charm rewriting genesis.json mesh-wide. |
| FED-X1 | Enterprise data does not commingle between federations sharing a pyramid. | FED-06 reaches hardware separation across pyramids only. Within a pyramid the boundary is software — tenant scoping in one state machine — and no check tests it. cc061 “State Bleed” sounds like the check for this and is not: it is a hygiene watchdog for a transient store whose only caller was retired, and it is deliberately left unwired, returning a transient failure on every invocation rather than a false green. not covered |
A check comparing state reachable under one federation’s scope against the rows another federation owns, in a pyramid actually carrying both. This is the separation most full-scale deployments will rely on, and it is the one the sovereignty argument does not rest on — worth resolving before those two facts are read as one. |
| FED-X2 | Data that must agree across shards does agree. | cc073 “Cross Shard Drift” is registered and runs, but compares a single hard-coded key described in its own source as hypothetical, returns success when fewer than two shards are reported, and continues past a shard it cannot read — the omission EVID-02 exists to forbid. registered; not evidence |
A real set of cross-shard invariants, and an unreadable shard treated as a finding rather than skipped. Until then this check’s pass carries no information, and it is counted in coverage as though it did. |
| EVID-X1 | Application state is bound into consensus on every tier. | Three tiers compute no app hash at all: member-classes (org-server-abci),the tophats tier, and the auditor tier ( auditor-abci). All three return anempty AppHash and leave last_app_hash NULL. They are outsideconsensus for two different reasons, and the difference decides what can be done about it. On member-classes it is a dependency: domain columns are sealed with AES-GCM, whose random nonce makes the ciphertext differ on every replica, so a digest taken over those columns would diverge consensus on every row. On the auditor tier it is a deferred choice: every attestation it commits is already self-authenticating, signed under a did:key derived from the signing key, so tampering with a stored row is detected by re-verifying the signature rather than by a chain digest. That tier also began at height zero, which is the one moment an app hash can be adopted without height-gating. three tiers outside consensus |
For member-classes and tophats: a digest computed over a canonical projection that excludes randomised ciphertext — the shape the overseer tier’s function already uses to strip wall-clock columns before hashing. For the auditor tier the work is smaller, because nothing has to be excluded: a digest over the committed attestations, adopted at a chosen height. Until then these three tiers’ application state is agreed by nobody, and a replica that drifts goes on committing blocks alongside its peers. The auditor tier is the least exposed of the three — a drifted attestation still fails signature verification — but least exposed is not the same as covered. |
| ORIG-X1 | Machine origination is restricted end to end, from the device to the settlement gate. | The restriction is enforced where the origination claim is evaluated. Whether it is populated is the upstream caller’s responsibility, and a caller that leaves the claim unset leaves the seam inert while every function remains correct. not covered end to end |
Evidence that the services which actually emit device and contract events populate the origination kind on the wire. Absent that, ORIG-01 is a property of a function rather than of the platform, and the difference is invisible from either side. |
| ORIG-X2 | A contract atom cannot originate a cross-boundary transaction without a human. | This is asserted in the pitch material and is not what the code does.allowedRegime restricts the device kind to the intra-pyramid regime andleaves contract atoms unrestricted across all three; the only brake on a contract atom is ORIG-04’s coordination floor, which applies to the domestic regime and not to the cross-border one. claim not supported |
Either the restriction the documentation describes, or documentation matching the restriction that exists. The two must not be handed to a reviewer together — see the note below. |
| EVID-X2 | A replica’s own failure cannot become a consensus outcome. | Nothing checks this. Each ABCI application decides for itself which errors are deterministic — the same on every replica, and therefore safe to return as a result code — and which describe only local conditions and must halt the node instead. That decision is a hand-written classifier per application, with no test coverage required of it and nothing comparing one application’s judgement against another’s. not covered anywhere |
A shared classifier, and a check that fails when any application returns a result code derived from a condition that is local to one replica. This is not theoretical, and it has now happened twice. The agg mesh halted unrecoverably on 2026-08-22 that way. On 2026-09-04 a routine credential rotation left one auditor node without database privileges for about twelve seconds; every block executed in that window returned a result code its peers did not; Block.Header.LastResultsHash diverged, and that node panicked on everysubsequent block until its chain state was rebuilt from its peers. The classifier is fixed and rolled — privilege and authentication failures now halt the node — but the fix is one application’s, and the property is asserted by nobody. |
| EVID-X3 | A sequence of attestations shows that auditing continued. | Nothing checks this. Empty windows are signed deliberately, so that a gap in the sequence is visible rather than hidden by a silent skip — but nothing asserts that consecutive attestations are distinguishable. Where they are not, the record cannot separate an auditor that examined every window and found nothing from one that made a single claim and never spoke again. not covered anywhere |
A check that fails when a mesh’s attestations stop advancing, or when consecutive attestations from one identity are identical. Observed on 2026-09-05: gov1, commercial-gov and the registry auditors each held exactly four attestations — one per replica — unchanged across a sampling interval, while the workload tiers climbed into the hundreds. The obvious reading was that they had stopped attesting. They had not. Those three checkers are DB-only, follow no chain, and so observed no heights; every window was 0–0, the signed claim was byte-identical each period, and because auditor.attestations is keyed by signature every republish collided into therow already there. The database was correctly refusing to store the same claim twice. The registry auditor was, at that moment, detecting six referential-integrity gaps and three completeness violations every thirty seconds. The window is now anchored to the height of the chain the attestation is published to, and the counts advance — but the property is asserted by nobody, and the same shape returns for any future auditor that watches something other than a chain. |
| NAME-X1 | A validator that is partitioned from its peers is detectable. | Nothing on this estate reads peer count. Not a check, not a charm status, not a roll gate. A node with no peers keeps committing its own view, answers RPC, reports its true height and passes every check registered here — and its unit status stays green. not covered anywhere |
A check comparing each validator’s peer count against the size of its own validator set, failing when any node sees fewer peers than it should. This is not theoretical: on 2026-09-04 a charm refresh rewrote peer addresses into an unresolvable form, all four nodes of a mesh dropped to zero peers, and the chain halted for about 25 minutes while every existing signal — heights, unit status, service state, image tags — read healthy throughout. Height is not a proxy: a partitioned node keeps committing until consensus stalls, so by the time heights stop advancing the chain has already stopped. |
MODE-X1 | A field the platform cannot decrypt is still cross-checked. | Only the platform-key rung is wired, and only for one field. The rungs at which the platform genuinely cannot decrypt are undesigned for every field the platform validates. designed for one field; undesigned generally |
Per-field classification and a customer-held key path. MODE-06 is the one criterion already written that survives the change, because it compares commitments rather than values — which is the argument for building outward from it rather than around it. |
10.2 · Registered checks that cannot fail
Coverage counts are taken from registries, and a check that returns success
unconditionally is counted exactly like one that tests something. Thirteen of the one hundred and
thirty registered checks have bodies that discard their arguments and return success, all emptied
in the same 2026-05-23 metadata collapse and each carrying a comment saying so. They are named here
individually so that a coverage figure taken from the registry can be corrected by subtraction, and
so that implementing any one of them breaks the build until this section is updated.
| Check | What it would test | Note |
|---|---|---|
| cc004 | Sybil attack / routing vulnerability | Depended on a per-transaction nonce removed in the collapse. Named in §6’s subject matter; not covered by any criterion there. |
| cc047 | Phantom write | Needs an action to report its own real table reference; the field carries a literal placeholder today. |
| cc048 | Lost rollback | Same root gap as cc047. Its own comment prescribes the MODE-03 guard for the revived version — one of the two callers that do not exist. |
| cc049 | Out-of-order commit | — |
| cc053 | Transaction gap | — |
| cc087 | Transaction id reordering | — |
| cc091 | Inverted causality via metadata | — |
| cc107 | Context-detached execution | Its comment argues the check is now redundant against gateway-layer verification — which is a decision to record, not a stub to revive. |
| cc108 | Unconsumed compensation logic | The second of MODE-03’s two prescribed-but-absent callers. Compensation is the mechanism FED-03 and ORIG-04 both depend on. |
| cc113 | Immutable field overwrite | Also registered as a prevention gate. The gate runs on every member-class transaction and rejects nothing. |
| cc-bpd-006 | Draft-version execution prevention | Also a prevention gate. |
| cc-bpd-007 | Illegal transition detection | Also a prevention gate. |
| cc-bpd-009 | Step entry/exit policy enforcement | Also a prevention gate. |
Four of the thirteen are prevention gates
A prevention gate is not a check that reports afterwards — it is a synchronous rejection in the
commit path, registered precisely because the invariant it holds is worth refusing a transaction
over. Four of them (cc113,
cc-bpd-006,
cc-bpd-007,
cc-bpd-009) call functions that return success
unconditionally.
The consequence is worse than a missing check, and worth stating plainly rather than folding into
the count above. A gate that rejects nothing is indistinguishable, from every angle available to
an operator, from a gate whose invariant has never been violated. It appears in the gate list,
it executes on every transaction, it adds latency, and it produces exactly the observable a
correctly-functioning gate produces on well-formed traffic. Nothing about running the system
reveals the difference; only reading the four functions does.
This is the same class as the two never-registered checks recorded in 10.3 below, arriving from the
opposite direction: there, a check that could not run; here, a gate that runs and decides nothing.
Both are counted as coverage.
10.3 · Defects this document found, all now closed
A check that had never run. cc-bpd-039, the
cross-replica commitment comparison and the check MODE-06 now rests on, was referenced
only inside its own source file and appeared in no registry. It had never executed once.
registered — together with the provider behind it, which was
declared but constructed nowhere, so registering the check alone would have produced
“provider not configured” on every transaction and looked like coverage.
A coverage count that disagreed with itself. The integrity registry’s comment said it
adds twelve checks, listed thirteen IDs beneath that sentence, and registered fourteen —
cc111 registered but undocumented.
corrected, and guarded: the comment is now checked against the
function that follows it, because correcting the number once would leave the next edit free to
desynchronise it again.
A second check that had never run. cc131
— the only check verifying what was submitted rather than the validators’ own account —
was likewise registered nowhere. Its two providers existed only in org-server-abci,
which passes its registry to the ABCI application rather than to a check registry, so nothing
could reach them. registered, with both providers built auditor-side.
Two checks written, built, tested and never called is a class, not an accident.
Earned passes on two checkers out of three.
chubbychecker-joint still called RunContinuousChecks, which returns
success unless a catastrophic fault also exceeds the threshold — so on the eight auditor units
running it, a check that could not execute was invisible and the cycle read as a pass. Governance
and registry had been switched to the summary form when it was written; this one had not.
switched.
None was discoverable by reading the code normally. All four surfaced the moment a criterion had
to name the mechanism supporting it — which is the argument for the document, and the reason the
conformance guard described in §3 is not optional. It has already earned its place: registering
cc131 broke the build, because this section still said it was uncovered.
10.4 · Open, found while writing §6 – §9
The documentation and the code disagree about who may cross a boundary
ORIG-X2 above is the sharpest of the new findings and the one with a reader on the other end of
it. The pitch material states that a contract atom, like a device, may originate only into the
intra-pyramid regime, and that reaching a domestic or cross-border regime requires a human. The
code says otherwise, deliberately and with its reasoning written down: the device restriction is
permanent, and the contract-atom restriction was lifted because an authored process carries its own
declared compensation. Inside the same source file, the constant’s own comment still says
restricted to Regime A, contradicting the package comment eighty lines above it.
Both positions are defensible. What is not defensible is handing a reviewer the document and the
system together, because the security answer to “can a machine move money across a
border” differs between them. A criteria document is the wrong place to resolve which
is right — that is an architectural decision — so it is recorded here as a divergence with both
sides named, and ORIG-01 is worded to claim only what the code enforces.
Mechanisms whose evidence expires
MODE-02 and NAME-01 share a shape that none of §4 or §5’s entries had. The mechanism is
correct — content is dropped, unverified peers are disconnected — and the only record that it
acted is a log line. A practitioner asked whether a hash-only customer ever transmitted content, or
whether an unverified peer ever attempted to join, has nothing to read once the window has rotated.
This is distinct from an absent mechanism and should not be reported as one. It is also distinct
from INIT-04, where the mechanism may be absent and the absence is silent. Here the mechanism is
present, working, and unable to produce evidence of having worked — which is the one failure
mode a criteria document is most likely to mark as satisfied.
Two gates that are off unless switched on, and silent when off
NAME-01 and NAME-02 are conditional in the same way and for the same reason: an empty pin set
disables certificate pinning, and an uninstalled verifier disables peer-identity gating. Neither
errors. Neither logs. The pinning path documents its permissive state as
“only safe for tests” and nothing enforces that sentence.
This is INIT-04’s pattern — unset means off — appearing twice more, in the layer that decides
who a node talks to at all. It is recorded here rather than only in the criteria because the
pattern, not the two instances, is the finding: three independent security-relevant mechanisms
on this estate default to off and say nothing about it, and there is no sweep that would find
the fourth.
11 · Evidence, retention and the practitioner’s tooling
Sample content — rewrite
Findings are attested at intervals by each checker, signed with a key held by that checker, and
Those attestations are now committed to the auditor tier’s own BFT meshes rather than
Retention: attestations are retained for [period — to be set], which
Findings are attested at intervals by each checker, signed with a key held by that checker, and
identified by a did:key that is derived from the signing key itself. A practitioner can
therefore verify an attestation using only the attestation: no registry lookup, no key
distribution, and no reliance on any service the operator runs.
Those attestations are now committed to the auditor tier’s own BFT meshes rather than
written to a log file. That distinction is the whole point: an attestation living only in a log the
audited party controls demonstrates integrity but not independence, because the party being audited
can remove it. Every one of the seven auditor meshes commits them, and each mesh carries four
distinct did:key identities — one per replica, each key generated on its own unit and never
transmitted — so the four auditors are separately attributable rather than averaged into one voice.
An empty window is signed and committed like any other, which is what stops silence being mistaken
for agreement.
committing on all seven meshes
Retention: attestations are retained for [period — to be set], which
must be at least the period the practitioner is asked to report on. The store now exists
(auditor.attestations, keyed by signature), so this is a policy decision rather than a
missing mechanism — but it is unanswered, and an unbounded store is not a retention policy.
State this plainly, and do not soften it
The verification tool is written by the operator. Under an assurance engagement the practitioner
The verification tool is written by the operator. Under an assurance engagement the practitioner
must satisfy themselves it is fit — by reviewing it, having an expert review it, or using their
own. Reproducible builds and published source narrow this; they do not close it. A criteria
document that omits this limitation misrepresents the strength of everything above it.
12 · Change control
Sample content — rewrite
Criteria are versioned as a set. A report cites the version it was performed against. IDs are
Adding a criterion, changing what a criterion requires, or moving one to §10 are all changes
The approver is settled even though the versioning policy around it is still sample content.
Criteria are versioned as a set. A report cites the version it was performed against. IDs are
never reused and never renumbered; a withdrawn criterion is marked withdrawn and kept, so that
an older report remains readable against the document it referenced.
Adding a criterion, changing what a criterion requires, or moving one to §10 are all changes
requiring the approval of the executive director of cyber-security
approver settled 2026-09-03. Correcting a typographical error
is not.
The approver is settled even though the versioning policy around it is still sample content.
An unnamed approver is the failure this section exists to prevent: it makes every change to the
criteria deniable after the fact, which is worse than a policy that has not been written yet.
Appendix A · Blank section to copy
One of these per criteria group. Suggested groups, following the shape of the existing
check set rather than inventing a taxonomy. Six are worked above — Initialisation (§4),
Evidence integrity (§5), Peer discovery and name resolution (§6),
Integration mode and data visibility (§7), Federation boundary and settlement regime
(§8) and Machine origination (§9). Groups still to write:
Admission & ordering, Replica agreement, Record completeness,
Anchoring & immutability, Authorisation & separation of duties,
Recovery.
| ID | Criterion | How it is tested | Evidence produced | What a failure looks like |
|---|---|---|---|---|
| XXX-01 | One sentence. What must be true, with no argument for why. | Check ID, or the named manual procedure. State plainly if there is none. | The artefact retained, named specifically enough to ask for. | The observable state when this is not met. If you cannot write this cell, the criterion is not yet testable. |
Follow each table with an exclusions table in the shape of §10 — even where it is empty,
in which case say so explicitly rather than omitting it.
Appendix B · Drafting checklist
| Check | Why |
|---|---|
| Can this criterion fail? | Write the failure cell first. If nothing goes in it, the criterion is unfalsifiable and will pass forever. |
| Does the cited check exist and run? | Existing, registered and non-vacuous are three different things. cc002, cc001 and cc-bpd-039 each fail a different one. |
| Is it stated without argument? | Justification belongs in the surrounding prose. In the cell it reads as advocacy and undermines neutrality. |
| Is the evidence retained? | A verdict that scrolls out of a log window cannot be reported on later. Decide from state that does not expire. |
| Is there an exclusions table? | Its absence is a claim of completeness, made silently and almost always wrongly. |
| Would a reader over-read this? | The test is whether someone could take a criterion as covering data truthfulness. If so, rewrite it. |
