Bundle version: b1. Profiles: record (defined here) and chain (reserved, §11).
A proof bundle is one JSON document that carries one DEO record, the subject, together with the material a verifier needs to check that record on its own: the record's envelope, its place in its chain, and the checkpoints, proofs and publications that tie its digest to a public ledger or a timestamp. A verifier reads a bundle without contacting whoever produced it. Nothing in a bundle is believed because the bundle says it: every fact is recomputed, and trust comes only from the auditor's own inputs (a publisher manifest, header sources, RFC 3161 roots).
The conventions of Specs §3 apply throughout.
1. Scope
This document defines:
- the members of a
b1bundle and what each one carries (§3, §5 to §10); - how a verifier reads a bundle before checking anything, which decides the
bundlerow (§4); - how a verifier takes the anchoring material out of a bundle and hands it to the anchor verification of Anchor §10 (§7);
- the order of the rows a verifier reports for a record bundle (§12);
- the layout of the
b1conformance corpus (§13).
It relies on:
- Record for the envelope, the payload, the record digest, the chain link and the record's own RFC 3161 token;
- Anchor for checkpoint bodies, origins, the published value P, publication entries, the
record artifact
nonRepudiation.anchorand its verification; - Tree for inclusion paths, consistency proofs and the hash encoding;
- Verification for the four outcomes, the check catalogue (row ids and reasons), the report and the exit codes.
2. Terms
- Subject: the one record a record bundle is about.
- Exporter: whatever writes a bundle. Verifier: whatever reads one and reports on it.
- Slot: a top-level member with a fixed name that every
b1bundle carries (§3.2). - Reserved slot: a slot this version reserves without defining its content (§8). A later specification may define it without a new bundle version.
- Log, origin: an append-only Merkle log and the name its checkpoint bodies carry
(Anchor §3, §4.3). The subject's evidence log is the log of its chain; the
anchor log is its domain's log of checkpoint digests (Anchor §5). A Tzun origin
whose rest is
anchors(Anchor §4.3.1) is an anchor-log origin; every other key of theanchoringslot is read as an evidence-log origin. - Final publication: a publication of an anchor checkpoint's P (Anchor §6, §7) that the exporter holds as final.
- Heavy material: the members an
evm-calldata/1entry needs for an offline check and the envelope leaves out:rawTransaction,blockHeader,txIndexandtxProof(Anchor §7.2, §8.2).
3. The bundle object
3.1 Members
A b1 record bundle is a JSON object with these members:
| Member | Type | Content |
|---|---|---|
bundleVersion | string | "b1" (§4) |
profile | string | "record"; "chain" is reserved (§11) |
subject | object | Names the subject (§5.1) |
envelope | object | The subject's envelope, as stored (§5.2) |
chain | object or null | The subject's chain id and predecessor (§5.3) |
custody | object or null | Custody material (§6) |
credentials | null | Reserved slot (§8) |
relatedRecords | null | Reserved slot (§8) |
anchoring | object or null | Checkpoints, publications and proofs, by origin (§7) |
anchorPending | object or null | The pending state of an unanchored subject (§7.7) |
policy | null | Reserved slot (§8) |
extensions | object or null | Extensions, by name (§9) |
exporter | object or null | Information about the export; never an input (§10) |
3.2 Every slot is present
Every member of §3.1 other than bundleVersion and profile is a slot. A b1 bundle MUST carry
every slot. A slot with nothing to carry holds null. A slot that is missing, as opposed to
null, makes the document something other than a b1 bundle, and a verifier reads it as
unreadable (§4). Because every slot is always present, material can be added to a reserved slot
later without a new bundle version, and a reader never has to guess whether a missing member held
nothing or has been removed.
Inside a slot, a member whose value is null reads as absent unless a rule of this document says
otherwise.
3.3 Other members
A record bundle MUST NOT carry any other top-level member. A verifier reports each top-level
member that §3.1 does not list as a row member[<key>] that abstains, reason
unsupported_member (Verification §4.7), because it has not examined what the member
carries. An abstention is never a pass.
3.4 Example (informative)
{
"bundleVersion": "b1",
"profile": "record",
"subject": { "evidenceId": "7d0c…", "canonicalDigest": "<hex64>" },
"envelope": { "envelopeVersion": "e1", "payload": { … }, "integrity": { … },
"nonRepudiation": { "rfc3161Token": "…", "anchor": { … } } },
"chain": { "chainId": "default", "predecessor": { "evidenceId": "…", "sequenceNumber": 41,
"canonicalDigest": "<hex64>" } },
"custody": null,
"credentials": null,
"relatedRecords": null,
"anchoring": {
"<evidence-log origin>": {
"checkpoints": [
{ "body": "<the subject's own evidence-log checkpoint>", "signatures": [] },
{ "body": "<the newest anchored one>", "signatures": [],
"logPath": ["<hex64>"], "anchorLeafIndex": 409, "anchorSize": 412,
"anchorPath": ["<hex64>"] } ],
"consistency": [ { "fromSize": 1024, "toSize": 1100, "path": ["<hex64>"] } ] },
"<anchor-log origin>": {
"checkpoints": [
{ "body": "<the subject's own anchor checkpoint>", "signatures": [],
"publications": [ { "kind": "evm-calldata/1", "chain": "eip155:11155111",
"transactionId": "0x…", "blockNumber": 7123456, "blockHash": "0x…",
"publisher": "0x…", "rawTransaction": "0x…", "blockHeader": "0x…",
"txIndex": 3, "txProof": ["0x…"] } ] },
{ "body": "<the newest anchor checkpoint>", "signatures": [], "publications": [ … ] } ],
"consistency": [ { "fromSize": 380, "toSize": 412, "path": ["<hex64>"] } ] } },
"anchorPending": null,
"policy": null,
"extensions": { "witness/1": null },
"exporter": { "exportedAt": "2026-01-01T00:00:00.000Z", "exportedBy": "…" }
}
4. Reading a bundle: the bundle row
A verifier reads a bundle in the order below before any other check. The outcome is the bundle
row of Verification §4.2.
- The document MUST be a JSON text (Record §3.1) whose top-level value is an object.
Otherwise the row is
checked-wrong,malformed_bundle. bundleVersionMUST be the string"b1". A value that is absent,null, not a string, or another string makes the verifier abstain on the whole bundle:abstain,unsupported_bundle_version. The version is read before anything else in the object, so a bundle of an unknown version is never judged by this version's rules.profileMUST be the string"record". Any other value,"chain"and absence included, makes the verifier abstain on the whole bundle:abstain,unsupported_bundle_profile.- Every slot of §3.1 MUST be present (§3.2).
envelopeMUST be an object;envelope.payloadandenvelope.integrityMUST be objects; andenvelope.nonRepudiation, when present and notnull, MUST be an object.- Every slot MUST be
nullor an object. - In
chain:chainId, when present and notnull, MUST be a string, andpredecessor, when present and notnull, MUST be an object. anchoringMUST have the shape of §7.1.- No member name of the bundle object, of
extensions, ofenvelope.payload, ofenvelope.nonRepudiationor ofanchoringholds a lone surrogate (Record §3.1). These are the names a report carries as part of a row id (Verification §4.7), and a report that holds a lone surrogate cannot be written (Verification §6.5).
A failure at steps 4 to 9 makes the row checked-wrong, malformed_bundle. When every step holds,
the row is checked-correct.
When the bundle row is not checked-correct, it is the only row of the report, and the exit
code is 2 (Verification §6.6). A verifier that fails for a reason of its own while
checking a bundle, rather than because of the bundle, reports the one row bundle,
not-checked, bundle_verifier_error.
Whatever the bundle row's outcome, a report restates the bundle's bundleVersion and subject
exactly as the bundle gives them, and null for either one the bundle does not carry or a
document that is not JSON (Verification §6.1).
5. The record
5.1 subject
subject is { "evidenceId": <string>, "canonicalDigest": <hash> }. It MUST name the envelope's
record: evidenceId equal to envelope.payload.evidenceId, and canonicalDigest equal, as a hash
(Tree §4), to the digest the envelope stores in envelope.integrity.canonicalDigest.
The comparison uses the stored digest, never a recomputed one. A payload edited after capture is
therefore reported once, by record.digest, and not a second time here. Any other outcome of the
comparison, including a subject that is null or a member that is missing or unreadable, makes
the row subject checked-wrong, subject_mismatch.
5.2 envelope
envelope is the subject's envelope exactly as stored (Record §2). An exporter MUST
NOT alter it. A verifier:
- recomputes the record digest from
envelope.payload(Record §4), which decides the rowrecord.digest. Every row that takes the digest as its input reads the recomputed digest, and isnot-checked,blocked_by:record.digest, unless that row ischecked-correct. A row whose artifact the envelope does not carry reports it absent instead, whatever the digest; - reads under
envelope.nonRepudiation:rfc3161Token, the record's own timestamp (Record §10);anchor, the record artifact (Anchor §8); the sign-off materialsignoffandwebauthnAssertion, which the rowssignoff.expectationandsignoff.keyread (Verification §4.5, §5); the mandate materialmandateandmandateIssuance, whichsignoff.expectationand the mandate rows read (Verification §4.12, §5); andconfirmation, whichsignoff.expectationreads when the record owes one (Verification §5), and which is otherwise reported as material this version does not read (Verification §4.7); - never takes a stored summary as an input.
nonRepudiation.rfc3161Metadatais a display copy of fields of the token, andenvelope.attestationStatusis the writer's own summary; neither is read; - reports a row for each payload member that Record §2.2 does not name, which the digest does not
cover, and for any other material present under
nonRepudiationthat it does not verify, so that nothing present is passed over (Verification §4.7).
5.3 chain
chain is { "chainId": <string>, "predecessor": <object or null> }.
chainIdis the id of the chain the subject belongs to. The verifier passes it as the chain id of step 2b of Anchor §10.3, for the subject's anchor (§7.4) and foranchor.newer(§7.5). WhenchainorchainIdisnullor absent, no chain id is supplied, and step 2b reports the chain unchecked. AchainIdthat holds a lone surrogate is supplied, and no origin spells it.predecessoris the record numbered one below the subject in the same chain:{ "evidenceId", "sequenceNumber", "canonicalDigest" }, with the digest that record stores. It isnullfor the first record of a chain, whosepayload.sequenceNumberis 1. An exporter SHOULD carry it for every other record: without it the chain link cannot be checked.
The row record.chainLink (Verification §4.3) checks envelope.integrity.chainLink
(Record §5) against predecessor, using the digests as stored, so that an edited payload
is record.digest's finding alone. A subject numbered above 1 whose bundle carries no
predecessor reads not-checked, not_in_bundle:predecessor; a predecessor that is present
must be numbered exactly one below the subject.
6. custody
custody is null or an object that carries custody material for the subject. This version of
the specification does not define that material and does not verify it. The row custody.ledger
(Verification §4.3) reports what a verifier of this version decides about it; custody
material it cannot verify is never passed over.
7. Anchoring
7.1 The anchoring slot
anchoring maps origins to logs:
"anchoring": { "<origin>": { "checkpoints": [ <checkpoint entry>, … ],
"consistency": [ <consistency entry>, … ] } }
It is {} or null when the bundle carries no anchoring material. Its shape, which step 8 of §4
requires:
- each key is a string with no lone surrogate, and each value is an object;
checkpointsis present and is an array of at most two checkpoint entries (§7.3), each an object whosebodyparses as a checkpoint body (Anchor §4.2) naming exactly the origin it is keyed under;consistency, when present and notnull, is an array of objects (§7.6).
Keying every body under its own origin means two logs are never compared as one: a bundle that places a body of one log under the key of another is unreadable.
7.2 Checkpoint entries
| Member | Type | Carried by | Rule |
|---|---|---|---|
body | string | every entry | A checkpoint body (Anchor §4.1) |
signatures | array of signature entries | every entry | Signatures on the body (Anchor §4.5), each a signature entry (below). This version defines no check over them: a verifier does not read them, and they have no row in the report (Verification §4.7). Anchor §4.5 defines no log key in this version, and until a log key exists an exporter writes []. |
publications | array | anchor-log entries | Every final publication of this checkpoint's P, each a publication entry with its heavy material (§7.4) |
logPath | array of hashes | one evidence-log entry | The subject's inclusion path in this body: PATH(leafIndex, D[n]), leaf first (Tree §3.3), where n is the body's size |
anchorLeafIndex | integer | the same entry | The index of this body's checkpoint digest (Anchor §4.4) in the anchor log |
anchorSize | integer | the same entry | The size of the carried anchor checkpoint that includes this body |
anchorPath | array of hashes | the same entry | PATH(anchorLeafIndex, A[anchorSize]), leaf first |
The last four members compose the subject's anchor into a newer anchor checkpoint (§7.5). An exporter writes them on at most one evidence-log entry.
Signature entries. Each element of signatures is an object with two members, line and
proofs:
{ "line": "— <key name> <base64(key ID ‖ signature)>",
"proofs": [ { "kind": "rfc3161", "token": "<base64 TimeStampResp>" } ] }
lineis one signature line of the signed note onbody, in the form of Anchor §4.5, without its final LF.proofsis an array of proofs overline,[]when the exporter holds none. A proof is an object whose memberkind, a string, names its form and the members it carries besidekind.
kind | Members beside kind | The proof |
|---|---|---|
rfc3161 | token, a string | An RFC 3161 timestamp over line: the DER TimeStampResp, in base64, to a TimeStampReq that is that of Anchor §7.3 with the SHA-256 of the UTF-8 bytes of line as hashedMessage in place of P |
Proof kinds are additive. A verifier that reads signatures abstains on a proof whose kind it
does not know, and never fails it, so that a kind defined later makes no bundle fail. A verifier
of this version reads none of them (above).
7.3 Which checkpoints a record bundle carries
For a subject that a final publication covers, the exporter carries its evidence log and its domain's anchor log. For each of the two logs it carries at most two checkpoints:
- the subject's own: the evidence-log body its artifact names as
logCheckpoint, and the anchor checkpoint it names asanchorCheckpoint. Nothing but the artifact authenticates these bodies, so an exporter carries them only when the envelope holds the artifact; - the newest: the newest anchor checkpoint that has a final publication when the bundle is written, and the newest evidence-log checkpoint that anchor checkpoint includes.
When both name the same body, the log has one checkpoint. When the envelope holds no artifact yet, the exporter carries the newest checkpoint of each log alone, with the subject's anchor into it (§7.5).
A record bundle MUST NOT carry intermediate checkpoints. A verifier reads more than two checkpoints under one origin as an unreadable bundle (§4 step 8). One direct consistency proof per log (§7.6) joins the two checkpoints, so the size of a record bundle's anchoring does not grow with the age of the record. A run of consecutive checkpoints belongs to the chain profile (§11).
7.4 Publications, and the join with the envelope
Each anchor-log checkpoint entry carries, in publications, every final publication of that
checkpoint's P as a publication entry of Anchor §8.2. An evm-calldata/1 entry carries its
heavy material. A bundle's evm-calldata/1 entry MAY omit transactionId (Anchor §8.2).
The envelope's artifact lists its publications without the heavy material. Before verifying the subject's anchor, a verifier joins each of its entries with the heavy material the bundle carries:
- The bundle's entries are every publication entry of every anchor-log checkpoint entry in the bundle, taken with origins in byte order of their keys, then checkpoint entries in array order, then publications in array order.
- An envelope entry of kind
evm-calldata/1with a stringtransactionIdjoins the first bundle entry that is also of kindevm-calldata/1, whoserawTransactionhashes underkeccak256to thattransactionId(compared without regard to case), and whoseblockHash, if both entries state one, is the same (compared without regard to case). Two transactions mined in one block are therefore never confused. - The joined entry keeps every member of the envelope's entry and gains each heavy member it does
not already have; a member whose value is
nullis one it does not have (§3.2), and a bundle member whose value isnullgives nothing. No other member of the bundle entry is taken: the chain, block number, block hash and publisher checked are the envelope's. - An envelope entry that joins no bundle entry, and every entry of another kind, is verified as the envelope writes it.
The verifier then runs Anchor §10.3 to §10.6 over the artifact with the joined entries,
the recomputed digest, payload.sequenceNumber, and chain.chainId. Its rows are the anchor
row and its step and publication rows of Anchor §10.7, in that order. When
the envelope holds neither nonRepudiation.anchor nor nonRepudiation.blockchainAnchor, the
anchor rows report the artifact absent (Anchor §10.9). Otherwise, when record.digest is
not checked-correct, anchor and each of its six step rows are not-checked,
blocked_by:record.digest.
7.5 The subject's anchor into a newer checkpoint: anchor.newer
When a bundle carries a checkpoint that the envelope's artifact does not name, or the envelope has
no artifact yet, the exporter writes logPath, anchorLeafIndex, anchorSize and anchorPath
on the largest evidence-log checkpoint it carries (§7.2), so that the subject's anchor into the
newest anchor checkpoint can be checked. That checkpoint can be the artifact's own
logCheckpoint, when the evidence log did not grow while the anchor log did.
A verifier checks that anchor as follows.
- The target. Among the evidence-log checkpoint entries that carry any of the four members (a
member whose value is
nullis not carried, §3.2), the target is the one whose body has the largest size, searched first under the origin of the artifact'slogCheckpoint(when the artifact is present and that body parses) and, if no entry there carries the members, under every evidence-log origin. On equal sizes, the first in the order of §7.4 step 1 is taken. With no target there is noanchor.newerrow. - The composed artifact. The verifier builds a record artifact (Anchor §8.1) from:
anchorSpec"tzun-anchor/1",merkleSpec"rfc6962",leafIndexequal topayload.sequenceNumber − 1(when the sequence number is an integer of at least 1), the target'sbodyaslogCheckpoint, and itslogPathandanchorLeafIndex; then, from the first anchor-log checkpoint entry (same order) whose origin has the same domain prefix as the target's (Anchor §4.3.1; any anchor-log origin when the target's origin is not a Tzun origin) and whose body's size equals the target'sanchorSize, that body asanchorCheckpoint, the target'sanchorPath, and that entry'spublications. A member the bundle cannot supply is left out, and the composed artifact then fails the shape of step 2 of Anchor §10.3 (malformed_anchor). - The verification. The verifier runs Anchor §10.3 to §10.6 over the composed
artifact, with the recomputed digest,
payload.sequenceNumberandchain.chainId. Its publications are the bundle's own entries, which carry their heavy material and need no join. BecauselogPathis the subject's own path, every step applies, the inclusion of the subject in the newer body included: this is a stronger check than the minimum of Anchor §10.8, and it authenticates the two bodies it names in the same way. - The row. The verifier reports one row,
anchor.newer, with the outcome and reason that theanchorrow of Anchor §10.7 would give the composed artifact. When it ischecked-correctits facts aretreeSizeandanchorSize, the sizes of the two bodies it authenticated. The step and publication rows of the composed artifact are not reported. Whenrecord.digestis notchecked-correct, the row isnot-checked,blocked_by:record.digest.
7.6 Consistency proofs
A consistency entry is { "fromSize": <integer>, "toSize": <integer>, "path": [<hash>, …] }:
the proof PROOF(fromSize, D[toSize]) of Tree §3.5 between two checkpoints of the
log it is keyed under. An exporter writes one direct proof between the two checkpoints it carries
for a log, with fromSize the smaller size and toSize the larger.
A verifier reports the rows anchor.consistency[<origin>] of Anchor §10.8, in byte order
of the origin:
- the origins are every key of
anchoring, and the origin of every body thatanchororanchor.newerauthenticated; - a body is authenticated by
anchorwhen the subject's anchor ischecked-correct(itslogCheckpointandanchorCheckpoint), and byanchor.newerwhen that row ischecked-correct(the two bodies of the composed artifact); - a carried body of the origin that neither row authenticated makes the row
not-checked,blocked_by:anchorwhileanchoris notchecked-correct, andblocked_by:anchor.neweronce it is, whether or not the report has ananchor.newerrow; - otherwise, with two authenticated bodies of the origin, the proof used is the
pathof the first carried entry whosefromSizeandtoSizeequal the smaller and the larger of their sizes; the sizes and roots compared are the parsed bodies' own, never the entry's (Anchor §10.8). Apaththat is missing ornullis not an array of hashes. With no such entry the row isnot-checked,not_in_bundle:consistency_proof; - an origin with fewer than two authenticated bodies and no unauthenticated carried body reports no row.
7.7 An unanchored subject: anchorPending
anchorPending is { "origin": <string>, "leafIndex": <integer>, "since": <date-time> } or null.
- An exporter that anchors, holding a subject that no final publication covers yet, writes the
subject's evidence-log origin, its
leafIndex(payload.sequenceNumber − 1), and insincethe time the subject's leaf entered its evidence log. It carries no anchoring for that subject (anchoringis{}). - The pending state lives only in this slot. It is never written under
nonRepudiation(Anchor §8.4). - A verifier reports a non-
nullanchorPending, whatever it holds, as the rowanchor.pending,not-checked,not_yet_published. That row never abstains and is never absent, so a bundle that reports it exits 4 unless the auditor allows unchecked rows (Verification §6.6). No check reads the slot's members.
7.8 A subject with no anchoring material
A bundle whose envelope has no artifact, whose anchoring is {} or null, and whose
anchorPending is null is what an exporter that does not anchor writes. Its anchor rows report
the artifact absent, and absence is not an unchecked artifact (Verification §6.6), so
the exit code alone does not show that the subject is anchored. An auditor who needs an anchor
requires anchor, or anchor.newer for a subject whose envelope has no artifact yet
(Verification §3.2, §6.6).
8. Reserved slots: credentials, relatedRecords, policy
These slots are reserved for sign-off verification material. This version of the specification
does not define their content and does not verify it. An exporter of this version writes null
in each.
A verifier of this version never treats a filled reserved slot as a pass:
- a
credentialsslot that is notnullmakessignoff.keyabstain,unsupported_signoff, unless an earlier rule of that row decides it (Verification §4.5); - a
relatedRecordsorpolicyslot that is notnullis reported as a row with the slot's name as its id,abstain,unsupported_slot.
9. extensions
extensions is null or an object whose keys name extensions. A key whose value is null is an
extension that is not present. The key witness/1 is reserved for independent witness attestation,
which this version of the specification does not define.
A verifier reports each key with a non-null value that it does not implement as the row
extension[<key>], abstain, unsupported_extension, in byte order of the key. The abstention
covers that key only; the rest of the bundle is checked as usual. A verifier of this version
implements no extension.
10. exporter
exporter is null or an object that describes the export, for example exportedAt (a
date-time), exportedBy (a string naming the software) and the exporting store's own verdict on
the subject. Exporters MAY add members. A verifier MUST NOT use any of it as an input to any check:
a bundle's account of itself proves nothing.
11. The chain profile (reserved)
The profile "chain" is reserved for a bundle that carries a whole range of a log: its records and
their leaves, in members that a record bundle does not have. Checks that need a whole leaf range,
such as recomputing a log's roots from its leaves (log.recompute) and confirming that every
record of the range is exactly one leaf (log.membership), belong to that profile. This version of
the specification does not define it, and a verifier of this version abstains on a chain-profile
bundle as a whole (§4 step 3).
12. The rows of a record bundle, in report order
Verification §4.1 fixes the order of the rows of a record bundle whose bundle row is
checked-correct. This table lists them in that order, with the bundle material each one reads.
Their outcomes, reasons and facts are those of Verification §4 and Anchor §10.7.
| Rows | Reads | Section |
|---|---|---|
bundle | the whole document | §4 |
subject | subject, the envelope | §5.1 |
record.digest | envelope.payload, envelope.integrity | §5.2 |
record.chainLink | envelope.integrity.chainLink, chain.predecessor | §5.3 |
custody.ledger | custody | §6 |
ts.record.token, ts.record.trust | nonRepudiation.rfc3161Token | §5.2 |
signoff.expectation, signoff.key | payload.signoffExpectation, nonRepudiation.signoff, nonRepudiation.webauthnAssertion, nonRepudiation.mandate, nonRepudiation.confirmation, credentials | §5.2, §8 |
decider, decider.freshness | payload.decider, payload.signoffExpectation, the sign-off material | §5.2 |
contributions, contributions.binding, contributions.pipeline | payload.contributions, and the payload members it is checked against | §5.2 |
links, then links[<i>] and links[<i>].edge by index | payload.links, payload.aiSystemId, payload.action, payload.contributions, payload.signoffExpectation, and the payload members a relation's record-local rule reads | §5.2 |
mandate.issuance, mandate.scope, mandate.limits, mandate.key, mandate.assertionTimestamp | payload.signoffExpectation, payload.schemaVersion, payload.decider, payload.aiSystemId, payload.action, payload.aiOutput, payload.contributions, the payload members that the mandate document's predicates and caps name, nonRepudiation.mandate, nonRepudiation.mandateIssuance, credentials | §5.2, §8 |
anchor, its step rows, then its publication rows | nonRepudiation.anchor, joined with anchoring | §7.4 |
anchor.newer | anchoring | §7.5 |
anchor.consistency[<origin>], by origin | anchoring | §7.6 |
anchor.pending | anchorPending | §7.7 |
extension[<key>], by key | extensions | §9 |
relatedRecords, then policy | the reserved slots | §8 |
payload.<name>, by name | payload members that Record §2.2 does not name | §5.2 |
member[<key>], by key | other top-level members | §3.3 |
rows for other material under nonRepudiation | the envelope | §5.2 |
A row whose section says it is reported only in some cases (contributions.pipeline,
links[<i>] and links[<i>].edge, the mandate rows, anchor.newer,
anchor.consistency[<origin>], anchor.pending, the reserved slots, extensions, other payload
members, other members) is left out in the others.
13. The b1 conformance corpus
13.1 Layout
The corpus is the bundle-b1/ directory of the conformance vectors (Vectors). index.json lists every case by name, with
its expected exit code and a description of what it pins. Each case is a directory:
| File | Content |
|---|---|
bundle.json | The bundle an exporter wrote, or that bundle altered as the case states |
inputs.json | The auditor's inputs (§13.2) |
expected-report.json | The report of Verification §6, without checkedAt |
expected-exit | The exit code, as decimal digits followed by a newline |
The expected reports are stated from this specification; every value inside them (a digest, an origin, a transaction id, a block time, a token's time) comes from the run that produced the case.
13.2 inputs.json
{
"publisherManifest": { "publishers": { … } } | null, // Anchor §9; null: none supplied
"headerSources": { // keyed by CAIP-2 chain; {} for none
"eip155:31337": {
"chainId": 31337,
"finality": "finalized", // the finality it declares (Anchor §10.4)
"finalizedBlockNumber": 13,
"blocks": [ { "number": 1, "hash": "0x…", "timestamp": 1790514581 } ]
}
},
"trustAnchorsPem": [ "-----BEGIN CERTIFICATE-----…" ], // RFC 3161 roots; [] for none
"regime": { "require": [], "requireRung": [], "allowUnchecked": false }
}
- A header source here is static. It has the stated chain id and finality, reports
finalizedBlockNumberas its finalized height, and knows exactly the canonical blocks it lists, each by number, hash and unix time in seconds. It has no block at any height it does not list, and it looks up no transaction, so only a trie proof in the bundle places a transaction in its block. - No other input exists for a case: no trust store of the environment, and no chain registry beyond the verifier's own (Anchor §9).
regimeis the auditor's policy for the exit code: the rows that must bechecked-correct, the rungs required, and whether unchecked rows are allowed (Verification §3.2).
13.3 Replaying a case
A verifier replays a case by verifying bundle.json with the inputs of inputs.json, the
publisher manifest supplied as the bytes of its canonical form (Record §3). The case holds
when the report, without checkedAt and in canonical form, equals expected-report.json, and the
exit code equals expected-exit. Specs §6 states what conformance requires across the
corpus.