| Internet-Draft | VTL | August 2026 |
| El Khatabi | Expires 14 February 2027 | [Page] |
This document profiles a verifiable-telemetry ledger. 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, an authoritative segment artifact encoded in Concise Binary Object Representation (CBOR), a producer manifest, three disclosure classes, and binding of the authoritative 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 calendar dates from either the source or the ledger producer. Every baseline producer selects the RFC 3161 timestamp channel, as updated by RFC 5816 and profiled by this document, for every emitted segment. OpenTimestamps (OTS) can be selected only as an additive, deployment-specific timestamp profile; peer signatures are optional attestations.¶
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 14 February 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.¶
Verifiable Telemetry Ledgers (VTL) support long-lived telemetry deployments that 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.¶
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 authoritative segment artifact. Batch roots describe their respective
batches; they are not combined to calculate segment_root.¶
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
+----------------------------+ --> authoritative segment
| Ledger producer | artifact ----------> Verifier
| admit / assign / commit | --> artifact digest
| seal / chain | |
+----------------------------+ +--> timestamp channel
+--> peer attestation
The boundary is admission of an already-formed canonical-record byte string. From that point, the ledger producer is responsible for byte preservation, segment assignment, durable state, artifact construction, and timestamp submission. Verification establishes consistency of disclosed post-admission evidence, not source authenticity, dataset completeness, or physical truth.¶
Document Roadmap. Section 2 and Section 3 define the common terminology and system roles. Producer implementers should focus on Section 4, Section 5, Section 6, Section 8, and Section 9. Verifier implementers should additionally read Section 7 and Appendices A through C. Operators should also read Section 10 and Section 11.¶
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:¶
commitment_profile_id): The opaque text value that selects exactly one commitment profile. This document defines one profile, informally named "VTL Canonical CBOR v2", and assigns it the UUIDv4 ad4a543a-4977-4632-af4d-a0df0301e0cf under [RFC9562]. The identifier uses the RFC 9562 lowercase hex-and-dash representation; the informal name is descriptive and is not an identifier. Producers MUST emit exactly that UUID value. Verifiers MUST compare it by exact string equality and reject an absent or unequal value. Implementations MUST NOT infer profile semantics from a schema version, media type, filename, producer manifest, proof sidecar, the informal name, or by parsing the identifier. The UUID MUST NOT be reused for rules that can produce different commitment bytes or verifier conclusions.¶
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.¶
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.¶
artifacts.segment_cbor references the exact bytes of this object and does not name a separate protocol object. Its storage path and filename are not protocol fields.¶
TimeStampResp: The RFC 3161 protocol response containing status information and, on success, a timestamp token.¶
TimeStampResp stored or disclosed by a VTL bundle. The .tsr suffix is an illustrative storage convention.¶
TimeStampResp.¶
The following JSON excerpt is illustrative; the authoritative segment artifact is CBOR and contains additional required fields:¶
{
"commitment_profile_id": "ad4a543a-4977-4632-af4d-a0df0301e0cf",
"ledger_id": "0123456789abcdef0123456789abcdef",
"segment_number": 42
}
¶
The profile identifier has that same fixed value wherever this
document carries the field. ledger_id and
segment_number identify a particular ledger and segment and
therefore vary.¶
In this document, optional parallel attestation channels are not required for baseline conformance. A baseline producer MUST select and initiate the [RFC3161] channel for every emitted segment. OTS ([OTS]) can be selected as an additive deployment-specific channel, and peer signatures are optional; when selected, 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, authoritative 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.¶
Under the commitment profile defined by this document, 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: restricted-cbor-item
]
restricted-cbor-item =
int / bstr / tstr / bool / nil / finite-float /
[* restricted-cbor-item] /
{ * tstr => restricted-cbor-item }
finite-float = float
¶
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 recursively restricted CBOR data item of the type above. 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.¶
Commitment bytes MUST satisfy the general deterministic-encoding requirements of Section 4.2.1 and the length-first core deterministic-encoding requirements of Section 4.2.3 of [RFC8949]. Items MUST use definite-length encoding; integers and finite floating-point values MUST use their shortest exact encodings. Accordingly, shorter encoded map keys sort first; encoded map keys of equal length sort in bytewise lexical order.¶
Map keys MUST be CBOR text strings. Duplicate map keys and invalid UTF-8 text strings MUST be rejected. CBOR tags, NaN, positive infinity, and negative infinity MUST NOT appear. Permitted values are integers, byte strings, text strings, arrays, maps, booleans, null, and finite deterministic floating-point values.¶
JSON projections are optional and non-authoritative and MUST NOT be commitment inputs. Implementations can use [RFC8785] when stable JSON projection octets are useful. Once a canonical-record byte string is admitted, its exact octets MUST be committed without re-encoding.¶
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 an elapsed-time source maintained by the
ledger producer. That source MUST be non-decreasing and MUST progress
during normal operation while an interval is open. Its resolution
MUST be no greater than the configured
closure_policy.interval_ms value. That field is a positive
uint64 number of milliseconds and specifies 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 other than shutdown 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 producer 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 producer 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 producer MUST determine deadline expiry by checked elapsed-time
subtraction; it MUST NOT add
closure_policy.interval_ms to an absolute counter in a way
that can wrap. If elapsed time cannot be represented or compared
safely, the producer MUST enter the recovery procedure below before
accepting another record.¶
Policy Changes and Early Closure¶
The producer 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 producer 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.¶
A manual closure occurs when a deployment-authorized
administrative action requests immediate closure for a reason not
represented by another close_reason. The producer MUST
serialize that action with admission, close the current logical
interval under its existing policy snapshot, and immediately open
the next logical interval. A shutdown closure occurs when
the producer closes the current logical interval as part of an
orderly cessation of ledger operation. It MUST NOT open another
logical interval until the ledger is reactivated. Artifact emission
and serial consumption for an empty manual or shutdown interval
follow the committed empty_mode.¶
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 neither a completeness claim nor a claim
that no event occurred.¶
Suspend time counts toward closure_policy.interval_ms when
the selected elapsed-time source advances across suspend. If it does
not, or if its continuity is uncertain, the producer MUST apply the
recovery procedure before accepting another record.¶
Recovery and Durable State¶
After restart or failover, the producer 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 producer 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 segment 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.¶
An authoritative segment artifact is interpreted only under its in-band
commitment_profile_id. Because that identifier is inside the
authoritative segment artifact bytes, every proof over its digest
binds the commitment semantics. A producer manifest MUST
repeat the same value and verifiers MUST reject a mismatch. Verifiers
MUST NOT infer the commitment profile from the filename, 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 the profile UUID defined in Section 2.¶
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 bytes of the previous authoritative segment artifact, 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 authoritative 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.¶
The deterministic-CBOR object is the authoritative segment artifact. A JSON
projection, filename, and storage path are non-authoritative. A
verifier MUST compare the decoded segment_number with the
producer manifest claim rather than trusting a path or filename.¶
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 exact bytes of the predecessor's authoritative segment artifact.¶
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 producer instances 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 authoritative 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
chain_status as predecessor_not_disclosed.¶
A deployment can store canonical records, authoritative segment artifacts, producer manifests, verifier results, and timestamp evidence in any suitable layout. Filenames and layouts are non-authoritative. Each disclosed record artifact MUST contain the exact admitted canonical-record octets without a wrapper or re-encoding.¶
Every verification bundle that claims a disclosure class under this document MUST disclose the authoritative segment artifact and a producer manifest.¶
The artifact's in-band commitment_profile_id is the
cryptographically bound profile identifier. The producer manifest
repeats the ledger identity, segment number, commitment profile,
claimed disclosure class, artifact digests, and claimed channel
state. It MUST NOT contain a segment-chain validation conclusion,
per-channel verifier status, failure reasons, 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.¶
Producer channel state is limited to present when the
corresponding evidence artifact is disclosed and pending
when the channel was selected but evidence is not yet available. An
unselected channel is omitted. Producer manifests MUST NOT use
verifier states such as verified or failed.¶
A pending channel MAY omit its evidence artifact. A
present TSA channel MUST reference tsa_tsr. A
present OTS channel MUST reference segment_ots and
MUST include the sidecar reference and binding required by the
applicable deployment-specific OTS profile. A present peer
channel MUST reference peer_attest and the applicable
binding metadata.¶
The producer manifest is the primary disclosure surface for verifier-visible producer claims. Its schema is defined in Appendix B. Deployment-specific data can be carried only in explicit extension containers and MUST preserve the semantics defined here.¶
Verification under Section 6.6 produces a logical verifier result. Only that verifier-authored result states the exercised scope, any segment-chain conclusion, per-channel validation status, verifier-policy identifier when applicable, overall outcome, and failure reasons. The result reports conclusions needed by a relying party; local step-by-step diagnostics and execution traces are implementation-specific. A producer manifest and a verifier result MUST NOT be represented as the same object.¶
A verifier MAY serialize its result as JSON. A serialized result that
claims conformance with this document MUST use the schema in
Appendix B and the application/json media
type. This document does not request a specialized media type for
verifier results.¶
Every path-bearing object consumed during verification, including a
producer manifest artifact reference, a deployment-specific sidecar,
or an extension object, MUST satisfy the requirements in this
subsection. Each path is a UTF-8 string 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.¶
For every such consumed path, path validation and file opening MUST be one race-resistant operation; a check-then-open sequence that permits target substitution is nonconformant. These checks are semantic requirements and do not depend on a regular-expression dialect. Every artifact listed in the producer manifest MUST carry a lowercase hexadecimal SHA-256 digest entry.¶
The producer manifest binds claim semantics to the authoritative
segment artifact. The producer manifest's ledger_id, site_id,
segment_number, and commitment_profile_id MUST match
the corresponding fields in the authoritative segment artifact. A
verifier obtains the applicable profile identifier from the artifact
itself rather than from a path or filename.¶
A deployment-specific OTS profile that uses a sidecar MUST bind at least:¶
Any path-valued artifact or ots_proof member, and
any other path-bearing member consumed from a deployment-specific
sidecar, MUST satisfy Section 5.3.
Verifiers MUST recompute the authoritative segment artifact digest
and compare it with the sidecar before accepting any proof validation
result.¶
For every emitted segment, a baseline producer MUST select and
initiate the [RFC3161] channel. Its RFC 3161 evidence
MAY remain pending while issuance is incomplete, but a
baseline success result requires verified RFC 3161 evidence.¶
OTS and peer channels are additive. A baseline verifier MAY report
either channel as skipped without preventing
success. If validation of selected optional evidence is
attempted and fails, that failure prevents success and
produces failure when verifier policy requires the channel;
otherwise it produces partial. A selected optional channel
whose evidence is pending or missing produces
partial unless verifier policy requires failure.¶
The generic anchoring contract is simple: a producer 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 authoritative segment artifact digest locally; proof validation occurs only after digest binding validation succeeds.¶
A timestamp or attestation over the authoritative 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 verifier result.¶
For each emitted segment, a baseline producer MUST select and initiate the RFC 3161 timestamping channel over the authoritative segment artifact digest. The producer MUST seal and durably write the authoritative authoritative segment artifact without waiting for timestamp proof completion. A deployment MAY also select a deployment-specific timestamp channel, such as OTS ([OTS]), under an explicitly identified deployment profile. Such a channel is additive and is not a baseline interoperable timestamp profile under this document. Peer signatures are optional attestations and do not by themselves satisfy the timestamping-channel requirement.¶
Baseline producers MUST select this channel for every emitted segment, and baseline verifiers MUST implement it.¶
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. The producer MUST set
TimeStampReq.certReq to TRUE.¶
The TimeStampReq, TimeStampResp, and timestamp
token MUST conform to [RFC3161], as updated by
[RFC5816] and restricted by this section. The token
MUST contain exactly one CMS
SignerInfo as defined by [RFC5652].¶
A successful TimeStampResp.status.status MUST be
granted (0). A verifier MUST reject
grantedWithMods (1) under this profile.¶
The SignerInfo signed attributes MUST contain exactly one
SigningCertificateV2 attribute with exactly one attribute
value, as defined by [RFC5035]. The first
ESSCertIDv2.certHash MUST equal SHA-256 over the complete
DER encoding of the selected signer certificate. If
hashAlgorithm is present, it MUST identify SHA-256;
omission denotes the SHA-256 default. If issuerSerial is
present, it MUST identify that same certificate. The signed
attributes MUST NOT contain a legacy
SigningCertificate attribute.¶
Because this profile requires
TimeStampReq.certReq=TRUE,
SignedData.certificates MUST contain exactly one X.509
certificate that matches both SignerInfo.sid and the first
ESSCertIDv2; zero or multiple matching certificates are a
verification failure. The set MAY also contain unrelated
certificates or certification-path certificates.¶
A deployment using this channel MUST define accepted TSA trust anchors, accepted TSA policy identifiers, certificate-revocation policy, acceptable signature and certificate algorithms, and any constraints applied to the token's generation time. When operators control the TSA, responses SHOULD include necessary intermediates and SHOULD omit an already provisioned trust anchor. A verifier MUST NOT rewrite a received response or reject it merely because it contains additional nonmatching certificates.¶
A verifier evaluating disclosed RFC 3161 evidence MUST recompute the
authoritative segment artifact digest and validate the
TimeStampResp and token under [RFC3161], as
updated by [RFC5816]. Validation MUST include a
response status of granted (0) and required token presence;
the CMS
id-signedData content type and id-ct-TSTInfo
encapsulated content type; exact SHA-256 message-imprint equality;
the CMS signature and signed attributes; unambiguous
signer-certificate binding; the signer certificate's single
critical extended-key-usage extension containing only
id-kp-timeStamping; certification-path validation under
[RFC5280] and configured trust anchors; configured
TSA policy and certificate-validation constraints; and nonce
equality when the corresponding original request is evaluated and
contained a nonce. Any failure is a timestamp-channel verification
failure. The corresponding TSA channel status in a verifier result
MUST be verified on success and failed on failure.¶
When [OTS] is used, the producer stamps the SHA-256 digest of the exact authoritative segment artifact bytes and stores an OTS proof plus its binding metadata.¶
OpenTimestamps is referenced here as a deployed public timestamping ecosystem rather than an IETF-standardized proof format. This document does not define an OTS wire format, calendar trust model, accepted attestation set, upgrade procedure, or validation algorithm. A deployment claiming OTS interoperability MUST define those items, identify the profile and verifier policy in use, and specify the exact binding metadata. Baseline VTL implementations are not required to implement OTS.¶
A verifier reports OTS validation under a distinct OTS channel. The
channel result MUST identify the collision-resistant deployment-
specific validation profile in use, for example
com.example.ots-verification; it MUST NOT report an OTS
proof as an RFC 3161 TSA channel.¶
If OTS submission fails, times out, or yields only an incomplete proof, the producer 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.1, Section 10.2, and Section 10.4.¶
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: the channel was selected but its evidence is incomplete, not yet available, or awaiting upgrade; this is not equivalent to invalid.¶
missing: an expected proof or channel artifact is absent without a valid pending producer state.¶
failed: validation was attempted and did not succeed.¶
skipped: validation was not attempted because of disclosure class, verifier configuration, or local policy.¶
The outcome effects of missing, pending, and
skipped are defined in
Section 6.1 and
Section 6.6.5.¶
Deployments MAY also produce a deployment-specific peer signature quorum over the same authoritative segment artifact digest.¶
This document does not define an interoperable peer-signature
validation profile. A peer channel result MUST identify the
collision-resistant deployment-specific validation profile in use,
for example com.example.peer-quorum-verification. A future
specification can define interoperable peer-signature semantics.¶
When multiple channels are present, verifiers SHOULD validate all available channels independently and report per-channel results.¶
Failure of a peer-attestation channel is fatal only when local
verifier policy makes that channel required. Otherwise, an attempted
peer-attestation failure prevents success but permits
partial.¶
Verifiers MUST first decode the authoritative segment artifact and
determine the applicable commitment_profile_id from its
in-band field. An absent or unsupported value prevents a successful
verification claim. When the field can be decoded as a text string,
the verifier result's optional commitment_profile_id MUST
echo its exact artifact value, including when that value is
unsupported. The producer manifest's ledger_id,
site_id, segment_number, and
commitment_profile_id MUST exactly match the corresponding
artifact fields whenever those fields can be decoded.¶
The verifier MUST treat commitment_profile_id as the semantic
key for interpreting the authoritative segment artifact. A structurally
well-formed authoritative segment artifact and a valid timestamp proof are insufficient
for semantic verification if the applicable
commitment_profile_id is absent or unsupported. A producer
manifest mismatch is a verification failure even when the artifact and
timestamp are otherwise valid.¶
The producer manifest's disclosure_class is the producer-claimed
class. The result's claimed_disclosure_class MUST repeat
that value. The result's verification_scope identifies the
scope actually exercised: public_recompute corresponds to
Class A, partial_verification to Class B, and
anchor_only to Class C. A scope is weaker in the order A,
B, C. If the verifier intentionally exercises a weaker scope than
the disclosed inputs support, the overall result MUST be
failure with scope_not_exercised. If the disclosed
inputs are genuinely inadequate for the claimed class or asserted
scope, the result instead uses insufficient_disclosure.
Exercising a stronger scope does not rewrite the producer-claimed
class.¶
Verifiers MUST determine the applicable verification scope from the disclosed artifacts, the claimed disclosure class, and local verifier policy. Reported outcomes MUST NOT claim assurances outside the scope actually exercised.¶
The result's manifest_sha256 MUST equal SHA-256 over the
exact UTF-8 octets of the producer manifest that was validated. The verifier
MUST NOT reserialize or otherwise normalize the JSON before
calculating this value. This field identifies the validated input;
it does not authenticate the verifier result.¶
The verifier MUST always compute SHA-256 over the exact referenced
bytes of artifacts.segment_cbor and compare it with
artifacts.segment_cbor.sha256. That value checks producer
manifest self-consistency only; it is not external timestamp evidence
and MUST NOT be counted as a timestamp-channel binding.¶
For every producer manifest artifact reference consumed during verification,
the verifier MUST compute SHA-256 over the exact referenced file
bytes and compare it with the reference's sha256 value. A
mismatch is a verification failure. A verifier MAY reuse one
successful file-digest computation for repeated references to the
same bytes. Duplicate record occurrences nevertheless contribute
once per listed occurrence to record-level and multiset
computations.¶
Verifiers SHOULD apply the following validation steps in fail-fast order, subject to the exercised verification scope:¶
artifacts.segment_cbor.sha256, and validate the digest of every other producer manifest artifact reference consumed during the remaining steps. Do not count the producer manifest digest as external timestamp evidence.¶
chain_status to epoch. For a non-epoch segment whose predecessor is disclosed, validate ledger and site identity, contiguous serials, and prev_segment_sha256; set chain_status to validated on success or failed on failure. When the predecessor is unavailable, set chain_status to predecessor_not_disclosed.¶
public_recompute, validate each disclosed canonical-record CBOR artifact, hash its exact disclosed octets without re-encoding, validate the batch metadata contract, and recompute segment_root. Compare the recomputed result to the authoritative segment_root. Do not attempt to reconstruct a record from source telemetry.¶
partial_verification, validate the complete batch objects embedded in the authoritative segment artifact as specified in Section 6.6.3. Withheld-material validation beyond those batch objects is deployment-specific and MAY be summarized in the result's extensions member.¶
anchor_only, do not claim record-level or batch recomputation.¶
messageImprint.hashedMessage, an OTS sidecar artifact_sha256, or deployment-specific peer-attestation binding metadata. A mismatch in any consumed binding is a verification failure. A selected channel that is pending can lack an external binding and yields partial unless verifier policy requires failure. A channel claimed present without a usable external binding is a verification failure.¶
validation_profile value.¶
When batch metadata is within the exercised verification scope, verifiers MUST apply the following validations 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;¶
segment_root; for an empty emitted segment, the empty-list root defined in Section 4.3 applies; and¶
leaf_hashes equals the leaf digest multiset derived from disclosed canonical records when canonical-record artifacts are available.¶
A verifier result whose overall value is failure
MUST contain one or more machine-usable failure_reasons.
This profile defines the following baseline categories:¶
unsupported_commitment_profilecommitment_mismatchsegment_chain_mismatchchannel_failureinsufficient_disclosurescope_not_exercisedverifier_policy_rejection
A conforming result MUST use only those baseline categories in
failure_reasons. Deployment-specific detail belongs in the
result's extensions member; this document creates no
extension namespace for failure-reason values. Failure reasons are
conclusions, not a trace of internal verifier steps. A category MUST
NOT occur more than once in one result. Failure reasons MUST be
absent when overall is success or partial;
channel status explains a partial outcome.¶
Verifier output states the claimed disclosure class, the verification scope actually exercised, any segment-chain conclusion, per-channel proof status, failure reasons when applicable, and whether the resulting claim is public recompute, partial verification, or anchor-only evidence.¶
Overall outcome is determined after applying the validations
required by the claimed disclosure class, exercised scope, and
verifier policy and after determining channel applicability. A
chain_status of predecessor_not_disclosed does not
by itself degrade the outcome; it makes no chain-adjacency claim.
A chain_status of failed makes the overall outcome
failure.¶
success: RFC 3161 evidence was successfully verified;
every validation and channel required by the disclosure class,
exercised verification scope, and verifier policy succeeded; and no
selected optional channel failed, remains pending, or is missing.
An additive OTS or peer channel that was not selected or that a
baseline verifier skipped does not degrade the outcome.¶
partial: the disclosed artifacts satisfy the claimed
disclosure class and no required validation or channel failed, but no
timestamp channel has yet been verified because qualifying timestamp
evidence remains pending and verifier policy permits that condition;
or at least one selected non-required channel failed, is pending, or
is missing, and verifier policy permits that condition.¶
failure: a required validation or channel failed or
could not execute, a consumed artifact or binding digest mismatched,
a channel claimed present lacked a usable external binding,
every completed timestamp-channel validation failed and no qualifying
timestamp-channel validation remains pending, or the claimed
disclosure class was not otherwise satisfied.¶
When local verifier policy affects validation or channel applicability or
any validation outcome, the result MUST include
verifier_policy_id. This includes policy inputs to
RFC 3161 validation, such as trust anchors, accepted TSA policy
identifiers, revocation policy, algorithm constraints, and
generation-time constraints. A result MAY include
verifier_policy_sha256 only when the corresponding policy
artifact is available to the verifier or otherwise discoverable. If
verifier_policy_sha256 is present,
verifier_policy_id MUST also be present, and the digest MUST
be SHA-256 over the exact policy-artifact bytes. A bare policy digest
is not sufficient policy identification.¶
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.¶
The producer claims one disclosure class in the producer manifest. The verifier independently reports the scope it actually exercised as specified in Section 6.6. A verifier claim MUST be limited to the disclosed artifacts and validation scope actually exercised 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.¶
A bundle whose only timestamp evidence uses a deployment-specific channel is interoperable only with verifiers that implement the identified deployment profile. A verifier that does not support that profile MUST NOT report successful timestamp-bearing verification.¶
A producer manifest claiming Class A, B, or C MUST contain at least one
selected timestamp channel in anchoring; a peer channel alone
is insufficient. A selected channel in pending state MAY omit
its evidence artifact. A present TSA channel requires
tsa_tsr; a present OTS channel requires
segment_ots and the applicable sidecar binding. Baseline
conformance additionally requires selection of the TSA channel as
specified in Section 6.1.¶
Class A is appropriate when public recomputation from disclosed
canonical records and authoritative segment artifacts is required. A Class A
bundle MUST include all canonical-record artifacts required to
recompute the claimed segment root, the authoritative segment artifact including
its batch objects, the producer manifest, and the selected timestamp-
channel states required above. For each channel claimed
present, the bundle MUST include its required evidence artifact
and binding metadata. A peer attestation does not satisfy the timestamp-
channel selection requirement. The authoritative segment artifact records the
commitment_profile_id.¶
A Class A verifier can perform record-level recomputation,
batch-metadata validation, segment-root recomputation, authoritative segment artifact digest
validation, producer manifest artifact-digest validation, and enabled anchor or
external-evidence validation when the corresponding artifacts are
disclosed. A successful public_recompute result asserts that
those required validations succeeded. A public-recompute claim is
invalid if required record artifacts are missing, root recomputation
was not performed, the in-band profile is absent or unsupported, or a
required digest validation fails.¶
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 authoritative segment
artifact, the producer manifest, and the selected timestamp-channel
states required above. For each channel claimed present, it
MUST include the timestamp proof and binding metadata. It MAY include commitments covering
withheld material, and a policy artifact describing withheld or
partitioned material.¶
Class B validation includes the complete batch metadata embedded in the
authoritative segment artifact. The verifier MUST validate that
metadata, including recomputation of
segment_root from the complete batch leaf list, even when
record preimages are withheld. Validation can additionally cover
disclosed withheld-material commitments, auditor-supplied material,
and timestamp channels present in the bundle. The
partial_verification scope states that public record-level
recomputation was not performed and that the result is not publicly
recomputable. Deployment-specific withheld-material conclusions MAY
be carried in the result's extensions member using
collision-resistant names.¶
Class C provides segment-level commitment and timestamp evidence
without record preimages. A Class C disclosure MUST be labeled as such
and MUST NOT claim record-level reproducibility. A Class C bundle MUST
include the authoritative segment artifact, the producer manifest, and
the selected timestamp-channel states required above. For each channel
claimed present, it MUST include the timestamp proof artifact
plus the metadata needed to bind it to the authoritative segment artifact digest. The in-band
commitment_profile_id supplies the profile identity.¶
A verifier exercising anchor_only can validate
authoritative segment artifact digest binding, producer manifest digests, chain or anchor
existence, and timestamp-channel status when the relevant artifacts
are present. It MUST report the anchor_only scope and MUST NOT
claim record-level or batch recomputation. For a non-epoch segment
whose predecessor artifact is not disclosed, it MUST report
chain_status as predecessor_not_disclosed rather than
validated.¶
The producer manifest MUST include:¶
ledger_id, site_id, and segment_number,¶
disclosure_class,¶
commitment_profile_id,¶
A separate verifier result MUST identify the authoritative segment
artifact and producer manifest digests, the commitment profile evaluated, the producer-claimed
disclosure class, the verification scope exercised, segment-chain
status when a chain conclusion can be made, per-channel validation
results, verifier-policy identifier when policy affects applicability
or a validation outcome, overall
outcome, and failure reasons when the outcome is failure. The
channels object MUST be present and non-empty, including when
the selected timestamp channel is missing, pending, skipped, or
failed.¶
Document revisions are editorial and do not alter commitment output by
themselves. Schema version fields identify individual object
shapes; neither a document revision nor a schema version substitutes
for the commitment_profile_id defined in
Section 2.¶
The name canonical-record-v1 identifies the stable version 1
canonical-record array used as input by this commitment profile. The
segment-record version value 2 identifies its object
shape; it does not rename the unchanged record-array schema or select
the commitment rules. A verifier that encounters an unsupported
commitment_profile_id MUST reject the verification claim
rather than applying fallback semantics.¶
This document defines exactly one commitment_profile_id. The
profile UUID assigned in Section 2 is a randomly
generated UUIDv4 under [RFC9562] and is bound
exclusively to the commitment profile specified by this document.
This document defines no general or private-use namespace for
additional values. Reusing the UUID for different rules is
nonconformant and creates ambiguous verifier semantics even though the
identifier remains bound into the authoritative segment artifact digest. A verifier
that encounters a conflicting semantic binding for the UUID MUST
reject the verification claim.¶
A future commitment profile MUST use a distinct UUID defined by a separate specification. Existing sealed artifacts retain their original identifier and semantics. Changing the UUID in a sealed artifact changes its exact bytes and digest and forces corresponding predecessor-link changes through the chain of successor artifacts. Such artifacts therefore MUST NOT be renamed or reinterpreted in place.¶
A deployment that introduces a future commitment profile SHOULD use a backward-compatible rollout that preserves verification support for artifacts sealed under this profile. A producer rollback affects only subsequently formed artifacts; it MUST NOT relabel or re-encode sealed artifacts, reuse segment numbers, or create an unreported predecessor discontinuity.¶
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:¶
ESSCertIDv2,¶
Negative coverage should include:¶
device_time, or ingest_time,¶
segment_root instead of the authoritative segment artifact digest,¶
chain_status as validated without the required predecessor,¶
SigningCertificateV2 attribute or value,¶
SigningCertificate attribute or a mismatched ESSCertIDv2.issuerSerial,¶
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.¶
Consistent with [I-D.ietf-opsawg-rfc5706bis], deployments SHOULD expose admission, sealing, timestamp submission, proof completion, retention, and verification as distinct operational states so that a delayed external channel is not confused with a malformed authoritative segment artifact.¶
Operators SHOULD monitor at least the following signals:¶
An operator-visible fault state SHOULD distinguish an invalid authoritative segment 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.¶
Management integrations SHOULD expose these events in a structured, machine-readable form with a stable event code, event time, severity, state transition, and, when known, the affected site, ledger, and segment number. They SHOULD include correlation data sufficient to reconstruct admission, sealing, anchoring, and verification activity during troubleshooting or digital-forensics review. Human-readable text can supplement, but does not replace, those stable fields.¶
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.¶
An implementation SHOULD expose the effective value of each operationally significant setting and whether that value is an implementation default or an operator override. Deployment documentation SHOULD explain the rationale for defaults and identify defaults expected to change as capacity, algorithms, or external services evolve.¶
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.¶
When a deployment-specific OTS profile is used, its calendar selection, redundancy, trust assumptions, finality criteria, and retention policy MUST be documented. Producers SHOULD retain disclosed proof artifacts for at least as long as the corresponding authoritative segment artifacts remain available for verification.¶
Coordinated configuration changes SHOULD be validated for compatibility before activation, applied atomically where the deployment permits, and accompanied by a documented rollback plan. A rollback MUST follow the interval-transition rules in Section 4.4 and MUST NOT mutate sealed artifacts, reuse a segment number, or conceal a chain discontinuity.¶
Producers SHOULD expose cumulative counters, high-water marks, and time-in-state measurements for admission and rejection, durable-write and sealing latency, anchoring backlog, proof-completion latency, retained-artifact storage, and verification duration. Counter definitions SHOULD state what is included, their reset behavior, and how wrap or discontinuity is reported. Reporting time spent in a delayed or failed state is generally more useful than a current-state snapshot alone.¶
Monitoring interfaces SHOULD support bounded, change-driven collection where practical and MUST NOT permit polling or automated queries to silently bypass admission, durability, or closure rules. Deployments SHOULD test behavior at record, storage, anchoring, and verifier capacity limits and document the resulting backpressure, rejection, and recovery behavior.¶
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, identify its
deployment-specific validation_profile, and use
pending_proof as the channel reason unless validation was
attempted and failed.
The outcome is partial when policy permits pending OTS
evidence and failure when policy requires completion.¶
tsa as
pending, report the TSA channel as pending and
use pending_proof unless a more specific human-readable
diagnostic is needed. The outcome is partial unless
verifier policy requires failure. Otherwise report the
selected TSA channel as missing; a channel claimed
present without tsa_tsr is a verification
failure. A baseline result cannot treat the TSA channel as
unselected or inapplicable.¶
chain_status as validated across an unknown
predecessor or serial conflict; a newly created ledger reports
epoch only after the epoch-segment requirements succeed.¶
Operators SHOULD periodically run an independent verifier against a recent bundle using the disclosure class expected by consumers. Operators SHOULD alert on verification failures, proofs pending beyond policy, or admission, timer, serial, fencing, and artifact-write faults.¶
Deployments that must preserve verifiability beyond the useful life of a timestamp certificate or current algorithms can define a separate archival-evidence profile using the timestamp-renewal or hash-tree-renewal mechanisms described in [RFC4998]. Such renewal evidence is outside the baseline VTL bundle.¶
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 verifier result establishes only that the disclosed artifacts are internally consistent with this profile and with any validated proof channels.¶
The authoritative segment artifact, producer manifest, and verifier result formats contain no executable content and define no intrinsic compression, but they provide no confidentiality. A producer manifest directs a verifier to open bundle-relative paths, creating path-traversal, symbolic-link or reparse-point substitution, and check-then-open race risks; verifiers MUST apply the containment and race-resistant access rules in Section 5. A timestamp over the authoritative segment artifact does not authenticate the producer manifest or verifier result. The baseline does not otherwise authenticate either object. When their provenance matters, those objects require separate authentication or the relying party must rerun verification from authenticated inputs.¶
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. Operational guidance for admission persistence, elapsed time, health, and verification procedures is consolidated in Section 10.¶
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.¶
Ledger-identifier generation is security sensitive. The random-source
requirement in Section 4.6 reduces accidental
identifier collision but does not replace durable state or writer
fencing. Operators SHOULD audit random-source initialization and
failures, record each new-epoch allocation, and alert on any observed
reuse of a ledger_id or conflicting use of a
(ledger_id, segment_number) pair.¶
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.¶
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
producer manifest 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 segment artifacts; requires the applicable
commitment_profile_id to be disclosed and bound to the same
authoritative segment artifact digest, and requires non-authoritative metadata and
sidecars to match the authoritative segment artifact. Any future semantic or
hash-composition change MUST use a new UUID as its
commitment_profile_id.¶
An attacker can modify a committed authoritative 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.¶
Successful RFC 3161 validation proves that the bytes bound by the validated message imprint existed no later than the TSA-asserted time, under the configured TSA trust and validation policy. It does not prove the ledger producer's identity, the source of the telemetry, or attribution of those bytes to a particular producer, device, site, or physical event.¶
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.4.2, and operational reporting for missing or pending channels is described in Section 10.4.¶
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 4.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.¶
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 producer'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 producer honestly observed real elapsed time. Likewise, an OTS proof validated under an identified deployment profile establishes only the time claim defined by that profile; it does not prove when the segment opened or that every configured deadline was honored.¶
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.1. This profile does not define a complete denial-of-service defense.¶
An attacker can rely on a successful verifier 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.¶
Leaf hashes are unsalted. If withheld telemetry has low entropy or its possible record inputs are enumerable, an observer can hash guesses offline and compare them with disclosed leaf hashes. Class B and Class C therefore provide limited confidentiality for enumerable record inputs. A high-entropy, application-layer nonce included in each record can make guessing impractical, but nonce generation and protection are outside this profile and do not constitute confidentiality supplied by VTL.¶
Even when payloads are withheld, producer manifests, authoritative 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.¶
Withholding record preimages in Class B or Class C does not by itself provide confidentiality. Because VTL leaf hashes are unsalted, an observer can test enumerable, low-entropy telemetry values by offline guessing. Applications can include a high-entropy record nonce to reduce that risk, but this is an application-layer mitigation rather than confidentiality provided by VTL; see Section 11.13.¶
Even when device_id is pseudonymous, its repeated disclosure
can link records across segments or external datasets and can enable
re-identification when combined with site_id, timestamps, or
payload characteristics. Operators SHOULD avoid publishing stable
identifiers beyond the intended disclosure scope and SHOULD assess
linkability before releasing Class A material.¶
Disclosure of producer manifests, canonical-record artifacts,
authoritative 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). This document requests exactly two IANA
actions: registration of
application/vnd.verifiable-telemetry-segment+cbor and
application/vnd.verifiable-telemetry-manifest+json in the
vendor tree of the Media Types registry. It requests no other IANA
action: no CBOR tag, no commitment_profile_id registry, and no
CoAP Content-Format allocation.¶
IANA is requested to register the following media types in the vendor tree of the "Media Types" registry in accordance with [RFC6838]:¶
These requests allocate values from an existing registry under the Expert Review procedure defined by [RFC6838]. They do not require IETF Review or Standards Action and are available to an Independent Stream document under [RFC8726].¶
The complete registration template is as follows.¶
Type name: application¶
Subtype name: vnd.verifiable-telemetry-segment+cbor¶
Required parameters: N/A¶
Optional parameters: N/A¶
Encoding considerations: binary¶
Security considerations: see Section 11.5, Section 11.6, Section 11.7, Section 11.12, and Section 11.11.¶
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, with the structural CDDL in
Appendix C. 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, together with Appendix C.¶
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/vnd.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: N/A¶
Author: Bilal El Khatabi¶
Change controller: Bilal El Khatabi¶
Provisional registration: no¶
The complete registration template is as follows.¶
Type name: application¶
Subtype name: vnd.verifiable-telemetry-manifest+json¶
Required parameters: N/A¶
Optional parameters: N/A¶
Encoding considerations: binary¶
Security considerations: see Section 11.1, Section 11.5, Section 11.6, Section 11.12, and Section 11.11.¶
Interoperability considerations: this media type identifies the
producer manifest defined by Section 5,
Section 6.6, and Appendix B. The
producer manifest is a non-authoritative metadata and digest-binding
surface. A recipient still needs the referenced authoritative
segment artifact and MUST compare the producer 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.6, and Appendix B.¶
Applications that use this media type: producers, verifiers, disclosure tools, publication services, and archival or audit systems that exchange producer manifests.¶
Fragment identifier considerations: no fragment identifier syntax is
defined by this document for
application/vnd.verifiable-telemetry-manifest+json.
Fragment identifiers, if present, are processed according to the
+json structured syntax suffix rules in
[RFC6839].¶
Additional information:¶
Person & email address to contact for further information: Bilal El Khatabi <elkhatabibilal@gmail.com>¶
Intended usage: COMMON¶
Restrictions on usage: N/A¶
Author: Bilal El Khatabi¶
Change controller: Bilal El Khatabi¶
Provisional registration: no¶
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.¶
This document requests no IANA registry for
commitment_profile_id. The two vendor-tree media-type
registrations in Section 13.1 are independent
registration requests under [RFC6838]. Neither
registration creates a namespace or subregistry for commitment-profile
identifiers, and this document requests no new IANA registry. This
document instead assigns the fixed UUIDv4 defined in
Section 2 as its sole profile identifier. UUID
generation under [RFC9562] does not
require a central allocation registry. Section 8
specifies the identifier's binding and collision behavior. Any
future registry requires a separate specification with an
appropriate publication stream and registration policy.¶
This document requests no CoAP Content-Format allocation for either media type registered by Section 13.1.¶
Separate specifications can define upstream admission, exported bundle
media types, SCITT or COSE publication, peer-signature validation,
withheld-material disclosure, or alternative commitment profiles.
Such extensions do not change this document's baseline semantics. A
change to commitment bytes or calculations requires a distinct UUID as
its commitment_profile_id.¶
Wrapped hexadecimal values in this appendix are presentation-only; a verifier or implementer should concatenate adjacent lines without inserting whitespace.¶
The following compact known-answer vector is normative for the profile
UUID defined in Section 2. 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.¶
segment_cbor is 1047 octets and commits three leaves in two
batches. segment_sha256 is the transcription checksum over
those exact segment_cbor octets; it is not a separate
commitment input.¶
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 = aa676261746368657382a865636f756e740267736974655f696466616e2d3030 316776657273696f6e02696c65646765725f6964782062376131643565343063 366634333865396137356462323763393666333161616b6c6561665f68617368 6573827840346638326533653765653930613131313737346464393531343731 6133316434353832653039303861306264356664363363303038306330323331 6634306363784062353232373335376366356430363139393134393731643864 6335323138633561393932363062633564356531623630636231303833613931 316132616361666b6d65726b6c655f726f6f7478403535343439316534656466 3238303631363232333936623833613837306462343635323231313535373132 3763363634633662653163346164363634373166666c62617463685f6e756d62 6572006e7365676d656e745f6e756d62657200a865636f756e74016773697465 5f696466616e2d3030316776657273696f6e02696c65646765725f6964782062 376131643565343063366634333865396137356462323763393666333161616b 6c6561665f686173686573817840623833626332376632643862653361363633 3733616632346536616633656566666666393966663036393661653138633730 65333739653835333739366432366b6d65726b6c655f726f6f74784062383362 6332376632643862653361363633373361663234653661663365656666666639 396666303639366165313863373065333739653835333739366432366c626174 63685f6e756d626572016e7365676d656e745f6e756d6265720067736974655f 696466616e2d3030316776657273696f6e02696c65646765725f696478206237 6131643565343063366634333865396137356462323763393666333161616c63 6c6f73655f726561736f6e68696e74657276616c6c7365676d656e745f726f6f 7478406263363530323535326564306335313566353864316336333265353464 6233373539343034323630396235393833386562306435623364353834326161 3035346e636c6f737572655f706f6c696379a66776657273696f6e016a656d70 74795f6d6f64656873757070726573736b696e74657276616c5f6d731a05265c 006c7265636f72645f6c696d6974f67073697a655f6c696d69745f6279746573 f67262617463685f7265636f72645f6c696d6974026e7365676d656e745f6e75 6d6265720073707265765f7365676d656e745f73686132353678403030303030 3030303030303030303030303030303030303030303030303030303030303030 30303030303030303030303030303030303030303030303030303075636f6d6d 69746d656e745f70726f66696c655f6964782461643461353433612d34393737 2d343633322d616634642d613064663033303165306366 segment_sha256 = 0f0397186e667db6d8938a2cc3b5b36e349ae85ae290107a1da3a924fa33240b 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 exact known-answer vectors in this
appendix are normative.¶
This appendix defines the Concise Data Definition Language (CDDL) ([RFC8610]) shape for the 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]. Parsers MUST reject duplicate object member names; generators MUST NOT emit them.¶
The producer manifest and verifier result both use version 2 in this profile. The producer manifest version is not independently negotiated.¶
Baseline failure reasons are defined in Section 6.6.4. Channel validation-profile names MUST be collision resistant.¶
The verifier result's commitment_profile_id is optional because
a malformed authoritative segment artifact might not be decodable far
enough to recover it. When the artifact field is decodable as a text
string, the result MUST include and exactly echo that value. It is a
generic tstr so that a result can report
unsupported_commitment_profile without replacing the
unsupported artifact value with this document's UUID.¶
chain_status MUST be present whenever the authoritative
segment artifact can be decoded far enough to make one of the chain
conclusions defined here. It MUST be absent otherwise, and absence
makes no chain claim. Its value is epoch only after the epoch
segment's serial and zero predecessor have been validated; validated
only after a disclosed non-epoch predecessor and its linkage have
been validated; predecessor_not_disclosed when that artifact
is unavailable; and failed when an attempted chain validation
fails. failure_reasons MUST be present and non-empty exactly
when overall is failure. An OTS or peer channel result
MUST include the collision-resistant validation_profile used;
the baseline TSA channel MUST omit it because its validation profile is
defined by Section 6.3.¶
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.3 to every consumed path-
bearing object, including deployment-specific sidecars and extensions.
Those rules include backslash, drive-prefix, UNC, colon, control-
character, dot-component, symbolic-link, reparse-point, containment,
and race-resistant-open checks.¶
segment_cbor is universally required. A Class A producer manifest MUST
contain records. JSON projections, standalone digest files,
TSA-info projections, and operational summaries are not baseline
producer manifest fields.¶
For a producer manifest claiming Class A, B, or C, anchoring MUST
contain tsa or ots to identify a selected timestamp
channel. peer alone is insufficient. The ots member
denotes a deployment-specific profile as described in
Section 6.4; its presence does not define baseline
OTS proof-format interoperability. A baseline producer manifest MUST
contain tsa for every emitted segment.¶
A channel in pending state MAY lack its evidence artifact. For
present, tsa requires tsa_tsr, ots
requires segment_ots and, when the deployment profile uses a
sidecar, the applicable segment_ots_meta binding; and
peer requires
peer_attest and its applicable binding metadata.¶
The fixed channels keys are tsa, ots, and
peer. Any extension channel key MUST be a collision-resistant
name and MUST NOT equal a fixed key. The channels map MUST be
non-empty. A channel reason is human-readable diagnostic text,
except where this document explicitly specifies a token such as
pending_proof.¶
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
collision-resistant extension names are normative prose constraints
in addition to the structural CDDL. hex32 is exactly 32
lowercase hexadecimal characters, and hex64 is exactly 64
lowercase hexadecimal characters.¶
vtl-commitment-profile-id =
"ad4a543a-4977-4632-af4d-a0df0301e0cf"
producer-manifest-v2 = {
"version": 2,
"ledger_id": hex32,
"site_id": tstr,
"segment_number": uint64-decimal,
"commitment_profile_id": vtl-commitment-profile-id,
"disclosure_class": disclosure-class,
"artifacts": artifacts,
"anchoring": anchoring,
? "extensions": { * tstr => json-data },
}
artifacts = {
"segment_cbor": artifact-ref,
? "predecessor_segment_cbor": artifact-ref,
? "records": [* artifact-ref],
? "segment_ots": artifact-ref,
? "segment_ots_meta": artifact-ref,
? "peer_attest": 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": "present" / "pending"
}
verifier-result-v2 = {
"version": 2,
"artifact_sha256": hex64,
"manifest_sha256": hex64,
? "commitment_profile_id": tstr,
"claimed_disclosure_class": disclosure-class,
"verification_scope":
"public_recompute" / "partial_verification" / "anchor_only",
? "chain_status": chain-status,
"channels": channels,
? "verifier_policy_id": tstr,
? "verifier_policy_sha256": hex64,
"overall": "success" / "partial" / "failure",
? "failure_reasons": [+ baseline-failure-reason],
? "extensions": { * tstr => json-data }
}
chain-status =
"epoch" /
"validated" /
"predecessor_not_disclosed" /
"failed"
baseline-failure-reason =
"unsupported_commitment_profile" /
"commitment_mismatch" /
"segment_chain_mismatch" /
"channel_failure" /
"insufficient_disclosure" /
"scope_not_exercised" /
"verifier_policy_rejection"
channels = {
? "tsa": verifier-channel-result,
? "ots": verifier-channel-result,
? "peer": verifier-channel-result,
* extension-channel-name => verifier-channel-result
}
extension-channel-name = tstr
verifier-channel-result = {
"status":
"verified" / "pending" / "missing" /
"failed" / "skipped",
? "validation_profile": tstr,
? "reason": tstr,
? "extensions": { * tstr => json-data }
}
disclosure-class = "A" / "B" / "C"
relative-path = tstr
uint64-decimal = tstr
hex32 = (tstr .regexp "[0-9a-f]{32}") .size 32
hex64 = (tstr .regexp "[0-9a-f]{64}") .size 64
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.¶
The tstr shape for commitment_profile_id does not
relax its exact-value requirement: the field MUST equal the profile
UUID defined in Section 2.¶
segment-record-v2 = {
"version": 2,
"commitment_profile_id": tstr,
"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.¶