| Internet-Draft | VTL | July 2026 |
| El Khatabi | Expires 16 January 2027 | [Page] |
This document profiles a verifiable-telemetry ledger for resource-constrained deployments. Its interoperability boundary begins with exact canonical-record byte strings that an upstream system has already produced. The profile fixes admission and assignment of those byte strings to serial-numbered segments, deterministic commitment-tree calculation, a Concise Binary Object Representation (CBOR) segment artifact, a verification manifest, three disclosure classes, and binding of the segment-artifact digest to external timestamp channels. Transport framing, decryption, anti-replay processing, payload interpretation, and source-telemetry-to-record mapping are outside this profile. Segment closure uses a deployment-configured elapsed-time interval and does not depend on source or gateway calendar dates. RFC 3161 timestamp responses are the mandatory-to-implement interoperable timestamp channel. OpenTimestamps (OTS) and peer signatures are optional parallel channels.¶
The profile enables independent recomputation and audit of disclosed evidence from the admitted canonical-record bytes onward. It does not verify how source telemetry was authenticated, interpreted, or mapped to those bytes, and it does not cover device onboarding, end-to-end security of sensor values, or safety decisions.¶
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 16 January 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.¶
Long-lived telemetry deployments need evidence that record bytes disclosed later are the same bytes a ledger producer committed when they were admitted, even when upstream delivery is intermittent and verification happens later.¶
Two trust questions must be distinguished. The first is whether a source was genuine, authorized, and mapped correctly. The second is whether, after exact record bytes were selected for commitment, a later verifier can determine that those bytes, the ledger artifact, and external evidence still agree. This profile standardizes the second question.¶
This memo is an Independent Submission. It is not an Internet Standard and has not been evaluated as having IETF community consensus.¶
The profile begins at an explicit byte-level handoff. An upstream admission system constructs one deterministic-CBOR canonical-record byte string and presents it to the ledger producer. Source eligibility, transport security, anti-replay processing, payload interpretation, and source-to-record mapping occur before that handoff and are outside this profile. The interoperability contract begins with the exact byte string presented for admission.¶
Protocol at a Glance¶
The following informative summary provides a reading path through the normative requirements that follow:¶
SHA-256(0x00 || record), sorts the leaf hashes, and calculates
segment_root over the complete sorted list using the
domain-separated tree construction in Section 4.3.
It partitions the same list deterministically into the batch objects
embedded in the segment artifact. Batch roots describe their respective
batches; they are not combined to calculate segment_root.¶
| Object | Status | Principal role |
|---|---|---|
| Canonical-record bytes | Authoritative admitted input | Exact leaf preimage after admission |
| Segment CBOR | Authoritative segment artifact | Hashed, chained, and externally timestamped |
| Manifest | Producer claim; non-authoritative | Indexes the bundle and claims disclosure class |
| Verifier result | Verifier-authored scoped output | Reports scope, checks, channels, and outcome |
Segment intervals are ledger batching rules, not source-reporting
periods or civil-time claims. The producer assigns each admitted
record to the logical interval open at its admission linearization
point and uses a non-decreasing elapsed-time source for interval
closure. Source arrival time, upstream processing time,
ingest_time, device_time, and UTC do not select
segment membership. Segment identity is
(ledger_id, segment_number), and a sealed segment is not
reopened. Section 4.4 specifies boundary ordering, empty intervals,
size-triggered closure, policy changes, and recovery behavior.¶
Source telemetry
|
v
+----------------------------+ OUTSIDE THIS PROFILE
| Upstream admission system |
| auth / replay / projection |
+----------------------------+
| exact canonical-record bytes
======|================================================ boundary
v
+----------------------------+ --> segment CBOR ------> Verifier
| Ledger producer |
| admit / assign / commit | --> artifact digest
| seal / chain | |
+----------------------------+ +--> timestamp: RFC 3161 / OTS
+--> attestation: peers (optional)
Successful verification establishes consistency within the scope reported by the verifier. When the necessary material is disclosed, it can show that exact record bytes produce the claimed commitments, that the authoritative artifact produces the digest bound by the disclosed external evidence, and that disclosed predecessor artifacts form the claimed chain adjacency. It does not establish source authenticity, correct source-to-record mapping, dataset completeness, physical truth, or the absence of selective drops before admission.¶
This profile covers the ledger evidence path beginning with admission of an already-formed canonical-record byte string:¶
It does not specify source transport or framing, authentication, decryption or other transport security, anti-replay processing, manufacturer identity, onboarding, fleet inventory, PKI policy, network admission, source buffering, identifier or message-type mapping, payload schemas, source-to-record projection, or firmware orchestration. Those functions can be colocated with the ledger producer, but they remain outside the interoperability claim made by this document.¶
The ledger producer is trusted to validate and admit each accepted byte string, assign it to one segment, preserve its exact octets, maintain durable segment state, and construct the specified artifacts. An upstream system that constructs the record bytes is separately trusted for their source semantics but is outside this profile.¶
This profile makes post-admission inconsistency detectable. It does not prove that upstream admission was correct, reveal a source event that was never admitted, establish ingestion completeness, validate a source-to-record mapping, or show that a committed measurement was physically true.¶
Section 2 defines the common terminology, and Section 3 identifies the system roles. Producer implementers should focus on Sections 4 through 6, Section 9, and Section 10. Verifier implementers should focus on Sections 4 through 7, Section 9, and Appendices A through D. Operators should additionally read Sections 10 through 12 and Section 14. Commitment-profile, versioning, and registry designers should read Sections 8, 13, and 15.¶
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.¶
Terms:¶
ledger_id, rendered as 32 lowercase hexadecimal characters. Segment serial numbers are scoped to this identifier.¶
ledger_id. The epoch segment is segment zero and carries the zero predecessor value. A ledger epoch is distinct from a transport-key epoch.¶
empty_mode, a segment can be empty. Segment membership is selected by the admission linearization point and a non-decreasing elapsed-time close rule, not by record timestamps.¶
segments/<segment-number>.cbor, where <segment-number> is the 20-digit, zero-padded decimal rendering of segment_number.¶
interval_ms and empty_mode. It is a gateway configuration claim, not independent proof that the gateway observed the claimed elapsed duration.¶
batches/00000000000000000007-00000000000000000000.batch.json) exported for convenience. When disclosed, it MUST match the corresponding batch object in the authoritative segment artifact.¶
segments/<segment-number>.ots.meta.json, a separate non-authoritative metadata file associated with an OTS proof and authoritative segment artifact, linking the artifact digest to the proof path. It is not a commitment input.¶
In this document, optional parallel attestation channels are not required for baseline conformance. A conforming deployment MUST use at least one timestamping channel and MUST implement the [RFC3161] channel. OTS ([OTS]) and peer signatures are optional; when present, they MUST bind to the same authoritative segment-artifact digest and verifiers MUST report their results separately.¶
The normative input to this section is an exact canonical-record byte string that has already been produced by an upstream admission system. The interoperable core begins at that byte-level handoff and covers record admission, segment assignment, deterministic hashing and tree calculation, segment artifacts, disclosure, and verification. No source transport, decryption, anti-replay, payload interpretation, or source-to-record projection is defined by this document.¶
The protocol input defined by this document is one exact canonical-record byte string. The byte string MUST encode exactly one CBOR data item using the record shape below and the deterministic encoding constraints in Section 4.2. A ledger producer MUST reject a proposed input that does not satisfy those byte-level constraints.¶
Once admitted, the exact supplied octets are authoritative. The ledger producer MUST use those octets, without modification, as the leaf preimage under Section 4.3. It MUST NOT decode and re-encode, normalize, enrich, remove, reorder, or otherwise substitute a different byte string for commitment. Each admission event contributes one record occurrence, including when two admitted occurrences have identical byte strings.¶
Source transport, framing, authentication, decryption, anti-replay processing, duplicate-submission policy, device-identifier mapping, message-type mapping, payload interpretation, and construction of the canonical-record byte string are upstream of this boundary and are not specified or verified here. A physical gateway MAY perform those functions and ledger production in one implementation, but its interoperability claim under this document begins only with the exact byte string passed across this logical boundary.¶
For verifiable-telemetry-canonical-cbor-v2, each
canonical-record byte string encodes the following fixed seven-element
CBOR array:¶
canonical-record-v1 = [ version: 1, device_id: bstr .size 8, fc: uint, ingest_time: uint, device_time: uint / nil, kind: uint, payload: any ]¶
The positional labels are conventional names for inspecting disclosed records; they do not move source-to-record mapping into this profile. Their byte-level requirements are:¶
version is the unsigned integer 1.¶
device_id is an opaque 8-octet identifier assigned upstream. This document defines no mapping from a transport or deployment alias to this value.¶
fc is an unsigned upstream-supplied sequence value. This document defines no replay or duplicate-suppression semantics for it.¶
ingest_time is an unsigned count of whole non-leap seconds since 1970-01-01T00:00:00Z. Its assignment and accuracy are upstream responsibilities, and it MUST NOT select segment membership.¶
device_time is an unsigned application timestamp or null. Its epoch and unit are upstream semantics, and it MUST NOT select segment membership.¶
kind is an unsigned application discriminator. This document defines no message-type or payload-family mapping for it.¶
payload is one CBOR data item permitted by Section 4.2. Its schema and meaning are outside this profile.¶
A different record array shape or different byte-level field type is
a different commitment profile and requires a distinct
commitment_profile_id. Application schemas MAY separately
define the meanings of device_id, fc,
device_time, kind, and payload, but
successful verification under this document does not validate those
external semantics.¶
Class A recomputation starts with the disclosed canonical-record byte strings. It demonstrates that those exact bytes produce the disclosed leaf digests, roots, and authoritative segment artifact. It does not reconstruct the bytes from source telemetry. Conformance vectors for this profile therefore MUST begin with exact canonical-record byte strings; transport messages and upstream projection fixtures, if supplied, are informative and are not inputs to baseline conformance.¶
This section does not define a new general-purpose CBOR variant. It
records the narrow deterministic CBOR encoding used for commitment
bytes by this profile.
The identifier verifiable-telemetry-canonical-cbor-v2 names
this commitment recipe so verifiers can tell which byte-level rules
were used; see Section 13.3 for allocation
policy.¶
The authoritative commitment artifacts, namely CBOR canonical-record artifacts and the canonical segment artifact, use a constrained subset of the length-first core deterministic encoding requirements in Section 4.2.3 of [RFC8949]. For commitment bytes in this profile, the following concrete choices apply:¶
Implementations MUST NOT accept generic CBOR serializers as authoritative commitment encoders. An encoder is acceptable only if it yields the same bytes as these rules.¶
JSON projections of canonical-record artifacts and segment artifacts are optional and non-authoritative. They MUST NOT be used as commitment inputs. When produced, such projections SHOULD follow [RFC8785].¶
Upstream systems MAY use any transport or internal encoding. Only the
exact canonical-record byte string admitted at
Section 4.1 is an authoritative record
commitment input. A different record encoding is not this profile
unless it is identified by a distinct
commitment_profile_id and verified under its own rules.¶
For a given segment S, the current commitment profile
computes segment_root from canonical-record bytes using the
domain-separated tree shape of Section 2.1.1 of
[RFC9162], specialized to SHA-256 and to the multiset
ordering below. SHA-256 is defined by [RFC6234].¶
For each exact canonical-record byte string record, compute
leaf_hash = SHA-256(0x00 || record). Sort the resulting raw
32-octet leaf hashes in ascending byte order. Lowercase hexadecimal
is only their artifact representation; sorting those fixed-width
lowercase strings is equivalent to sorting the raw bytes.¶
Let MTH(L) operate on the sorted list of already-computed
leaf hashes. MTH({}) = SHA-256("") and
MTH({x}) = x. For a list of n > 1 hashes, let
k be the largest power of two strictly less than n,
and compute
MTH(L) = SHA-256(0x01 || MTH(L[0:k]) || MTH(L[k:n])).
Implementations MUST NOT duplicate an unpaired final hash. The
prefixes 0x00 and 0x01 provide leaf/parent domain
separation, and the recursive split gives every leaf count a unique
tree shape.¶
For an emitted empty segment, batches MUST be an empty array
and segment_root MUST equal MTH({}), the SHA-256 digest of zero bytes:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.
Its closure_policy.empty_mode MUST be emit; an empty
artifact under suppress mode is invalid.
For a non-empty segment, batches MUST contain at least one
non-empty batch. The resulting segment_root is deterministic
for the multiset of committed canonical records. Because leaf
digests are sorted before reduction, the root does not commit to
admission order. Admission order selects segment membership at the
boundary but is not itself a verifier-visible total-order claim.¶
Any future change to this calculation that alters commitment bytes
MUST use a new
commitment_profile_id.¶
Normal Interval Timing and Admission¶
Segment formation uses a gateway elapsed-time source that MUST be
non-decreasing and MUST progress during normal operation while an
interval is open. Its resolution MUST be no greater than the configured
interval_ms. The configured interval_ms is a fixed
elapsed duration. It is not a civil-
time duration and MUST NOT be aligned by local midnight, UTC
midnight, time zone, daylight-saving transition, or leap second.
The first logical interval of an epoch opens when the ledger is activated.
Each normal or early closure immediately opens the next logical
interval. Logical intervals continue across idle periods in both
empty modes; suppress changes artifact emission and serial
consumption, not the elapsed-time schedule.¶
The gateway MUST serialize the interval-boundary transition with the
admission linearization point. For an interval whose elapsed-time
deadline is T:¶
T belongs to the current logical interval.¶
T or later, the gateway MUST process the boundary before another acceptance can linearize.¶
T, but if canonical-record admission linearizes at or after T, the record belongs to the next logical interval.¶
device_time, and ingest_time MUST NOT override this assignment.¶
The gateway MUST determine deadline expiry by checked elapsed-time
subtraction; it MUST NOT add interval_ms to an absolute
counter in a way that can wrap. If elapsed time cannot be represented
or compared safely, the gateway MUST enter the recovery procedure
below before accepting another record.¶
Policy Changes and Early Closure¶
The gateway snapshots closure_policy when a logical interval
opens. That snapshot MUST remain unchanged through closure. A normal
configuration update becomes effective for the next logical
interval. An immediate update MUST first close the current logical
interval under the old snapshot. It emits an artifact with
close_reason equal to reconfigure unless the interval
is empty under suppress mode, in which case it emits no
artifact and consumes no segment number.¶
Early closure is permitted only for a condition represented by the
committed close_reason. A gateway MUST NOT place a record
whose acceptance linearizes after the interval deadline into the
expired interval merely because closure processing was late. Late
closure is an operational fault and SHOULD generate an alarm.¶
Limits and Close-Reason Selection¶
closure_policy.record_limit, when non-null, is the maximum
number of admitted records in one logical interval. The interval
closes immediately after the acceptance that makes the record count
equal to record_limit.¶
closure_policy.size_limit_bytes, when non-null, is a close
threshold for the sum of the lengths of the exact admitted
canonical-record byte strings. After an acceptance has linearized, if
the resulting byte total is greater than or equal to
size_limit_bytes, the producer MUST close that logical
interval before another acceptance can linearize. The triggering
record remains assigned to the interval because segment assignment is
final at the admission linearization point. Consequently,
size_limit_bytes is not a hard pre-admission maximum and an
emitted segment can exceed the threshold by the contribution of its
final admitted record. If a single record admitted to an empty
interval exceeds size_limit_bytes, that record forms a
one-record interval, which MUST close before another acceptance can
linearize. Threshold comparisons and byte-count updates MUST use
checked arithmetic; the producer MUST enter recovery or stop
acceptance before acknowledging a record if the new total cannot be
represented safely.¶
If multiple close conditions are simultaneously true, the committed
close_reason MUST be selected by this precedence, from
highest to lowest: recovery, shutdown,
reconfigure, size_limit, record_limit,
interval, then manual. The selected reason does not
change which acceptances already linearized into the interval.¶
Empty Intervals and Timer Continuity¶
While elapsed-timer continuity is maintained, in emit mode
every logical interval produces an artifact;
an empty interval uses the empty construction in
Section 4.3. In suppress mode, an empty
logical interval produces no artifact and consumes no segment number.
The next emitted artifact uses the next contiguous number. A
suppressed interval makes no completeness or non-observation claim.¶
Suspend time counts toward interval_ms when the selected
elapsed-time source advances across suspend. If it does not, or if
its continuity is uncertain, the gateway MUST apply the recovery
procedure before accepting another record.¶
Recovery and Durable State¶
After restart or failover, the gateway MUST recover the active
ledger_id, next segment number, policy snapshot, and any open
interval state before accepting more telemetry. If elapsed-time or
open-interval state is uncertain, the gateway MUST NOT infer the
boundary from a possibly regressed wall clock. It MUST either stop
acceptance or seal recoverable material with close_reason
equal to recovery before accepting into a new interval. It
MUST NOT synthesize historical empty artifacts and represent them as
having been sealed at missed deadlines.¶
The admission linearization point is a durable transaction boundary. Before acknowledging acceptance, the producer MUST make the exact canonical-record octets, their membership in the open interval, the interval record count and byte count, and the corresponding recovery state atomically durable or recoverable. After a crash, an acceptance MUST be recovered exactly once in the same logical interval, or it MUST be treated as never having completed. Segment sealing MUST atomically persist the authoritative artifact, its digest, the next serial allocation, and the new open-interval state before admission resumes.¶
Deterministic Batch Partitioning¶
For a non-empty interval, compute the complete sorted leaf-hash list
defined in Section 4.3. Partition that list into
consecutive batches of at most
closure_policy.batch_record_limit hashes. Batch zero contains
the first hashes, batch one the next hashes, and so on; only the last
batch can contain fewer than the limit. This rule is the sole
baseline batch partitioning rule and is independent of storage flushes,
worker scheduling, or input-file layout.¶
The authoritative segment artifact is a deterministic CBOR-encoded segment record produced under Section 4.2. It is the stable segment-scoped object of commitment verification. It commits to one record multiset, its ledger identity, serial number, closure policy and reason, and predecessor artifact. It is not a transport envelope, publication statement, or complete verification claim.¶
A segment artifact is interpreted only under its in-band
commitment_profile_id. Because that identifier is inside the
authoritative bytes, every proof over the segment-artifact digest
binds the commitment semantics. A verifier-facing manifest MUST
repeat the same value and verifiers MUST reject a mismatch. Verifiers
MUST NOT infer the commitment profile from the file name, media type,
segment-record version, or proof sidecar alone.¶
The segment record contains exactly these fields:¶
version (uint): segment-record schema version, exactly 2.¶
commitment_profile_id (tstr): exactly verifiable-telemetry-canonical-cbor-v2.¶
ledger_id (tstr): stable ledger identifier consisting of exactly 32 lowercase hexadecimal characters.¶
site_id (tstr): non-empty site identifier.¶
segment_number (uint): serial number in the range 0..(2^64-1).¶
closure_policy (map): immutable policy snapshot for this logical interval, containing exactly version equal to 1; positive uint64 interval_ms and batch_record_limit; record_limit and size_limit_bytes, each a positive uint64 or null; and empty_mode equal to emit or suppress.¶
close_reason (tstr): exactly one of interval, reconfigure, record_limit, size_limit, shutdown, recovery, or manual.¶
prev_segment_sha256 (tstr): SHA-256 digest of the exact previous authoritative segment-artifact bytes, as 64 lowercase hexadecimal characters, or the epoch predecessor value defined in Section 4.6.¶
batches (array): authoritative batch objects sorted by batch_number; exactly empty for an empty emitted segment.¶
segment_root (tstr): deterministic segment root as 64 lowercase hexadecimal characters.¶
Each batch object contains exactly these fields:¶
version (uint): batch-record schema version, exactly 2.¶
ledger_id (tstr): the containing segment's ledger_id.¶
site_id (tstr): the containing segment's site_id.¶
segment_number (uint): the containing segment's segment_number.¶
batch_number (uint): batch serial in the range 0..(2^64-1), unique within the segment.¶
merkle_root (tstr): batch Merkle root as 64 lowercase hexadecimal characters.¶
count (uint): positive number of committed canonical records in the batch.¶
leaf_hashes (non-empty array of tstr): leaf hashes sorted as lowercase hexadecimal strings.¶
The batch objects embedded in the segment artifact are authoritative
batch metadata. For a non-empty segment, batch objects MUST be sorted
by ascending batch_number, and batch numbers MUST be unique
and contiguous starting at zero. Their leaf lists MUST be the
consecutive partitions of the complete sorted segment leaf list
required by Section 4.4.¶
ledger_id, site_id, and segment_number MUST equal the containing segment fields.¶
count MUST equal the length of leaf_hashes and MUST be greater than zero.¶
merkle_root MUST equal the Merkle reduction of that batch's leaf_hashes under Section 4.3.¶
leaf_hashes MUST equal the segment leaf-digest multiset from which segment_root is computed.¶
segments/<segment-number>.cbor is authoritative. The
corresponding segments/<segment-number>.json file is a
projection only. The path label is the 20-digit, zero-padded decimal
rendering of the unsigned serial number; it is not a protocol field.
A verifier MUST compare the decoded segment_number with the
manifest claim rather than trusting the file name.¶
Segment identity and chaining are defined within one stable
ledger_id. They do not depend on UTC dates or elapsed idle
time.¶
segment_number equal to 0 and prev_segment_sha256 equal to 64 zero characters, representing 32 zero bytes.¶
ledger_id and site_id, and MUST set prev_segment_sha256 to SHA-256 over the predecessor's exact authoritative CBOR bytes.¶
segment_number. Before serial exhaustion, it MUST stop the ledger and start a new ledger with a new ledger_id.¶
segment_number or ledger_id.¶
When a new epoch begins, the producer MUST generate ledger_id from a
cryptographically strong random source. If durable sequence state
cannot be recovered unambiguously, a producer MUST stop acceptance or
begin a new ledger with a fresh identifier; it MUST NOT reset the
serial under the old identifier. Redundant gateways MUST use single-
writer fencing or an atomic shared allocator so that they cannot emit
different artifacts for the same
(ledger_id, segment_number).¶
A verifier given adjacent segment artifacts MUST validate serial continuity and predecessor-digest linkage. A partial disclosure that omits the predecessor can still support validation of the disclosed artifact and its external proof, but the verifier MUST report segment chain validation as skipped because the predecessor is unavailable.¶
Illustrative artifact layout:¶
records/<record-id>.cbor - authoritative canonical records¶
records/<record-id>.json - optional projections¶
segments/<segment-number>.cbor - authoritative canonical segment artifact¶
segments/<segment-number>.json - optional projection¶
segments/<segment-number>.verify.json - verifier-facing segment manifest¶
segments/<segment-number>.result.json - optional verifier-produced result¶
batches/<segment-number>-<batch-number>.batch.json - optional standalone batch-metadata projection of one batch object¶
segments/<segment-number>.cbor.sha256 - optional convenience digest¶
segments/<segment-number>.tsr - RFC 3161 timestamp response¶
segments/<segment-number>.cbor.ots - OTS proof¶
segments/<segment-number>.ots.meta.json - OTS binding metadata¶
Each disclosed records/<record-id>.cbor file contains the
exact canonical-record octets admitted at the boundary in
Section 4.1. A storage or bundle layer MUST
NOT add a wrapper to those file octets or replace them with a
re-encoding. File names are non-authoritative and are not leaf inputs.¶
Deployments MAY store artifacts differently and MAY export them as
bundles. The path shapes above are illustrative. In those shapes,
<segment-number> and <batch-number> are 20-digit,
zero-padded decimal renderings of their uint64 values.¶
Standalone batch metadata files are convenience projections of batch objects already carried in the authoritative segment artifact. They are not additional commitment inputs. Verifiers that process disclosed standalone batch-metadata projections MUST compare them with the corresponding batch object in the authoritative segment artifact and reject mismatches.¶
Every verification bundle that claims a disclosure class under this
document MUST disclose the authoritative segment artifact and the
producer-supplied manifest segments/<segment-number>.verify.json.
The artifact's in-band commitment_profile_id is the
cryptographically bound profile identifier. The manifest repeats the
ledger identity, segment number, commitment profile, claimed
disclosure class, artifact digests, and claimed channel state. It
MUST NOT contain checks_executed,
checks_skipped, or an overall verification outcome.¶
Each entry in artifacts.records represents one admitted
record occurrence. Duplicate entries are permitted and MUST be counted
separately. When two or more occurrences have identical canonical-
record bytes, their entries MAY reference the same disclosed artifact;
a Class A verifier MUST hash its exact octets once for each listed
occurrence. Artifact-reference order does not assert admission order.¶
A verifier MAY emit a separate
segments/<segment-number>.result.json. Only that
verifier-produced result states the checks actually executed or
skipped, the per-channel validation status, policy, and overall
outcome. A producer manifest and a verifier result MUST NOT be
represented as the same object.¶
Verifier-facing manifests MUST be portable. Artifact paths in the
manifest are UTF-8 strings interpreted relative to the disclosed
evidence bundle root, using / as the only separator. A path
MUST be non-empty; MUST NOT begin with /, \, or a
drive-letter prefix; MUST NOT contain \, a colon, a control
character in the ranges U+0000 through U+001F or U+007F, an empty path
component, or a component equal to . or ..; and after
resolution MUST remain below the bundle root. Verifiers MUST reject a
symbolic link, reparse point, or equivalent filesystem indirection, or
MUST use a containment-enforcing open operation that prevents such
indirection from changing the target between validation and access.
Path validation and file opening MUST be one race-resistant operation;
a check-then-open sequence that permits target substitution is
non-conformant. These checks are semantic requirements and do not depend
on a regular-expression dialect. Every artifact listed in the manifest
MUST carry a lowercase hexadecimal SHA-256 digest entry.¶
The verifier-facing metadata binds claim semantics to the stable
segment artifact. A bundle that discloses
segments/<segment-number>.cbor and a
timestamp proof can obtain the applicable
commitment_profile_id from the artifact itself. If a manifest
is also disclosed, its repeated identifier MUST match the in-band
value.¶
The verification manifest is the primary disclosure surface for verifier-visible producer claims. Its schema is defined in Appendix C. Deployment-specific data can be carried only in the explicit operational-summary or extension containers and MUST preserve the semantics defined here.¶
At minimum, an OTS sidecar MUST bind:¶
Verifiers MUST recompute the segment artifact digest and compare it with the sidecar before accepting any proof validation result.¶
The generic anchoring contract is simple: a gateway computes the SHA-256 digest of the authoritative segment artifact and submits that digest to one or more external timestamping channels. Verifiers MUST first recompute the segment artifact digest locally; proof validation occurs only after digest binding validation succeeds.¶
A timestamp or attestation over the segment-artifact digest binds the
complete artifact bytes, including the in-band
commitment_profile_id. It does not bind a disclosure class,
producer manifest, verifier policy, or checks exercised unless the
timestamped object separately includes those items.¶
A deployment conforming to this profile MUST use at least one timestamping channel for each emitted segment. Conforming producers and verifiers MUST implement the [RFC3161] channel defined below. Implementation support is mandatory, but a deployment MAY use OTS ([OTS]) instead of RFC 3161 for a particular emitted segment. Peer signatures are optional attestations and do not by themselves satisfy the timestamping-channel requirement. OTS and peer signatures are not baseline interoperable timestamp profiles.¶
time ------------------------------------------------------------>
Upstream |--record bytes-->| |--record bytes-->| |
Ledger | admit exact bytes | admit exact bytes |
|----- segment N open for configured elapsed interval ----|
| write segments/SEGMENT-N.cbor |
|---------- submit digest to OTS / RFC 3161 ------------->|
Channel | pending / delayed proof | upgrade |
Verifier | verify later from |
|<---------------- disclosed bundle --------------------->|
Figure 2 illustrates the current lifecycle. The upstream path can be intermittent, although it lies outside this profile. Proof completion or later publication can lag behind the authoritative segment-artifact write.¶
Conforming producers and verifiers MUST implement this channel. As specified in Section 6.1, a deployment is not required to use it for every segment.¶
When this channel is used, the producer MUST set
TimeStampReq.messageImprint.hashAlgorithm to SHA-256 and its
hashedMessage to the exact 32-octet result of SHA-256 over
the authoritative segment-artifact bytes. The producer MUST NOT hash
that 32-octet result again.¶
A deployment using this channel MUST define the accepted TSA trust anchors and any required TSA policy OIDs or other validation constraints.¶
A verifier evaluating disclosed RFC 3161 evidence MUST recompute the
segment-artifact digest and validate the TimeStampResp and time-stamp
token under [RFC3161]. Validation MUST include response
status, confirmation that TSTInfo.messageImprint uses SHA-256 and
contains the recomputed digest, the token signature, and the TSA
signer certificate and certification path under the configured trust
anchors and policy constraints. Successful validation MUST be
reported as tsa_verification.¶
When [OTS] is used, the gateway stamps
SHA-256(segments/<segment-number>.cbor) and stores an OTS
proof plus an OTS sidecar.¶
OpenTimestamps is referenced here as a deployed public timestamping
ecosystem rather than an IETF-standardized proof format.
Implementations claiming OTS support depend on the interoperable
behavior of the public OTS project, its calendar servers, and
compatible client tooling. OTS proof-format interoperability is
therefore defined operationally by that ecosystem and its reference
implementations. A verifier reports this deployment-specific check
using an extension identifier beginning with x-, for example
x-ots-verification; it MUST NOT report
tsa_verification for an OTS proof.¶
Calendar selection and multi-calendar availability guidance are described in Section 10.4.¶
If OTS submission fails, times out, or yields only an incomplete proof, the gateway MUST still write the authoritative segment artifact and MUST treat OTS as a separate channel whose state is not yet complete. Any later replacement or upgrade of the OTS proof MUST continue to bind to the same authoritative segment-artifact digest. Operator handling and verifier reporting for pending or absent proofs are described in Section 10.3, Section 10.4, and Section 10.5.¶
Verifier results SHOULD use the following status vocabulary for timestamp and optional parallel attestation channels:¶
verified: proof validation succeeded for the disclosed artifact binding.¶
pending: a proof exists but is incomplete or awaiting upgrade; this is not equivalent to invalid.¶
missing: the expected proof or channel artifact is absent.¶
failed: validation was attempted and did not succeed.¶
skipped: validation was not attempted because of disclosure class, verifier configuration, or local policy.¶
Whether missing, pending, or skipped
is verifier-fatal depends on the disclosure class, local verifier
policy, and whether the relevant channel is required.¶
Deployments MAY also produce:¶
This document does not define an interoperable peer-signature
validation profile. Peer-signature validation MUST be reported under
an extension identifier beginning with x-, for example
x-peer-quorum-verification. A future specification can
register interoperable peer-signature semantics.¶
When multiple channels are present, verifiers SHOULD validate all available channels independently and report per-channel results.¶
If a verifier is configured in strict mode for optional channels, failure of those channels MUST cause overall verification failure.¶
Verifiers MUST first decode the authoritative segment artifact and
determine the applicable commitment_profile_id from its
in-band field. The verifier MUST reject an absent or unsupported
value. When a verifier-facing manifest is disclosed, its repeated
value MUST exactly match the artifact field.¶
The verifier MUST treat commitment_profile_id as the semantic
key for interpreting the authoritative segment artifact. A structurally
well-formed segment artifact and a valid timestamp proof are insufficient
for semantic verification if the applicable
commitment_profile_id is absent or unsupported. A manifest
mismatch is a verification failure even when the artifact and
timestamp are otherwise valid.¶
Verifiers MUST determine the applicable verification scope from the disclosed artifacts, the claimed disclosure class, and local verifier policy. Reported outcomes MUST NOT claim checks or assurances outside that scope.¶
Producer manifests do not report executed or skipped checks. A verifier produces those lists only in its separate result after validating the disclosed artifacts.¶
Verifiers SHOULD apply checks in the following fail-fast order, subject to the claimed disclosure class:¶
bundle_disclosure_validation.¶
segment_artifact_validation and verification_manifest_validation as applicable.¶
prev_segment_sha256. Report segment_chain_validation as executed or, when the predecessor is unavailable, as skipped with reason predecessor_not_disclosed.¶
segment_root. Compare the recomputed result to the authoritative segment_root, and report record_level_recompute and batch_metadata_validation. Do not attempt to reconstruct a record from source telemetry.¶
record_level_recompute in checks_skipped. Deployment-specific withheld-material checks MAY be reported only through extension names beginning with x-.¶
record_level_recompute and batch_metadata_validation in checks_skipped as out of scope, and treat the result as anchor-only evidence.¶
SHA-256(segments/<segment-number>.cbor) and compare it with every applicable disclosed binding value: the manifest's artifacts.segment_cbor.sha256 value, an RFC 3161 messageImprint.hashedMessage, an OTS sidecar artifact_sha256, or deployment-specific peer-attestation binding metadata. A mismatch in any consumed binding is a verification failure. Report segment_digest_binding. If no binding value is disclosed, report the check as skipped with reason missing_binding_metadata; the bundle is then insufficient for any disclosure class defined here.¶
tsa_verification.¶
x- extension check identifiers.¶
When batch metadata is within the exercised verification scope, verifiers MUST apply the following checks before accepting a result:¶
count equals the length of its leaf_hashes;¶
ledger_id, site_id, and segment_number exactly;¶
batch_record_limit;¶
merkle_root equals the Merkle reduction of its leaf_hashes;¶
leaf_hashes equals the leaf digest multiset derived from disclosed canonical records when canonical-record artifacts are available; and¶
Verifier implementations SHOULD expose machine-usable failure categories:¶
commitment_profile_id,¶
Verifier output SHOULD state the claimed disclosure class, the verification scope actually exercised, the per-channel proof status, which checks were executed, which checks were skipped, and whether the resulting claim is public recompute, partial verification, or anchor-only evidence.¶
Standardized Check Identifiers¶
When verifier results report
checks_executed or checks_skipped, this profile
defines the following interoperable check identifiers:¶
bundle_disclosure_validation: disclosure-class sufficiency was validated.¶
verification_manifest_validation: the verifier-facing manifest was validated.¶
segment_artifact_validation: the authoritative segment artifact was validated structurally and semantically under the claimed profile.¶
segment_chain_validation: epoch-segment state or adjacent segment serial, identity, and predecessor-artifact digest linkage were validated.¶
record_level_recompute: record-level recomputation from disclosed canonical-record artifacts was performed.¶
batch_metadata_validation: authoritative or disclosed batch metadata was validated against the segment artifact and disclosed record material within scope.¶
segment_digest_binding: the recomputed SHA-256(segments/<segment-number>.cbor) digest was compared with disclosed binding metadata.¶
tsa_verification: the [RFC3161] timestamp channel was validated.¶
A verifier result that reports one of these standardized
checks MUST use the exact identifier listed here. For any
standardized check whose applicability conditions are met within the
exercised verification scope, the verifier result MUST
report that check exactly once in either checks_executed or
checks_skipped. The same standardized identifier MUST NOT
appear in both lists and MUST NOT appear more than once. Silent
omission of an applicable standardized check is non-conformant.¶
Applicability is determined as follows:¶
bundle_disclosure_validation and segment_artifact_validation apply whenever verification proceeds on a disclosed bundle.¶
verification_manifest_validation applies when a verifier-facing manifest is disclosed or consumed to obtain verifier-visible metadata.¶
segment_chain_validation applies to every disclosed segment. For an epoch segment it validates the zero predecessor and serial zero. For a non-epoch segment, it MUST be executed when the predecessor is disclosed and otherwise MUST be reported as skipped.¶
record_level_recompute, batch_metadata_validation, and segment_digest_binding apply. If required artifacts for one of these checks are absent, that check MUST appear in checks_skipped with a reason indicating insufficient disclosure or missing artifacts.¶
batch_metadata_validation and segment_digest_binding apply when the corresponding artifacts are disclosed. If withheld material prevents public recomputation, record_level_recompute MUST appear in checks_skipped.¶
record_level_recompute and batch_metadata_validation MUST appear in checks_skipped as out of scope, while segment_digest_binding applies when the segment artifact and binding metadata are disclosed.¶
tsa_verification applies when the RFC 3161 channel is disclosed or required by verifier policy. Other channels use x- extension identifiers.¶
Additional deployment-specific checks MAY be reported, but they MUST
NOT redefine these identifiers and MUST use a distinct extension
name beginning with x-.¶
Verifier output MUST NOT be represented as proving more than the exercised verification scope. In particular, a successful result does not by itself establish dataset completeness, physical truth of measurements, or suitability for autonomous actuation or sanctions.¶
Verification claims depend on what artifacts are disclosed. This profile defines three disclosure classes.¶
Disclosure classes are verifier behavior, not prose intent. A verifier MUST decide each class from the artifacts it can recompute, the artifacts it cannot recompute, and the checks it reports as executed or skipped. A verifier claim for any disclosure class MUST be limited to the verification scope supported by the disclosed artifacts and MUST NOT be represented as proving dataset completeness, physical truth of measurements, omitted device lifecycle state, omitted external channels, or suitability for autonomous actuation or sanctions.¶
Class A (Public Recompute)¶
Class A is appropriate when public recomputation from disclosed
canonical records and authoritative artifacts is required. A Class A
bundle MUST include all canonical-record artifacts required to
recompute the claimed segment root, the canonical segment artifact including
its authoritative batch objects, any disclosed standalone
batch-metadata projections, the verifier-facing segment manifest, and
at least one proof artifact plus its binding metadata. The segment
artifact itself records the
commitment_profile_id.¶
A Class A verifier can perform record-level recomputation, batch-metadata validation, segment-root recomputation, segment-artifact digest validation, manifest artifact-digest validation, and enabled anchor or publication-proof validation when the corresponding artifacts are disclosed. It MUST report recomputation, profile, and manifest status. A public-recompute claim is invalid if required record artifacts are missing, root recomputation was skipped, the in-band profile is absent or unsupported, or digest checks fail.¶
Class B (Partner Audit)¶
Class B is appropriate for controlled disclosure where some record material is withheld while commitment and anchor evidence remain auditable. Class B outputs MUST NOT be represented as publicly recomputable. A Class B bundle MUST include the canonical segment artifact, the verifier-facing segment manifest, and at least one timestamp proof plus binding metadata. It MAY include standalone batch-metadata projections, commitments covering withheld material, and a policy artifact describing withheld or partitioned material.¶
Class B validation is limited to the authoritative segment artifact,
disclosed batch metadata, any disclosed withheld-material commitments,
any auditor-supplied material, and any anchor channels present in the
bundle. Verifier output SHOULD explicitly state when record-level
recomputation was partial or was not attempted for withheld material.
It MUST report record_level_recompute as skipped when public
record-level recomputation is impossible and MUST report that the
result is not publicly recomputable. Deployment-specific checks for
withheld-material commitments or policy artifacts MUST use extension
names beginning with x-.¶
Class C (Anchor-Only)¶
Class C is appropriate when only existence and timestamp evidence is
disclosed. A Class C disclosure MUST be labeled as existence and
timestamp evidence only and MUST NOT claim record-level
reproducibility. A Class C bundle MUST include the canonical segment
artifact, the verifier-facing segment manifest, and at least one
timestamp proof artifact plus the metadata needed to bind it to the
segment artifact digest. The in-band
commitment_profile_id supplies the profile identity.¶
A Class C verifier can validate segment-artifact digest binding, manifest
digests, chain or anchor existence, and timestamp or publication status
when the relevant artifacts are present. Class C verifier output SHOULD
be reported as anchor-only evidence. It MUST report record-level and
batch recomputation as skipped. It MUST NOT report
segment_chain_validation as executed for a non-epoch segment
unless the predecessor artifact is disclosed.¶
The verifier-facing manifest MUST include:¶
ledger_id and segment_number,¶
disclosure_class,¶
commitment_profile_id,¶
A separate verifier result MUST identify the artifact digest and commitment profile it evaluated, the claimed disclosure class, checks executed, checks skipped with reasons, per-channel validation results, verifier policy, and overall outcome.¶
This profile has several independent version surfaces:¶
-00, -01) is editorial and is not part of commitment output.¶
version fields in segment, batch, verification-manifest, and verifier-result records.¶
commitment_profile_id identifies the canonical CBOR, hash, and Merkle rules that define commitment outputs.¶
The commitment profile defined in this document is
verifiable-telemetry-canonical-cbor-v2. If a verifier encounters an unsupported
commitment_profile_id, it MUST reject the verification claim
rather than silently using a fallback interpretation.¶
This revision defines exactly one non-private
commitment_profile_id. Additional non-private profile
identifiers are allocated as described in
Section 13.3 and require a stable public
specification before they are used for interoperability claims.¶
The move from calendar-day artifacts to serial-numbered segments is a
commitment-format migration, not an editorial alias. It changes the
authoritative artifact family, schema bytes, paths, chain input, and
verifier semantics. Therefore this revision uses segment and batch
schema version 2, verification-manifest version 2,
the new media type in Section 13.1, and
verifiable-telemetry-canonical-cbor-v2. A producer MUST NOT
label v2 bytes with the v1 identifier. Migration from a v1 day ledger
starts a fresh v2 ledger_id at segment zero; any cross-profile
migration statement requires a separately specified artifact and is
not a normal prev_segment_sha256 link.¶
The fixed canonical-record array retains its in-band record
discriminator value 1. The v2 profile uses domain-separated
leaf and parent hashes, the uniquely determined recursive tree shape
in Section 4.3, and deterministic batch
partitioning. Its roots are therefore not interchangeable with roots
produced by the legacy duplicate-last construction.¶
The authoritative segment artifact carries the applicable
commitment_profile_id in-band. A verifier-facing manifest
repeats it and MUST match the artifact. Timestamping the artifact
digest therefore binds the profile identifier without relying on an
unprotected manifest association.¶
A segment-record version identifies the schema of the segment artifact
under a known commitment profile. It is not a substitute for
commitment_profile_id. Likewise, a media type or file extension
can identify the artifact family, but it does not authorize a verifier
to select canonical CBOR, hash, or Merkle rules without an explicit
commitment profile.¶
The following migration rules apply to the public contract surfaces:¶
commitment_profile_id
A change can trigger more than one action. For example, a new
publication statement that also changes commitment bytes requires both
a new artifact family and a new commitment_profile_id.¶
The deterministic rules in this profile can be exercised with machine-readable conformance vectors. Vector suites SHOULD cover the positive and negative cases below.¶
Positive coverage should include:¶
Negative coverage should include:¶
device_time, or ingest_time,¶
segment_root instead of the authoritative segment-artifact digest, and¶
segment_chain_validation as executed without the required predecessor.¶
Cross-implementation checks SHOULD verify byte-for-byte parity across at least two independent implementations. Interval tests MUST use a controllable fake elapsed-time source and restart tests MUST inject failures at persistence boundaries; conformance tests SHOULD NOT wait for real elapsed time. The canonical-record bytes are test inputs, not outputs reconstructed from transport fixtures. Any mismatch in leaf digests, artifact bytes, artifact digests, roots, assignments, or expected failures is a conformance failure.¶
Vector bundles SHOULD include the
commitment_profile_id.¶
This section consolidates deployment guidance for operators and follows the operational topics described in [I-D.ietf-opsawg-rfc5706bis]. It does not make operator policy part of the cryptographic commitment output, but it identifies the state and configuration that determine whether the committed evidence remains useful and verifiable.¶
Any ingest_time or device_time value is already part
of the canonical-record byte string at the profile boundary. Its
assignment, source authentication, accuracy, leap-second handling,
and clock-health policy are upstream responsibilities. The ledger
producer MUST preserve that value unchanged and MUST NOT use it for
segment selection, renumbering, or reopening. Segment closure uses
only the elapsed-time rules in Section 10.2.¶
Operators MUST persist the active ledger_id, next emitted
segment number, current closure-policy snapshot, open-interval state,
record and byte counters, and artifact-write state across restart.
Admission, artifact publication, and sequence-state advancement MUST
use the atomic or recoverable protocol in
Section 4.4 so a crash cannot lose an accepted
record or reuse a published serial. Redundant
gateways MUST use single-writer fencing or atomic shared allocation.¶
Operators SHOULD monitor elapsed-timer health, closure delay, unexpected early-close reasons, serial conflicts, policy changes, and recovery closures. If deadline state cannot be recovered, the gateway MUST follow Section 4.4 rather than consulting UTC to reconstruct elapsed boundaries.¶
Operators SHOULD monitor at least the following signals:¶
An operator-visible fault state SHOULD distinguish an invalid commitment artifact from a delayed or failed external anchoring channel. A delayed OTS proof, for example, is not by itself evidence that the authoritative segment artifact is malformed.¶
Deployments SHOULD document the maximum canonical-record byte length,
admission backpressure and durable-write behavior,
closure_policy, record and size limits, permitted early-close
triggers, artifact and proof retention periods, OTS calendars,
optional TSA identities, anchoring policy, verifier strictness for
optional channels, and any peer-signature quorum threshold and
identity set. These settings are distinct and MUST NOT be silently
substituted for one another.¶
Transport, decryption, anti-replay, source buffering, source identity, and source-to-record mapping configuration are upstream of this profile. When one implementation contains both upstream and ledger functions, operator documentation SHOULD still identify the byte-level handoff and distinguish upstream failures from ledger admission or commitment failures. A configuration change that alters the canonical-record byte syntax or another commitment output requires the versioning action specified in Section 8.¶
When OTS is used, ledger producers SHOULD submit to multiple calendars operated by administratively distinct entities and retain disclosed OTS proof artifacts for at least as long as the corresponding segment artifacts remain available for verification.¶
Operational faults do not all have the same verifier meaning. Verifier output MUST distinguish at least the following cases when the condition is visible from disclosed artifacts or local verifier policy:¶
pending. Place
x-ots-verification in checks_skipped with reason
pending_proof unless validation was attempted and failed.
Overall success is permitted only when local policy does not
require completed OTS evidence.¶
missing when required by
policy, or skipped with reason disabled when the
channel is not configured. Report tsa_verification exactly
once in either executed or skipped checks when applicable.¶
segment_chain_validation as successful across an unknown
predecessor, serial conflict, or newly created ledger.¶
Artifact size grows primarily with the number of accepted canonical records and the number of batches in a segment. Class A verification requires access to the disclosed canonical-record artifacts and scales with the number of records that must be decoded, hashed, and reduced into the segment root. Class C verification can be substantially smaller because it validates the segment-artifact digest and disclosed proof channels without public record-level recomputation. OTS submission traffic is one digest submission per emitted segment artifact per selected calendar; using multiple calendars increases availability but also increases submission attempts and proof-status tracking.¶
Shorter segment intervals reduce the normal time to sealing and
anchoring but increase artifact count, anchor submissions, storage,
verifier work, and cadence metadata leakage. Longer intervals reduce
that overhead but increase the amount of unsealed material and the
size of each record-level verification. In emit mode, idle
deployments also pay one artifact and anchor submission per interval;
suppress mode avoids that cost but makes no continuous-
coverage claim.¶
Operators SHOULD periodically run an independent verifier against a
recently produced bundle using the same disclosure class that consumers
are expected to rely on. A healthy run should confirm that disclosed
artifacts are present, the commitment_profile_id is supported,
the authoritative segment artifact is well formed, the segment-artifact digest
matches binding metadata, disclosed adjacency passes segment-chain
validation, expected checks appear exactly once in either
checks_executed or checks_skipped, and configured
proof channels report a status permitted by local policy and
reported according to Section 10.5. Operators SHOULD
alert when required checks are silently absent, when OTS proofs remain
pending beyond local policy, or when canonical-record handoff,
elapsed-timer health, serial allocation, writer fencing, or segment-
artifact-write faults occur.¶
This profile does not introduce new cryptographic primitives. Its security depends on a byte-preserving canonical-record handoff, deterministic commitment encoding, trustworthy ledger admission and elapsed-time handling, accurate verifier reporting, and disciplined artifact and proof handling. The threats below are stated in the threat-and- remediation style described by [RFC3552]. Unless explicitly stated otherwise, a successful verification result establishes only that the disclosed artifacts are internally consistent with this profile and with any validated proof channels.¶
Gateway Compromise and Pre-Commit Omission¶
An attacker can compromise the ledger producer or its canonical-record handoff and then fabricate byte strings, suppress proposed inputs before commitment, substitute different bytes, or assign a record to the wrong segment. This profile does not by itself detect a malicious producer; it makes outputs tamper-evident only after commitment, as described in Section 1.2. Operational guidance for admission persistence, elapsed time, health, and verification checks is consolidated in Section 10.¶
Segment Sequence Rollback, Fork, and Truncation¶
An attacker or failed multi-writer deployment can reuse or roll back a segment number, emit conflicting artifacts for one ledger and serial, substitute a predecessor from another ledger, or disclose only a chain prefix or suffix. Fresh ledger identity, single-writer fencing, contiguous serials, and full predecessor-artifact digest validation detect conflicts when the relevant artifacts are disclosed. They do not prove global completeness to an isolated verifier: a producer can still withhold undisclosed segments or a chain suffix. Verifier output MUST therefore distinguish validated adjacency from a completeness claim.¶
Upstream Admission and Semantic Substitution¶
An attacker can exploit an upstream transport, replay mechanism, credential system, decryption path, identifier mapping, or payload parser so that incorrect, duplicated, or misattributed record bytes are presented at the profile boundary. Those controls are outside this document. This profile neither prevents nor detects such an attack once the resulting byte string has been admitted. A separate upstream specification is needed for claims about source authentication, anti-replay, confidentiality, or source-to-record semantics, and a successful ledger verification MUST NOT be reported as validation of those claims.¶
Canonicalization, Profile, and Metadata Confusion¶
An attacker can exploit differences in CBOR validation, re-encoding,
record occurrence handling, hash composition, or non-authoritative
metadata handling while implementations still claim the same
commitment_profile_id. An attacker can also present a
verifier-facing manifest, batch-metadata projection, or OTS sidecar
that does not match the authoritative segment artifact in the hope that a
verifier will treat convenience metadata as authoritative. The
mitigation is that this profile fixes the canonical-record byte syntax,
deterministic encoding, and hash rules; requires producers and
verifiers to hash the exact authoritative record bytes without
re-encoding; treats the authoritative segment artifact as the
cryptographic source of truth; requires verifiers to recompute
commitment material from authoritative artifacts; requires the applicable
commitment_profile_id to be disclosed and bound to the same
segment-artifact digest, and requires standalone metadata projections and
sidecars to match the authoritative artifact. Any future semantic or
hash-composition change MUST use a new
commitment_profile_id.¶
Artifact Mutation and Proof Substitution¶
An attacker can modify a committed segment artifact after disclosure, or can present a valid proof over the wrong artifact digest. The mitigation is that verifiers recompute the authoritative segment-artifact digest independently and compare it with the disclosed binding metadata before accepting any proof result. Mutation or substitution therefore changes the digest or its binding and causes verification to fail.¶
Calendar Withholding and Optional-Channel Downgrade¶
An attacker can operate or compromise a timestamping or attestation service so that proof issuance is delayed, withheld, or selectively unavailable, can present pending or placeholder proofs as if they were final attestations, or can exploit verifier policy that silently ignores a missing required channel. The channel-status vocabulary is defined in Section 6.3.3, and operational reporting for missing or pending channels is described in Section 10.5.¶
UTC Timestamp Manipulation¶
An attacker can alter an upstream UTC source so that canonical records
carry misleading ingest_time or device_time values.
Timestamp assignment and source authentication are outside this
profile, as described in Section 10.1. Verification can
detect byte or artifact inconsistencies, but it cannot reconstruct true
real-world time from a false admitted value. UTC changes MUST NOT affect
segment membership or reopen sealed segments.¶
Segment Policy and Elapsed-Time Manipulation¶
An attacker can lengthen the closure interval, regress or freeze the elapsed-time source, alter an active policy, misstate a close reason, or race boundary processing in order to delay anchoring or assign a record to a different segment. Committing the policy snapshot and close reason makes the gateway's claim tamper-evident after sealing, while the serialized boundary algorithm and operational monitoring reduce accidental races. These controls do not independently prove that the gateway honestly observed real elapsed time. Likewise, a validated OTS proof establishes that the artifact existed no later than the validated timestamp; it does not prove when the segment opened or that every configured deadline was honored.¶
Resource Exhaustion¶
An attacker can flood a ledger producer with malformed, oversized, or excessive-rate canonical-record inputs in order to exhaust admission capacity, artifact storage, or verifier computation. Producers need deployment-appropriate input-size limits, rate controls, and backpressure at the byte-level handoff; relevant operational signals and sizing considerations are described in Section 10.3 and Section 10.6. This profile does not define a complete denial-of-service defense.¶
Verification Scope, Completeness, and Disclosure¶
An attacker can rely on a successful verification result being misread as proof of dataset completeness, physical truth of measurements, or authorization for autonomous actuation. An attacker can also obtain sensitive information if disclosed bundles expose more record material than intended for the chosen disclosure class. This profile mitigates those risks only partially: verifier output is required to state the exercised verification scope, a successful result establishes internal consistency and proof binding for the disclosed bundle rather than completeness of all observed or emitted telemetry, and disclosure classes constrain what is expected to be published. Deployments that need stronger completeness, safety, or confidentiality guarantees must add external operational controls, independent observation, and access-control and retention policies that match the sensitivity of the disclosed artifacts.¶
Even when payloads are withheld, manifests, segment artifacts, proof sidecars, and operational summaries can disclose source-activity metadata such as record counts, outage windows, and anchoring delay. Segment serials, interval values, close reasons, and the difference between emitted and suppressed empty intervals can add cadence and activity information. Deployments SHOULD account for that metadata exposure in disclosure and retention policy.¶
Telemetry payloads can include sensitive operational data. Operators should:¶
Privacy-preserving disclosures remain valid, but they MUST NOT be described as publicly recomputable unless Class A conditions are met.¶
Disclosure of verifier-facing manifests, canonical-record artifacts,
segment artifacts, proof sidecars, and operational summaries can reveal
source-activity patterns, outage windows, configured segment duration, empty-interval policy,
anchoring cadence, and operational incidents even when payload values
are withheld. Short intervals and suppress mode can make
activity timing especially visible. Operators SHOULD treat these
artifacts as metadata-bearing evidence and apply disclosure, retention,
and access-control policy accordingly.¶
This section follows the guidance in [RFC8126] and provides the complete instructions for the Internet Assigned Numbers Authority (IANA).¶
IANA is requested to register the following media types in the standards tree of the "Media Types" registry in accordance with [RFC6838]:¶
Because this document is intended for publication on the Independent Submission Stream, the standards-tree registrations in this section require IESG approval under [RFC6838].¶
Type name: application¶
Subtype name: verifiable-telemetry-segment+cbor¶
Required parameters: none¶
Optional parameters: none¶
Encoding considerations: binary¶
Security considerations: see Section 11, especially profile and metadata confusion, artifact mutation, proof substitution, disclosure scope, and resource exhaustion.¶
Interoperability considerations: this media type identifies the
authoritative segment-artifact family defined by
Section 4.2, Section 4.3,
Section 4.4,
Section 4.5, and
Section 4.6. A recipient uses the artifact's
in-band commitment_profile_id to select canonical CBOR, hash,
and Merkle semantics for a verification claim.¶
Published specification: this document, especially Section 4.2, Section 4.3, Section 4.4, Section 4.5, and Section 4.6.¶
Applications that use this media type: producers, verifiers, disclosure tools, and archival or audit systems that exchange or retain authoritative segment artifacts.¶
Fragment identifier considerations: no fragment identifier syntax is
defined by this document for
application/verifiable-telemetry-segment+cbor.
Fragment identifiers, if present, are processed according to the
+cbor structured syntax suffix rules in
[RFC8949].¶
Additional information:¶
Person & email address to contact for further information: Bilal El Khatabi <elkhatabibilal@gmail.com>¶
Intended usage: COMMON¶
Restrictions on usage: none¶
Author: Bilal El Khatabi¶
Change controller: IESG¶
Type name: application¶
Subtype name: verifiable-telemetry-manifest+json¶
Required parameters: none¶
Optional parameters: none¶
Encoding considerations: binary¶
Security considerations: see Section 11, especially profile and metadata confusion, artifact mutation, stale or substituted manifests, disclosure scope, and resource exhaustion.¶
Interoperability considerations: this media type identifies the
verification manifest defined by Section 5,
Section 6.5, and Verification Manifest and Result CDDL. The
manifest is a metadata and digest-binding surface;
it is not an authoritative commitment artifact. A recipient still
needs the referenced authoritative artifact and MUST compare the
manifest's commitment_profile_id with the artifact's in-band
value to interpret and verify a claim. The JSON representation
conforms to [RFC8259].¶
Published specification: this document, especially Section 5, Section 6.5, and Verification Manifest and Result CDDL.¶
Applications that use this media type: producers, verifiers, disclosure tools, publication services, and archival or audit systems that exchange verification manifests.¶
Fragment identifier considerations: no fragment identifier syntax is
defined by this document for
application/verifiable-telemetry-manifest+json.¶
Additional information:¶
Person & email address to contact for further information: Bilal El Khatabi <elkhatabibilal@gmail.com>¶
Intended usage: COMMON¶
Restrictions on usage: none¶
Author: Bilal El Khatabi¶
Change controller: IESG¶
This document requests no new CBOR tag allocation. Commitment bytes defined by Section 4.2 forbid CBOR tags, and the authoritative segment artifact defined by Section 4.5 does not require additional tag semantics for exchange.¶
IANA is requested to create the Verifiable Telemetry Ledger
Commitment Profiles registry under a new Verifiable Telemetry Ledger
Parameters registry group. This registry is tied to the
application/verifiable-telemetry-segment+cbor media type
registered in Section 13.1 and records values of
the commitment_profile_id sub-code carried in that
representation. Registry change control belongs to the Independent
Stream. The registry records four columns:
Identifier, Description, Reference, and
Change Controller.¶
A registered identifier is 1 through 63 lower-case ASCII characters.
It begins with a letter, ends with a letter or digit, and otherwise
contains only lower-case letters, digits, and single hyphens between
non-hyphen characters. Comparison is case-sensitive; an identifier
containing an upper-case letter is invalid. Identifiers beginning
with x- are reserved for Private Use, are not registered,
and MUST NOT be used as interoperable public profile identifiers.¶
The registration policy is RFC Required as defined by [RFC8126] and constrained by [RFC8726] for the Independent Submission Stream.¶
A registration request MUST provide all four registry fields and an RFC reference. The referenced RFC MUST define the canonical input bytes, deterministic encoding rules, hash and tree calculation, authoritative artifact schema, verification procedure, profile identifier binding, positive and negative conformance vectors, and relevant security considerations. An identifier that does not satisfy the syntax above is invalid and MUST NOT be registered.¶
An update request requires authorization from the registered change controller and an RFC reference. An update MUST NOT change commitment bytes or verification semantics for an existing identifier; such a change requires a new identifier. A deprecated entry remains recorded with its reference and MUST NOT be reassigned.¶
This registry is created by a document published on the Independent Submission Stream. Any issues that arise with management of the registry will be resolved by IANA in consultation with the Independent Submissions Editor.¶
| Identifier | Description | Reference | Change Controller |
|---|---|---|---|
| verifiable-telemetry-canonical-cbor-v2 | Deterministic CBOR canonical-record and serial-segment profile with domain-separated SHA-256 tree commitments | This document | Independent Stream |
This document requests no CoAP Content-Format entry.¶
This profile standardizes the durable evidence object produced after local telemetry admission and before external publication. It is useful where the source protocol and application semantics vary, but later auditors need a common way to recompute exactly what bytes were committed, how they were grouped, and which timestamped artifact binds them.¶
This profile is not appropriate when an application needs proof of sensor truth, source authentication, complete upstream ingestion, or the semantics of source-to-record projection; those properties require upstream specifications and evidence. It also does not replace SCITT or another publication system: such a system can publish a VTL artifact, while this document defines how the local artifact is formed and verified.¶
The following items are outside the baseline profile defined by this document. They identify extension surfaces that would require separate specification before they are used as interoperability claims.¶
commitment_profile_id.¶
This appendix shows a representative verification manifest. A concrete deployment can carry additional operational fields in the defined extension containers; the example below captures the baseline verification surface described here. Operational summaries can be carried as deployment-specific extensions, but they are not substitutes for canonical-record or segment-artifact authority and are not required by the disclosure classes.¶
{
"version": 2,
"ledger_id": "b7a1d5e40c6f438e9a75db27c96f31aa",
"site_id": "an-001",
"segment_number": "7",
"commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
"disclosure_class": "A",
"artifacts": {
"segment_cbor": {
"path": "segments/00000000000000000007.cbor",
"sha256": "<64 hex chars>"
},
"predecessor_segment_cbor": {
"path": "segments/00000000000000000006.cbor",
"sha256": "<64 hex chars>"
},
"records": [
{
"path": "records/device-003-00000006.cbor",
"sha256": "<64 hex chars>"
},
{
"path": "records/device-003-00000007.cbor",
"sha256": "<64 hex chars>"
}
],
"segment_json": {
"path": "segments/00000000000000000007.json",
"sha256": "<64 hex chars>"
},
"segment_sha256": {
"path": "segments/00000000000000000007.cbor.sha256",
"sha256": "<64 hex chars>"
},
"tsa_tsr": {
"path": "segments/00000000000000000007.tsr",
"sha256": "<64 hex chars>"
},
"segment_ots": {
"path": "segments/00000000000000000007.cbor.ots",
"sha256": "<64 hex chars>"
},
"segment_ots_meta": {
"path": "segments/00000000000000000007.ots.meta.json",
"sha256": "<64 hex chars>"
}
},
"anchoring": {
"tsa": { "status": "complete" },
"ots": { "status": "complete" },
"peer": { "status": "skipped" }
}
}
¶
A verifier result is a separate object. For example:¶
{
"version": 2,
"artifact_sha256": "<64 hex chars>",
"commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
"disclosure_class": "A",
"verification_scope": "public_recompute",
"checks_executed": [
"bundle_disclosure_validation",
"verification_manifest_validation",
"segment_artifact_validation",
"segment_chain_validation",
"record_level_recompute",
"batch_metadata_validation",
"segment_digest_binding",
"tsa_verification"
],
"checks_skipped": [],
"channels": {
"tsa": { "status": "verified" },
"ots": { "status": "verified", "check": "x-ots-verification" }
},
"policy": { "optional_channel_failure": "warn" },
"record_multiset_root": "<64 hex chars>",
"overall": "success"
}
¶
The figure below is a reader-oriented sketch of the
verifiable-telemetry-canonical-cbor-v2 conformance-vector bundle shape and
naming only. It is illustrative and is not itself a complete
machine-readable vector corpus.¶
The exact compact known-answer vector later in this appendix is
normative for verifiable-telemetry-canonical-cbor-v2. The
surrounding reader-oriented sketches remain illustrative.¶
Wrapped hexadecimal values in this appendix are presentation-only; a verifier or implementer should concatenate adjacent lines without inserting whitespace.¶
The fixtures below are reader-oriented decoded views, not upstream transport or projection fixtures. A machine-readable vector corpus for this profile MUST carry the exact canonical-record byte strings as its starting inputs together with their expected leaf digests.¶
In these reader-oriented sketches, kind is shown as the
unsigned value carried in the authoritative CBOR array. Its application
meaning is outside this profile.¶
commitment_profile_id: verifiable-telemetry-canonical-cbor-v2 fixture record_a: device_id: "0000000000000065" fc: 1 ingest_time: 1772366400 device_time: null kind: 250 payload.temp_c: 21.5 fixture record_b: device_id: "0000000000000066" fc: 2 ingest_time: 1772367000 device_time: null kind: 250 payload.temp_c: 22.0 fixture record_c: device_id: "0000000000000067" fc: 3 ingest_time: 1772367600 device_time: null kind: 250 payload.temp_c: 22.5 segment_record_v2: version: 2 commitment_profile_id: verifiable-telemetry-canonical-cbor-v2 ledger_id: b7a1d5e40c6f438e9a75db27c96f31aa site_id: an-001 segment_number: 7 closure_policy.version: 1 closure_policy.interval_ms: 86400000 closure_policy.batch_record_limit: 1024 closure_policy.record_limit: null closure_policy.size_limit_bytes: null closure_policy.empty_mode: suppress close_reason: interval prev_segment_sha256: <SHA-256 of exact segment 6 CBOR> batches: <ordered batch objects> segment_root: <root over the segment leaf multiset> class-a-bundle-v2: disclosure_class: A commitment_profile_id: verifiable-telemetry-canonical-cbor-v2 required_artifact_1: records/<record-id>.cbor required_artifact_2: segments/<segment-number>.cbor required_artifact_3: segments/<segment-number>.tsr verifier_check_1: bundle_disclosure_validation verifier_check_2: segment_artifact_validation verifier_check_3: segment_chain_validation verifier_check_4: record_level_recompute verifier_check_5: batch_metadata_validation verifier_check_6: segment_digest_binding verifier_check_7: tsa_verification required_fail_cases: - serial reuse, decrease, gap, or wrap - wrong predecessor artifact digest or ledger identity - record accepted exactly at deadline assigned to old interval - timestamp-driven reassignment or reopening of sealed segment - in-place closure-policy mutation - invalid empty-mode behavior - batch identity, number, count, ordering, or root mismatch - batch partition does not follow batch_record_limit - manifest profile identifier differs from the in-band artifact value - proof covers segment_root instead of segment artifact digest
The following compact known-answer vector is normative for
verifiable-telemetry-canonical-cbor-v2. Hexadecimal values are
lowercase and unprefixed. It encodes the epoch segment: the outer
segment and both embedded batches use segment_number = 0, and
prev_segment_sha256 is 32 zero octets. The segment uses
batch_record_limit = 2.¶
record_1 = 87014800000000000000010100f600f6 leaf_1 = b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26 record_2 = 87014800000000000000020201f600f6 leaf_2 = b5227357cf5d0619914971d8dc5218c5a99260bc5d5e1b60cb1083a911a2acaf record_3 = 87014800000000000000030302f600f6 leaf_3 = 4f82e3e7ee90a111774dd951471a31d4582e0908a0bd5fd63c0080c0231f40cc sorted_leaves = 4f82e3e7ee90a111774dd951471a31d4582e0908a0bd5fd63c0080c0231f40cc b5227357cf5d0619914971d8dc5218c5a99260bc5d5e1b60cb1083a911a2acaf b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26 batch_0_root = 554491e4edf28061622396b83a870db4652211557127c664c6be1c4ad66471ff batch_1_root = b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26 segment_root = bc6502552ed0c515f58d1c632e54db37594042609b59838eb0d5b3d5842aa054 segment_cbor = aa676261746368657382a865636f756e740267736974655f696466616e2d303031 6776657273696f6e02696c65646765725f69647820623761316435653430633666 34333865396137356462323763393666333161616b6c6561665f68617368657382 784034663832653365376565393061313131373734646439353134373161333164 343538326530393038613062643566643633633030383063303233316634306363 784062353232373335376366356430363139393134393731643864633532313863 356139393236306263356435653162363063623130383361393131613261636166 6b6d65726b6c655f726f6f74784035353434393165346564663238303631363232 333936623833613837306462343635323231313535373132376336363463366265 3163346164363634373166666c62617463685f6e756d626572006e7365676d65 6e745f6e756d62657200a865636f756e740167736974655f696466616e2d3030 316776657273696f6e02696c65646765725f696478206237613164356534306336 6634333865396137356462323763393666333161616b6c6561665f686173686573 817840623833626332376632643862653361363633373361663234653661663365 656666666639396666303639366165313863373065333739653835333739366432 366b6d65726b6c655f726f6f747840623833626332376632643862653361363633 373361663234653661663365656666666639396666303639366165313863373065 333739653835333739366432366c62617463685f6e756d626572016e7365676d 656e745f6e756d6265720067736974655f696466616e2d303031677665727369 6f6e02696c65646765725f696478206237613164356534306336663433386539 6137356462323763393666333161616c636c6f73655f726561736f6e68696e74 657276616c6c7365676d656e745f726f6f747840626336353032353532656430 633531356635386431633633326535346462333735393430343236303962353938 333865623064356233643538343261613035346e636c6f737572655f706f6c69 6379a66776657273696f6e016a656d7074795f6d6f6465687375707072657373 6b696e74657276616c5f6d731a05265c006c7265636f72645f6c696d6974f670 73697a655f6c696d69745f6279746573f67262617463685f7265636f72645f6c 696d6974026e7365676d656e745f6e756d6265720073707265765f7365676d65 6e745f73686132353678403030303030303030303030303030303030303030303030 30303030303030303030303030303030303030303030303030303030303030303030 3030303030303075636f6d6d69746d656e745f70726f66696c655f69647826766572 69666961626c652d74656c656d657472792d63616e6f6e6963616c2d63626f722d76 32 segment_sha256 = ce76302d1fcbf713097c0d70070b6a651bcd97e7855213aaf422b0ff9226708c three_identical_record_1_root = 05ddc48e556d67534bf7960a70209696ca9eeb6f18d5595358e7f4804ec87701 four_identical_record_1_root = d5d26faa3f54d81d8173700a48d9286179c9d35685d464183a99b1e966f1dfd8¶
A published machine-readable vector set can carry exact canonical
bytes, digests, expected roots, and the applicable
commitment_profile_id. The reader-oriented sketches in this
appendix are illustrative; the exact compact known-answer vector above
is normative.¶
This appendix defines the Concise Data Definition Language (CDDL) ([RFC8610]) shape for the verification producer manifest and the separate verifier result. It captures the verification surface described here and provides explicit containers for deployment-specific additions. Producer manifests and verifier results MUST be UTF-8 JSON texts under [RFC8259] and MUST reject duplicate object member names.¶
Check names are drawn from the standardized vocabulary defined in
Section 6.5; deployment-specific extensions MUST use
separate names beginning with x- that do not redefine those
identifiers.¶
The relative-path rule below is intentionally structural. RFC
8610 regular expressions use the XML Schema dialect and cannot
portably express all cross-platform path and filesystem-containment
checks. Implementations MUST apply the semantic path rules in
Section 5, including backslash, drive-prefix, UNC,
colon, control-character, dot-component, symbolic-link, reparse-point,
and race-resistant containment checks.¶
segment_cbor is the only universally required convenience-key
entry. Record lists, standalone batch projections, JSON projections,
digest files, and operational summaries are optional at the schema
level; disclosure-class rules determine when record or proof material
is required. A Class C manifest does not require source identifiers,
upstream transport counters, or a records directory.¶
segment_number is a JSON string containing the shortest
unsigned base-10 representation of a uint64: 0, or a digit
from 1 through 9 followed by zero or more digits. Its
numeric value MUST NOT exceed 18446744073709551615. This avoids loss
of precision in JSON implementations whose exact integer range ends at
2^53-1. The lexical rules for relative-path,
uint64-decimal, hex32, hex64, and extension
check names are normative prose constraints in addition to the
structural CDDL.¶
verification-manifest-v2 = {
"version": 2,
"ledger_id": hex32,
"site_id": tstr,
"segment_number": uint64-decimal,
"commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
"disclosure_class": disclosure-class,
"artifacts": artifacts,
"anchoring": anchoring,
? "operational_summary": { * tstr => json-data },
? "extensions": { * tstr => json-data },
}
artifacts = {
"segment_cbor": artifact-ref,
? "predecessor_segment_cbor": artifact-ref,
? "records": [* artifact-ref],
? "batches": [* artifact-ref],
? "segment_json": artifact-ref,
? "segment_sha256": artifact-ref,
? "segment_ots": artifact-ref,
? "segment_ots_meta": artifact-ref,
? "peer_attest": artifact-ref,
? "tsa_info": artifact-ref,
? "tsa_tsr": artifact-ref,
? "extensions": { * tstr => artifact-ref }
}
artifact-ref = {
"path": relative-path,
"sha256": hex64
}
anchoring = {
? "tsa": producer-channel-state,
? "ots": producer-channel-state,
? "peer": producer-channel-state
}
producer-channel-state = {
"status":
"verified" / "pending" / "missing" /
"failed" / "skipped" / "complete"
}
verification-result-v2 = {
"version": 2,
"artifact_sha256": hex64,
"commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
"disclosure_class": disclosure-class,
"verification_scope":
"public_recompute" / "partial_verification" / "anchor_only",
"checks_executed": [* check-name],
"checks_skipped": [* skipped-check],
? "channels": { * tstr => verifier-channel-result },
? "policy": { * tstr => json-data },
? "record_multiset_root": hex64,
"overall": "success" / "partial" / "failure"
}
check-name = standardized-check-name / extension-check-name
standardized-check-name =
"bundle_disclosure_validation" /
"verification_manifest_validation" /
"segment_artifact_validation" /
"segment_chain_validation" /
"record_level_recompute" /
"batch_metadata_validation" /
"segment_digest_binding" /
"tsa_verification"
extension-check-name = tstr
skipped-check = {
"check": check-name,
"reason": tstr
}
verifier-channel-result = {
"status":
"verified" / "pending" / "missing" /
"failed" / "skipped" / "complete",
? "reason": tstr,
? "detail": tstr,
? "diagnostic": tstr,
? "check": check-name
}
disclosure-class = "A" / "B" / "C"
relative-path = tstr
uint64-decimal = tstr
hex32 = tstr
hex64 = tstr
json-data =
nil / bool / int / float / tstr /
[* json-data] / { * tstr => json-data }
¶
This appendix gives the structural CDDL for v2 segment and embedded batch artifacts. The lexical and cross-field requirements in Section 4.5, the formation rules in Section 4.4, and the chain rules in Section 4.6 are normative in addition to this structural shape.¶
segment-record-v2 = {
"version": 2,
"commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
"ledger_id": hex32,
"site_id": tstr,
"segment_number": uint64,
"closure_policy": segment-closure-policy-v1,
"close_reason": close-reason,
"prev_segment_sha256": hex64,
"batches": [* segment-batch-v2],
"segment_root": hex64
}
segment-batch-v2 = {
"version": 2,
"ledger_id": hex32,
"site_id": tstr,
"segment_number": uint64,
"batch_number": uint64,
"merkle_root": hex64,
"count": positive-uint64,
"leaf_hashes": [+ hex64]
}
segment-closure-policy-v1 = {
"version": 1,
"interval_ms": positive-uint64,
"batch_record_limit": positive-uint64,
"record_limit": positive-uint64 / nil,
"size_limit_bytes": positive-uint64 / nil,
"empty_mode": "emit" / "suppress"
}
close-reason =
"interval" /
"reconfigure" /
"record_limit" /
"size_limit" /
"shutdown" /
"recovery" /
"manual"
uint64 = 0..18446744073709551615
positive-uint64 = 1..18446744073709551615
hex32 = tstr
hex64 = tstr
¶
The author thanks the OpenTimestamps project for the public calendar infrastructure used during validation.¶
The author thanks Joe Clarke for OPSDIR review feedback that improved the operational considerations and deployment guidance.¶