| Internet-Draft | SCITT Measurement Capsules | October 2026 |
| Templeman | Expires 30 April 2027 | [Page] |
This document defines the measurement capsule: a small, deterministic JSON record in which a party that is neither the subject of a claim nor a participant in the action it concerns records what the subject declared, what the measuring party observed, and the difference between the two. A capsule carries digests of its evidence, a measurement state in which "could not be checked" is a first-class outcome, and no decision, approval or authorisation. Capsules are identified by the SHA-256 of their JCS serialisation and batched under an RFC 9162 Merkle Tree Hash. The document describes their registration as SCITT Signed Statements (RFC 9943), how they refer to rather than restate receipts issued under other profiles, its encoding as a COSE_Sign1 Signed Statement with test vectors, and one implementation, including where it does not yet match this profile.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 30 April 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Several individual drafts define receipts for automated actions. [I-D.schrock-ep-authorization-receipts] binds an enrolled approver key to one canonical action before execution; [I-D.marques-asqav-compliance-receipts] profiles signed action receipts, including decision receipts carrying a policy digest; [I-D.sahu-agent-action-receipts] defines signed, hash-chained action receipts and [I-D.noa-scitt-ai-agent-receipt] carries such receipts as SCITT Signed Statements; [I-D.hopley-x402-compliance-receipt] records categorical screening outcomes in agentic-payment flows; and [I-D.farley-acta-signed-receipts] defines signed decision receipts for access control at the MCP transport layer. These readings are the author's; corrections from their authors will be adopted.¶
Those receipts are issued by a party in the path of the action and answer "was this permitted, and by whom?". They are not designed to answer a different question: does what a subject publicly declares about itself (a protocol version in a registry, a signing key in an agent card, a token's deployments, an evaluation result) match what an unaffiliated reader can observe?¶
A measurement capsule records one such comparison. It differs from an action receipt in three ways. First, its Issuer is neither the subject nor a participant in the action, and it grants no authority; where the Issuer measures itself, the capsule should say so. Second, it carries the declaration, the observation and an explicit differential, and its state may be UNCHECKABLE, which is never recorded as a pass, a failure, a zero or an absence. Third, it may reference a receipt issued under another profile by digest (Section 8.2) but never copies its outcome, so an approver's receipt and an independent measurement of the same effect can sit in one Transparency Service without either restating the other.¶
The closest work, [I-D.dogru-cedulon-decision-profile], reconciles a
decider's signed Decision Records against an authenticated extract of
effects; a capsule records one comparison and draws no conclusion about
any decision. [I-D.mih-sokolov-scitt-payload-binding] specifies declared
canonicalisation and typed digest references for Signed Statements;
capsule_id (Section 4) is its derived identifier under algorithm jcs
with the exclusion set {capsule_id}.¶
This document profiles content, not the SCITT architecture. The terms Issuer, Signed Statement, Transparency Service and Receipt are used as defined in [RFC9943], and registration follows [I-D.ietf-scitt-scrapi] unchanged. The author's organisation does not operate a Transparency Service. The document is Experimental because its requirements on decision fields and UNCHECKABLE (Section 8) have not been shown useful by more than one implementation (Section 14).¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
What the subject, or a registry or manifest speaking for it, states about a claim, as read from bytes the measurer retrieved.¶
What the measurer read from a source other than the declaring one: a live protocol exchange, a ledger's state, a signature verification or a rerun on different hardware.¶
The structured difference between the two. It is data, not a judgement: "these two statements disagree" does not say which is true.¶
The Issuer of a capsule; neither the subject nor a participant in the action the claim concerns, except in a self-measurement, which the capsule SHOULD mark as such.¶
An ordered vocabulary recording how strong an observation is, as distinct from what it found: STATE_PROOF_VERIFIED (a proof checked against a block header's state commitment, the header not checked against consensus), STATE_PROOF_RECORDED (kept, did not verify), OPERATOR_API (an operator's answer, no proof), UNCHECKABLE and REJECTED (an identity check did not pass). A label MUST NOT be upgraded; an Issuer MUST refuse to build a capsule from a source record whose label claims more than its evidence shows.¶
A capsule is a JSON object [RFC8259] with the structure below, in CDDL
[RFC8610] using the .cat control of [RFC9165]. The inner structure
of the open maps depends on kind.¶
capsule = {
"schema": "csoai.measurement-capsule/0.2",
"kind": tstr .regexp "measurement\\.[a-z0-9_]+",
"subject_id": tstr,
"claim": { "statement": tstr, * tstr => any },
"declared": open-map,
"observed": open-map,
"differential": open-map,
"sources": sources,
"measurement_state": tstr .size (1..64),
"authority_state": authority-none,
"effect_reference": effect-reference / null,
"observed_at": tdate,
"correction_pointer": correction-pointer / null,
"limitations": [* tstr],
? "runtime_declared": open-map,
? "runtime_observed": open-map,
"capsule_id": sha256-hex
}
open-map = { * tstr => any }
sources = { * tstr => source-value }
source-value = digest / null / [* source-value] / sources
digest = tstr .regexp "(sha256:)?[0-9a-f]{40,128}"
sha256-hex = tstr .regexp "[0-9a-f]{64}"
authority-none = "NONE: measurement only; this capsule grants"
.cat " and records no execution authority"
effect-reference = { "profile": tstr, "statement_digest": digest,
? "transparency_service": tstr, ? "entry_id": tstr, * tstr => any }
correction-pointer = { "record_schema": tstr, "record_version": tstr,
"record_sha256": digest, "supersedes_record_sha256": digest / null,
"from": any, "to": any, ? ("why" / "cause"): tstr, * tstr => any }
kind fixes the inner structure of the open maps and the vocabulary
of measurement_state. The grammar above admits measurement.*
kinds only; the capsules the implementation publishes under the
operations.* kinds do not match it, which is where the implementation
does not yet match this profile (Section 13 and
Section 15). subject_id is an identifier (an endpoint URL,
asset:product:ledger:address), not a resolvable reference.
claim.statement can be true or false of the subject. differential
SHOULD name the items that differ, not only a count. sources holds
digests of the artefacts the capsule was derived from (signed source
record, fetched documents, responses, proofs, commits) and MUST NOT
carry evidence bytes, URLs or free text; any other value makes the
capsule invalid. authority_state is the only member whose name
concerns authority, with one permitted value. observed_at is the time
of the observation, not of the build. limitations states what the
measurement does not show; a capsule SHOULD carry at least one, and it
is covered by capsule_id. In runtime_declared and
runtime_observed (reproducibility claims), values not recorded at the
time are UNRECORDED, never omitted or inferred.¶
This profile describes seven comparison kinds, not registered here. They
compare: an MCP
endpoint's registry, mcp.json, server-card and payment-manifest
declarations with its live initialize and tools/list answer
(contract_parity); an agent card's signatures with their verification
under its declared protocol version (a2a_card_signature); an issuer's
list of a tokenised asset's deployments with each ledger's state
(cross_ledger_supply); external indexes' listings of the measurer's
own offerings with its live bytes (self_parity); a signed evaluation
result with a re-run on a second runtime
(cross_runtime_reproduction); and an endpoint's advertised tools at
two times (tool_drift). The seventh, public_signal, records one
reading of a public counter and is observation-only (Section 15).
This is not a list of every kind the implementation publishes: the same
implementation also publishes capsules under measurement.claim_watch and
the five operations.* sub-kinds, neither of which this revision
defines. Two gaps follow. The grammar above admits measurement.* only,
so the 236 operations.* capsules do not match it. The one
measurement.claim_watch capsule does match the grammar, but the kind
is undefined here, so it is outside this profile as well. Open issue 9 in
Section 15 records both gaps: whether those kinds belong to
this profile, or the grammar widens.¶
capsule_id is the SHA-256 digest, as 64 lowercase hexits, of the JSON
Canonicalization Scheme (JCS) [RFC8785] serialisation of the capsule
with capsule_id removed. Issuers MUST NOT place non-finite numbers or
integers whose magnitude exceeds 2^53 in a capsule; such quantities
(token supplies in base units are the common case) MUST be carried as
strings. Issuers SHOULD avoid floating-point values.¶
A capsule file stores each capsule as exactly its JCS bytes, so that a
verifier can recompute capsule_id from the stored line.¶
A batch is a capsule file and a batch record that commits to it. The
capsule file holds one capsule per line, each followed by a single LF,
sorted by capsule_id, with no duplicates.¶
The batch Merkle root is the Merkle Tree Hash of [RFC9162], Section
2.1.1, with SHA-256, over the capsule_id values as 32-byte strings
sorted in ascending byte order. Sorting makes the root a commitment to a
set: reordering the file does not change it, so a changed root always
means changed membership or content. Inclusion of one capsule is shown
by an RFC 9162 audit path (Section 2.1.3), which existing tooling can
verify.¶
The batch record is a JSON object carrying at least schema, as_of,
kind, n_capsules, per-state counts, merkle_root, the construction
in words, the capsule file's SHA-256 and authority_state. It SHOULD
state its inclusion rule and count, by reason, the source rows the rule
excluded (for example, a dimension on which only one public surface
spoke, where nothing was compared), so a reader sees what was not
measured.¶
An index lists each batch's record digest, root, count, signature state
and timestamp state, and carries two roots under the same rule: one over
the union of all capsule_id values (a duplicate across batches is an
error) and one over the batch roots. The index is signed and
timestamped. The implementation also chains daily indexes: each names
the previous day's index by SHA-256 and root and states the number of
days without an index.¶
A batch record or an index is registered as the payload of a COSE_Sign1 message [RFC9052], tagged 18. Capsules are not registered one by one: a capsule reaches the log through the batch root that commits to it (Section 5).¶
The protected header is a map in the core deterministic encoding of Section 4.2.1 of [RFC8949]. It carries:¶
kind, or the fixed string
measurement-capsule-index for an index; iat (6), the signing
time.¶
The unprotected header is empty when the statement is signed. Receipts obtained later are carried under label 394, as in [RFC9943].¶
The Issuer signs the Sig_structure ["Signature1", protected, h'', payload]
of Section 4.4 of [RFC9052]. A verifier decodes the message,
rejects a protected header that is not deterministically encoded, rebuilds
the Sig_structure, and verifies the signature under the key that kid
resolves to. For an attached payload it then checks that the payload is
exactly the JCS serialisation of the record it parses to; for a hash
envelope, that the SHA-256 of the retrieved record equals the payload.¶
A COSE statement is a new artefact over unchanged content. The capsule identifiers, batch roots and index roots it commits to do not change, and the JSON signatures an implementation already published over the same records stay verifiable; the two are published side by side. Appendix A gives vectors for both encodings.¶
No published batch record or index carries a COSE_Sign1 statement: the Issuer's signing service does not yet sign a Sig_structure. The published records are wrapped in a signed-artifact envelope instead, schema csoai.signed-artifact/0.1, whose signature object carries the did did:web:csoai.org#board-attestation-1, the alg Ed25519, the signature sig_ed25519, the digest payload_sha256 and the time signed_at. The record read on 27 October 2026 is at:¶
https://councilof.ai/measurement-capsules/v0.2/ a2a_card/record.signed.json¶
The a2a_card batch measures JOSE agent-card signatures (ES256, EdDSA and RS256) in its subject; that is the subject being measured, not a signature carried by a capsule or a record.¶
Registration follows [I-D.ietf-scitt-scrapi]. The Receipt is a COSE Receipt [RFC9942] whose verifiable data structure is set by the Transparency Service; for a service built on CCF it is the profile in [I-D.ietf-scitt-receipts-ccf-profile]. Inclusion of one capsule is shown in two steps: capsule to batch root by an RFC 9162 audit path under the Issuer's tree, then batch record or index to the log by the Receipt.¶
A Receipt shows that the Transparency Service registered the statement at a time. It does not show that any measurement in it is correct.¶
No Receipt has been obtained. As of 27 October 2026 there is no Transparency Service registration for any batch or index, no COSE Receipt [RFC9942], no entry identifier, no Receipt's SHA-256 and no verifier, because no Receipt exists.¶
The estate publishes a separate aggregate payment-receipt feed at https://councilof.ai/api/receipts/latest, schema (csoai.receipts.latest/0.2), as_of 2026-10-27T15:40:31.490Z, count 26, covering at most the 50 most recent stored receipts: 4 demand-eligible, 17 internal and 5 zero-value (read 27 October 2026). Those are payment receipts. They are not Receipts as defined in this document, and neither is the feed.¶
measurement_state is one string from a vocabulary defined per kind.
The vocabularies in use, with the family each state belongs to (agreement,
verification, reproduction, reading, and absence and inability), are listed
in Appendix B. For every kind:¶
effect_reference, when not null, names a Signed Statement issued under
another profile about the same effect: the profile and revision (for
example draft-schrock-ep-authorization-receipts-13), the digest of the
statement, and optionally where it can be retrieved. The digest MUST be
computed over the octets as registered, since a re-encoded statement has
a different digest under the same signature
[I-D.templeman-scitt-framing-space]. The referenced statement's fields,
in particular its outcome, are not copied. The implementation has not
yet populated this member, so this composition is a proposal, not a
report.¶
A capsule is never edited; any change produces a different capsule. A
correction is a new capsule, in a new batch, whose correction_pointer
records the schema, version and SHA-256 of the source record in which
the change was made, the SHA-256 of the record it supersedes, the state
before (from) and after (to), and the reason, with the fixing commit
where there was one. The superseded capsule remains valid and
retrievable. A change of canonicalisation or Merkle construction changes
identifiers and roots without changing any measurement, and MUST be
published as a new batch, leaving earlier batches in place.¶
sources carries only digests; the evidence stays with whoever holds
it. A digest of a public document is meant to be re-identifiable. A
digest of a non-public, low-entropy artefact can be recovered by
guessing, so Issuers SHOULD NOT place one in sources without blinding,
which the implementation does not provide; its sources are all public
or its own records.¶
subject_id can identify a service run by one person. Issuers SHOULD
measure only surfaces published for machine consumption, SHOULD NOT send
credentials or go beyond discovery (the MCP measurements stop at
initialize and tools/list), and SHOULD offer subjects a route to
request correction or exclusion. Registration is append-only, so a
capsule registered in error can be superseded but not withdrawn;
Issuers SHOULD review batches before registering them.¶
A valid signature on a batch record shows only that the holder of the
key signed those bytes, not that any value is correct, that the
instrument is sound or that the subject agrees with the measurement. A
verifier SHOULD recompute every capsule_id, the batch root, the
record and file digests and the signature, and SHOULD reject a batch in
which any capsule carries a forbidden member or value.¶
The implementation signs with one Ed25519 key, held by a signing service
reached by an authenticated request; it is not a threshold key and no
claim is made about hardware protection. Compromise of the key or of the
request credential allows valid signatures over false records,
including a re-signed chain of daily indexes. Such a rewrite is
detectable only against an anchor dated before it (a Bitcoin-attested
timestamp, a Rekor entry or a Receipt), so verifiers SHOULD check
anchors as well as signatures. The key is published through did:web,
so its authenticity rests on DNS and the Web PKI; retired verification
methods SHOULD remain resolvable.¶
An OpenTimestamps calendar commitment shows only that calendars
received a digest; only a proof upgraded to a Bitcoin attestation dates
the bytes. SHA-1 Git commit identifiers in sources are locators on
which no integrity claim rests.¶
The measurer reads from one location at one time, and surfaces that
should agree may be read hours apart (recorded in limitations). A
VERIFIED card signature does not show who controls the key. A measurer
chooses what to measure, and a batch of subjects likely to disagree
would be accurate capsule by capsule and misleading in aggregate; hence
the inclusion rule in batch records, and consumers SHOULD NOT aggregate
state counts across batches with different inclusion rules.¶
This document has no IANA actions. It uses three media types in the
vendor tree, application/vnd.csoai.measurement-capsule+json,
application/vnd.csoai.measurement-capsule-batch+json and
application/vnd.csoai.measurement-capsule-index+json, which can be
registered without IETF action. None of the three has been registered: the IANA media type registry
listed no csoai entry when it was read on 27 October 2026
(https://www.iana.org/assignments/media-types/application.csv). Their
names are open issue 4.¶
This section records the status of known implementations at the time of posting, following [RFC7942]. RFC Editor: please remove this section before publication.¶
This is also where the implementation does not yet match this profile. The
kind grammar of Section 3 admits measurement.*
only. Of the 10,737 capsules the signed index lists, 236 carry an
operations.* kind and do not match that grammar; the index records
those 236 together under the kind operations. One further capsule
carries the kind measurement.claim_watch, which this revision does
not define. The state vocabularies of both are in
Appendix B.¶
CSOAI measurement capsule builder (Council of AI, contact nicholas@csoai.org). Every count, root, commit and URL in this section is read from the live artefacts on the day of posting and given with the time of reading; none is carried over from -00.¶
Anchors: the OpenTimestamps [OTS] state of each record's proof (calendar commitment or Bitcoin attestation) and the Rekor [REKOR] log indexes. Neither is a SCITT Transparency Service or issues Receipts. Read 27 October 2026 from the index (as_of 2026-10-01T08:11:31Z) and https://councilof.ai/measurement-capsules/v0.2/anchors.json (as_of 2026-10-01T08:52:55Z): the five batches a2a_card (33), contract_parity (9,148), mill_cross_runtime batch 1 (14), mill_cross_runtime batch 2 (140) and tool_drift (497) are BITCOIN_ATTESTED, each with one Bitcoin block-header attestation and three pending calendar attestations; the five batches claim_watch (1), cross_ledger (383), operations (236), public_signals (119) and self_parity (166) are PENDING_CALENDAR_COMMITMENT, each with pending calendar attestations only (two each, three for public_signals). At index level the proof is (measurement-index-v0.2-2026-10-01.json.ots), SHA-256 1f8d2994895a74ff384a1a1331e398abdd98d4df8f59850c91436c823b350360, state PENDING_CALENDAR_COMMITMENT with no Bitcoin block height; a calendar commitment alone dates nothing. The estate has since published an upgraded proof for the same index file, re-read from the calendars, carrying a Bitcoin block-header attestation at height 969421 (block time 1790842779), SHA-256 671b14f1a24dbe5757a15416954e540f7fa0a4e38ca6f7e873b5d7c0a70763ab (https://huggingface.co/datasets/csoai/evidence-index/tree/main/ots-upgraded/2026-10-01). One Rekor entry is published for this index and none per batch; its state is INCLUDED and its inclusion proof verifies:¶
logIndex 3033118403
integratedTime 1790844616
uuid 108e9186e8c5677a6bee5ebdf0c4c372
4f342d9792170c896c507407e23cecc4
6d29859461be4da9
¶
No per-batch Rekor log indexes are published. Earlier daily indexes and chain heads carry entries of their own, the 2026-09-30 index among them with logIndex 3014901172; an entry dated before a rewrite is what detects a re-signed daily-index chain. The XRP Ledger anchor is PREPARED_NOT_SUBMITTED: memo drafts exist and nothing has been submitted to the XRP Ledger.¶
The experiment asks whether an unaffiliated, authority-free
declared-versus-observed record is useful alongside actor-issued
receipts in a SCITT deployment. It is judged by four outcomes: (1) an
implementation written by another party from this text recomputes the
identifiers and roots of a published batch; (2) a batch is registered
with a Transparency Service operated by another party and its Receipt
is verified by a third; (3) a capsule carries an effect_reference to a
Signed Statement from a different Issuer; (4) the open issues are
resolved and published as corrections without loss of existing batches.
If none occurs within two revisions, the author will withdraw the draft.¶
(1) COSE_Sign1 encoding: specified in this revision
(Section 6). (2) The superseded capsule_id in
correction_pointer: open. (3) A per-kind allowlist of member names
in place of the denylist: open; Appendix B lists state
vocabularies only. (4) Neutral names for the csoai.-prefixed
identifiers and media types: open; a rename changes every identifier and
would be published as new batches. (5) Blinded digests for non-public
sources: open. (6) Whether observation-only kinds belong here: open.
(7) An explicit self-measurement member: open. (8) Transparency Services
differ in the Issuer identities their registration policies accept (for
example did:x509 rather than did:web); which forms a measurer needs is
open. (9) The kind grammar of Section 3 admits
measurement.* only, but the implementation publishes 236 capsules under
five operations.* kinds that it does not admit, recorded in the index
together as the kind operations; it also publishes one capsule under
measurement.claim_watch, which the grammar admits and this revision
does not define. Whether those kinds belong to this profile or the grammar
widens: open.¶
These vectors are synthetic. The signing key is the TEST 1 key of
Section 7.1 of [RFC8032], whose secret is published there, so
nothing it signs means anything. Subjects are under .example, and
source digests are SHA-256 values of labelled placeholder strings. The
full vectors, their generator and a checker that shares no code with the
generator are published at
https://raw.githubusercontent.com/CSOAI-ORG/councilof-ai/master/docs/ietf/measurement-capsule-01/test-vectors/vectors.json
(vectors.json, SHA-256
33d1545489f880b6beb84bb0086cc18ec9495f429783216afa9be60df36c6a55),
with gen_vectors.py and check_vectors.py in the same directory at
https://github.com/CSOAI-ORG/councilof-ai/tree/master/docs/ietf/measurement-capsule-01/test-vectors,
read 27 October 2026.¶
Public key (hex): d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a. kid: did:web:measurer.example#test-key-1.¶
The first of five capsules, as its JCS bytes. Line breaks are added for display only; the bytes contain none.¶
{"authority_state":"NONE: measurement only; this capsule grants and
records no execution authority","capsule_id":"790c6908bf69e6863301aa
6cdb922ef2f51e37cc8bd6374da261bf5a39a0ae4d","claim":{"statement":"th
e protocol version a registry entry declares for this endpoint
equals the version the endpoint returns from initialize"},"correctio
n_pointer":null,"declared":{"protocol_version":"2025-06-18","surface
":"registry"},"differential":{"differs":["protocol_version"]},"effec
t_reference":null,"kind":"measurement.contract_parity","limitations"
:["the registry entry and the endpoint were read 40 seconds apart
from one location"],"measurement_state":"INCONSISTENT","observed":{"
exchange":"initialize","protocol_version":"2025-11-25"},"observed_at
":"2026-09-25T12:00:00Z","schema":"csoai.measurement-capsule/0.2","s
ources":{"initialize_response":"62e37c1818f25a0bd931d75c9e1da28b262d
50afd980c39172165ab6ed34fa07","registry_entry":"bc012a010624de5fe157
b48c4c8222b82d1a326374a44c67a428ad25f836d387"},"subject_id":"https:/
/mcp-a.example/mcp"}
¶
capsule_id (SHA-256 of the JCS bytes without capsule_id):¶
790c6908bf69e6863301aa6cdb922ef2f51e37cc8bd6374da261bf5a39a0ae4d¶
Five capsule_id leaves, sorted ascending:¶
790c6908bf69e6863301aa6cdb922ef2f51e37cc8bd6374da261bf5a39a0ae4d 7933cc6a2b3daa915e651da0e70bbb558640763062e08bbf831e8cc7946c7570 97e3e57263664c1f980664c73da0aad987daf292552b5d9f0e87b594d2dcde8a bd7cef2dd9f66b6140ab03cfd4a3958aa5e91f8e54df9533de27a9e891f541a1 c79034f8eb5e79924077a6a18530cd6033547230f373d0340d2ceeae0b09ae62¶
RFC 9162 Merkle Tree Hash (SHA-256):¶
609d0f628fd70eeefd53d834333af8efa4d12b6e536f28f421f2cad18063b092¶
Audit path for leaf index 2 of 5, verifiable with Section 2.1.3.2 of [RFC9162]:¶
ec8bb44e799ff3af50b4e5fb250f5090689b7e30d54a44ff92378e45607624d9 015d548669d37c398fa2c86502caa5edf42fde88c502e2df194feb3b3634128f 2726cbfb4f5551190f1c834055f1db56334cfe62ed55db73c4dee7233dbbafcb¶
SHA-256 of the batch record's JCS bytes:¶
77c6996d9794b8defcf4e885470c7138fe78c0cd16ec63b6b6497cae8e8af975¶
Protected header (EDN, then the deterministic encoding in hex):¶
{1: -19, 3: "application/vnd.csoai.measurement-capsule-batch+json",
4: 'did:web:measurer.example#test-key-1', 15: {1:
"did:web:measurer.example", 2: "measurement.contract_parity", 6:
1790000000}}
a401320378346170706c69636174696f6e2f766e642e63736f61692e6d656173
7572656d656e742d63617073756c652d62617463682b6a736f6e045823646964
3a7765623a6d656173757265722e6578616d706c6523746573742d6b65792d31
0fa30178186469643a7765623a6d656173757265722e6578616d706c6502781b
6d6561737572656d656e742e636f6e74726163745f706172697479061a6ab13b
80
¶
Signature over the Sig_structure:¶
cec79a49b8eb0fbebaccbe7a907029257e33838e8fab950f91699b2ef0c9a02a 907fe789805f552f75763dbcdc881be034661c039375bfcf039bed630b666b06¶
Protected header (EDN, then hex). Label 3 is absent.¶
{1: -19, 4: 'did:web:measurer.example#test-key-1', 15: {1:
"did:web:measurer.example", 2: "measurement.contract_parity", 6:
1790000000}, 258: -16, 259:
"application/vnd.csoai.measurement-capsule-batch+json", 260:
"https://measurer.example/batches/contract_parity/record.json"}
a601320458236469643a7765623a6d656173757265722e6578616d706c652374
6573742d6b65792d310fa30178186469643a7765623a6d656173757265722e65
78616d706c6502781b6d6561737572656d656e742e636f6e74726163745f7061
72697479061a6ab13b801901022f19010378346170706c69636174696f6e2f76
6e642e63736f61692e6d6561737572656d656e742d63617073756c652d626174
63682b6a736f6e190104783c68747470733a2f2f6d656173757265722e657861
6d706c652f626174636865732f636f6e74726163745f7061726974792f726563
6f72642e6a736f6e
¶
Payload (SHA-256 of the batch record's JCS bytes) and signature:¶
77c6996d9794b8defcf4e885470c7138fe78c0cd16ec63b6b6497cae8e8af975 4e09a643366cabff54914397ef7389b6f53d2706bdaee6aca2fdd6c0361e284e b7e1da1f2ab986c0bd09127f2de6b07ccf61cf28ba5600b18778558418d5c504¶
Each control is built to be rejected and names the one rule it breaks. A verifier counts a control only when it is rejected for that rule. For each rule, relaxing that rule alone in the checker changes the result of the control that names it and of no other vector.¶
| Control | Rule | Why it is rejected |
|---|---|---|
| N1-forbidden-member | no-authority-member | a member named decision is forbidden at any depth |
| N2-source-not-a-digest | sources-digest-only | sources carries a URL where only digests are allowed |
| N3-stored-line-not-jcs | stored-bytes-are-jcs | the stored line is indented JSON, so it is not the JCS bytes the identifier covers |
| N4-payload-byte-flipped | cose-signature | one payload byte of V3 changed; the signature no longer verifies |
| N5-hash-envelope-with-label-3 | rfc9995-no-label-3 | RFC 9995: label 3 (content_type) MUST NOT be present with a hash envelope payload |
| N6-duplicated-last-leaf | leaf-set-no-duplicates | the leaf list repeats its last member; its root differs from V2 and n no longer equals n_capsules |
This appendix is generated at build time from the implementation's vocabulary file: for each kind, each state, the family it belongs to and a one-line meaning. It is not written by hand, so that the text and the implementation cannot drift apart. The families are the five named in Section 8: agreement, verification, reproduction, reading, and absence and inability. The kinds and the states are those published in the capsule bodies read on 27 October 2026. A state records what the measurement established and nothing more, so no entry below says that a measurement is good, bad, correct or incorrect.¶
| State | Family | Meaning |
|---|---|---|
| VERIFIED | verification | The card's signatures verified under the protocol version the card declares. |
| FAILED | verification | The card's signatures did not verify under the protocol version the card declares. |
| UNCHECKABLE | absence and inability | The signature could not be checked, so the capsule records no outcome for it. |
| State | Family | Meaning |
|---|---|---|
| QUARANTINED | absence and inability | A watched claim was quarantined; the sealed subject's claims and evidence are withheld until the owner publishes the claim record, and only digests are carried. |
| State | Family | Meaning |
|---|---|---|
| CONSISTENT | agreement | The declarations read and the live answer agree on the compared dimension. |
| INCONSISTENT | agreement | The declarations read and the live answer differ; the state does not say which is right. |
| UNCHECKABLE | absence and inability | The live read did not answer the compared dimension, so the two were not compared. |
| State | Family | Meaning |
|---|---|---|
| CONSISTENT | agreement | The issuer's listing and the ledger's deployment agree. |
| INCONSISTENT | agreement | The issuer's listing and the ledger's deployment differ; the state does not say which is right. |
| STATE_PROOF_VERIFIED | verification | A proof checked against a block header's state commitment, the header not checked against consensus. |
| STATE_PROOF_RECORDED | verification | The state proof was kept and did not verify. |
| OPERATOR_API | verification | The figure came from an operator's answer, no proof. |
| LISTED_NOT_READ | absence and inability | The deployment is listed and was not read; not read is not zero and not absent. |
| PERMISSIONED_NOT_READABLE | absence and inability | The issuer's listing is readable only with permission that was not given, so nothing was read. |
| ISSUER_LIST_UNAVAILABLE | absence and inability | The issuer's list of deployments could not be obtained, so nothing was read. |
| UNCHECKABLE | absence and inability | Nothing was read, so nothing was compared. |
| NOT_A_SUPPLY_CLAIM | reading | The issuer's entry states no supply figure for the deployment, so there is nothing to compare. |
| TOTAL_COMPLETE | reading | Every deployment the issuer lists was read with a supply figure, so a total is given. |
| TOTAL_PARTIAL | reading | Some deployments the issuer lists were not read with a supply figure, so no total is given. |
| State | Family | Meaning |
|---|---|---|
| REPRODUCED_ITEMWISE | reproduction | The re-run on the second runtime gave the same grade for every item. |
| REPRODUCED_AGGREGATE_ONLY | reproduction | The re-run gave the same aggregate, but the grades of some items differed. |
| NOT_REPRODUCED | reproduction | The re-run's aggregate differed from the signed evaluation result's aggregate. |
| State | Family | Meaning |
|---|---|---|
| MEASURED | reading | The public counter was read once and returned a value. |
| PARTIAL | reading | The read returned only part of the signal, a named list rather than the whole population. |
| UNCHECKABLE | absence and inability | The read returned no value, so nothing is recorded about the signal. |
| State | Family | Meaning |
|---|---|---|
| CONSISTENT | agreement | The index's listing of the offering agrees with the live bytes. |
| INCONSISTENT | agreement | The index's listing of the offering differs from the live bytes; the state does not say which is right. |
| NOT_LISTED | absence and inability | A complete read of the index found no listing of the offering. |
| NOT_DECLARED | absence and inability | The offering's own surface declares no such field; this is recorded so the surface can be completed, and it is not a contradiction. |
| UNCHECKABLE | absence and inability | The index could not be read completely, so no listing could be established. |
| State | Family | Meaning |
|---|---|---|
| UNCHANGED_AT_NAME_GRANULARITY | agreement | The tool names advertised at the second read are the same as at the first. |
| TOOLS_ADDED | agreement | The second read lists tools the first did not. |
| TOOLS_REMOVED | agreement | The second read omits tools the first listed. |
| TOOLS_ADDED+TOOLS_REMOVED | agreement | The second read both lists tools the first did not and omits tools the first listed. |
| UNCHECKABLE | absence and inability | The first read was incomplete or unsuccessful, so the two tool lists could not be compared. |
The 236 operations capsules carry five sub-kind values, which the index records together as the kind operations.¶
| State | Family | Meaning |
|---|---|---|
| BITCOIN_ATTESTED | verification | The anchored bytes carry an OpenTimestamps proof with a Bitcoin block-header attestation. |
| PENDING_CALENDAR_COMMITMENT | absence and inability | The anchored bytes carry an OpenTimestamps proof with pending calendar attestations only; a calendar commitment alone dates nothing. |
| INCLUDED_PROOF_VERIFIES | verification | The artefact's signed preimage is in the log and its inclusion proof verifies. |
| State | Family | Meaning |
|---|---|---|
| TIME_TO_CORRECT_UNMEASURED | absence and inability | The correction was recorded, but the time from detection to correction was not recorded, so it is not measured. |
| State | Family | Meaning |
|---|---|---|
| UNCHECKABLE | absence and inability | The deploy source could not be read for the window, so its events are not recorded. |
| State | Family | Meaning |
|---|---|---|
| LANDED_NOT_SHIPPED | agreement | The change landed on the branch; the release covering the window does not carry it. |
| State | Family | Meaning |
|---|---|---|
| PRESENT_SHA256_UNRECORDED | absence and inability | The files are present at the commit, but no SHA-256 was recorded for them, so none was checked. |
kind grammar admits measurement.* only, and 236 of the
published capsules carry operations.* kinds it does not admit; the
one measurement.claim_watch capsule matches the grammar but the
kind is undefined here; open issue 9 records both.¶
rfc tag no longer declares a submissionType. The
Datatracker records this draft as an individual submission with no stream,
and a declared stream made its own submission check report
SUBMISSION_TYPE_UNEXPECTED. RFC 7991 makes IETF the default for the
attribute, so the declared stream is unchanged and no section of the
document changes; only this change log records it.¶
The drafts cited in the introduction sharpened the distinction this document draws. Any mischaracterisation of them is the author's.¶