Verifiable Telemetry Ledgers
draft-elkhatabi-verifiable-telemetry-ledgers-11
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Bilal El Khatabi | ||
| Last updated | 2026-09-07 (Latest revision 2026-09-06) | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Reviews |
OPSDIR Early review
(of
-05)
by Joe Clarke
Has issues
|
||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-elkhatabi-verifiable-telemetry-ledgers-11
Independent Submission B. El Khatabi
Internet-Draft Independent
Intended status: Informational 6 September 2026
Expires: 10 March 2027
Verifiable Telemetry Ledgers
draft-elkhatabi-verifiable-telemetry-ledgers-11
Abstract
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 their admission into 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 artifact
digest through a required external timestamp channel. Segment
closure uses a deployment-configured elapsed-time interval and does
not depend on calendar dates.
The profile enables independent recomputation and audit of disclosed
evidence from the admitted bytes onward. Transport framing,
decryption, anti-replay processing, payload interpretation, and
source-telemetry-to-record mapping are outside it, as are device
onboarding, end-to-end security of sensor values, and safety
decisions.
Status of This Memo
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 10 March 2027.
El Khatabi Expires 10 March 2027 [Page 1]
Internet-Draft VTL September 2026
Copyright Notice
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.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Example: From Admission to Audit . . . . . . . . . . . . 4
1.2. Relationship to Existing Work . . . . . . . . . . . . . . 5
2. Conventions and Terminology . . . . . . . . . . . . . . . . . 6
3. System Roles . . . . . . . . . . . . . . . . . . . . . . . . 9
4. Data and Commitment Model . . . . . . . . . . . . . . . . . . 9
4.1. Canonical-Record Input Boundary . . . . . . . . . . . . . 9
4.2. Deterministic CBOR Commitment Encoding . . . . . . . . . 12
4.3. Deterministic Commitment Tree Calculation . . . . . . . . 12
4.4. Segment Formation and Closure . . . . . . . . . . . . . . 13
4.4.1. Normal Interval Timing and Admission . . . . . . . . 13
4.4.2. Policy Changes and Early Closure . . . . . . . . . . 14
4.4.3. Limits and Close-Reason Selection . . . . . . . . . . 15
4.4.4. Empty Intervals and Timer Continuity . . . . . . . . 15
4.4.5. Recovery and Durable State . . . . . . . . . . . . . 16
4.4.6. Deterministic Aligned Batch Subtrees . . . . . . . . 17
4.5. Authoritative Segment Artifact Schema . . . . . . . . . . 17
4.6. Segment Chaining . . . . . . . . . . . . . . . . . . . . 19
5. Artifacts and Verification Bundles . . . . . . . . . . . . . 20
5.1. Producer Manifest . . . . . . . . . . . . . . . . . . . . 20
5.2. Verifier Result . . . . . . . . . . . . . . . . . . . . . 21
5.3. Portable Artifact References and Binding . . . . . . . . 21
6. Anchoring and Verification . . . . . . . . . . . . . . . . . 21
6.1. Baseline Conformance . . . . . . . . . . . . . . . . . . 22
6.2. TSA Channel Status Vocabulary . . . . . . . . . . . . . . 22
6.3. Anchoring Contract . . . . . . . . . . . . . . . . . . . 23
6.4. Baseline TSA Channel . . . . . . . . . . . . . . . . . . 23
6.5. Verification . . . . . . . . . . . . . . . . . . . . . . 25
6.5.1. Inputs and Scope . . . . . . . . . . . . . . . . . . 26
6.5.2. Verification Procedure . . . . . . . . . . . . . . . 27
6.5.3. Batch-Subtree Validation . . . . . . . . . . . . . . 28
6.5.4. Disclosed Canonical-Record Validation . . . . . . . . 29
6.5.5. Failure Reasons . . . . . . . . . . . . . . . . . . . 29
6.5.6. Overall Outcome . . . . . . . . . . . . . . . . . . . 30
6.5.7. Chain-Claim Composition . . . . . . . . . . . . . . . 32
El Khatabi Expires 10 March 2027 [Page 2]
Internet-Draft VTL September 2026
7. Disclosure Classes . . . . . . . . . . . . . . . . . . . . . 32
8. Versioning . . . . . . . . . . . . . . . . . . . . . . . . . 34
9. Conformance Vectors . . . . . . . . . . . . . . . . . . . . . 35
10. Operational Considerations . . . . . . . . . . . . . . . . . 36
10.1. Operational Signals and Deployment . . . . . . . . . . . 36
11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 37
12. Security Considerations . . . . . . . . . . . . . . . . . . . 38
12.1. Artifact and Bundle Integrity . . . . . . . . . . . . . 38
12.2. Producer, Sequence, and Lifecycle Threats . . . . . . . 39
12.3. TSA Trust and Algorithm Lifetime . . . . . . . . . . . . 40
12.4. Resource Exhaustion . . . . . . . . . . . . . . . . . . 41
12.5. Verification Scope, Disclosure, and Privacy . . . . . . 41
12.6. Extension Boundaries . . . . . . . . . . . . . . . . . . 42
13. References . . . . . . . . . . . . . . . . . . . . . . . . . 42
13.1. Normative References . . . . . . . . . . . . . . . . . . 42
13.2. Informative References . . . . . . . . . . . . . . . . . 43
Appendix A. Compact Commitment Known-Answer Vectors . . . . . . 44
Appendix B. Producer Manifest and Verifier Result CDDL . . . . . 47
Appendix C. Authoritative Segment Artifact CDDL . . . . . . . . 50
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 51
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 51
1. Introduction
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
much 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 the timestamp artifacts are mutually consistent. This profile
standardizes the second question only.
This memo is an Independent Submission. It is not an Internet
Standard and has not been evaluated as having IETF community
consensus.
Segment intervals are ledger batching rules, not source-reporting
periods or civil-time claims. Segment membership follows admission
into intervals governed by a non-decreasing elapsed-time source;
timestamps carried in records do not select membership
(Section 4.4.1).
El Khatabi Expires 10 March 2027 [Page 3]
Internet-Draft VTL September 2026
The profile boundary is admission of an already-formed canonical-
record byte string. This document specifies admission and the
subsequent commitment, disclosure, and verification of those bytes.
1.1. Example: From Admission to Audit
This informative example shows why the machinery in the rest of this
document exists. It is illustrative only; every rule it depends on
is specified normatively later.
A factory gateway admits sensor readings as canonical-record byte
strings throughout the day. At each interval boundary it fixes the
membership of a segment. It then hashes the exact admitted bytes,
sorts the resulting leaf hashes, computes a segment root, seals a
segment artifact naming the ledger, the segment's serial number, its
closure claim, and the digest of its predecessor, and submits SHA-256
over the artifact bytes to a Timestamp Authority.
Months later a customer disputes one shipment. For this example, the
disputed readings fall within two batches of a segment containing
several batches. The operator does not want to disclose all the
segment's telemetry, so it supplies a producer manifest, the segment
artifact, its predecessor artifact, the timestamp response, and any
request required for nonce correlation, along with complete openings
for those two batches. Because batches are slices of the sorted
leaf-hash list, those openings also disclose any unrelated records in
the same batches.
The auditor recomputes the two batch roots from the disclosed record
bytes, checks that the artifact's complete list of batch roots
composes to the committed segment root, confirms that the timestamp
token binds the exact artifact bytes, and validates the artifact's
link to its predecessor.
The auditor's result then says exactly that much: the two disclosed
batches were recomputed and matched, the artifact existed no later
than the timestamp under the auditor's stated policy, and the
predecessor link held. It claims nothing about the batches that were
not opened, nothing about whether the readings were true, and nothing
about whether other segments exist.
Disclosing some batches but not all is one of three disclosure levels
a producer can claim. They are defined normatively in Section 7; in
outline:
* *Class A* discloses everything needed to recompute the whole
segment.
El Khatabi Expires 10 March 2027 [Page 4]
Internet-Draft VTL September 2026
* *Class B* discloses complete selected batches, so a partner can
check that material against the commitment without seeing the
rest.
* *Class C* discloses the segment artifact without record openings;
successful verification requires valid timestamp evidence.
What a producer discloses and what a verifier actually checks are
separate throughout this document. A Class A bundle does not by
itself mean anyone performed full recomputation, and a successful
narrower check makes no claim about unopened records. Every verifier
result states the scope it exercised, and that scope bounds what the
result asserts.
1.2. Relationship to Existing Work
VTL reuses the Merkle Tree Hash construction of [RFC9162] to commit a
producer-local segment. It defines no Certificate Transparency log,
transparency service, public append-only log, statement-registration
protocol, receipt, inclusion or consistency proof, gossip protocol,
or log-auditing API. Unlike Certificate Transparency, VTL sorts leaf
hashes before reduction and so commits to a multiset rather than an
append-ordered sequence: the root is independent of admission order
and supports no append-order, prefix, or consistency claim between
partial snapshots. Chaining orders sealed artifacts, not records
within a segment.
The SCITT architecture in [RFC9943] defines signed statements,
registration with transparency services, and receipts; [RFC9052]
defines COSE signing and encryption structures. Neither is used by
the VTL baseline: the authoritative artifact is not a COSE object and
no producer signature is required. A separate specification can
publish or wrap VTL artifacts through either without altering the
rules defined here.
Profile Boundary
The following informative figure shows the profile boundary and the
artifact and timestamp flows used for baseline verification.
El Khatabi Expires 10 March 2027 [Page 5]
Internet-Draft VTL September 2026
Source telemetry
|
v
.----------------------------. OUTSIDE VTL
| Upstream admission system |
| auth, replay, projection |
'-------------+--------------'
| exact canonical-record bytes
==============+================================ profile boundary
v
.----------------------------. authoritative segment artifact
| Ledger producer +-------------------------------------.
| admit, assign, commit | |
| seal and chain | |
'-------------+--------------' |
| artifact digest |
v v
.-------------. .----------.
| TSA | | |
'------+------' | Verifier |
| | |
'----- timestamp artifact --------------->+ |
'----------'
Figure 1: VTL Profile Boundary and Processing Flow
2. Conventions and Terminology
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.
Upstream admission system: A component outside this profile that
authenticates, filters, decrypts, de-duplicates, interprets, or
maps source telemetry and produces a canonical-record byte string.
It can be colocated with the ledger producer.
Canonical-record byte string: The exact deterministic-CBOR byte
string presented at the profile boundary and admitted as one
commitment input. "Canonical" describes its byte encoding, not
its physical truth or upstream derivation.
Commitment profile: An immutable set of rules for validating
El Khatabi Expires 10 March 2027 [Page 6]
Internet-Draft VTL September 2026
canonical-record bytes and constructing commitment outputs,
selected by commitment_profile_id. This document assigns the
UUIDv4 c08ade4e-1785-4eb6-9648-b7003d76288d; identifier handling
is specified in Section 8.
Ledger: An ordered chain of segment artifacts identified by one
ledger_id. Segment numbers are scoped to that identifier.
Ledger epoch: The lifetime of one ledger sequence under one
ledger_id. Its first segment is number zero and carries the all-
zero predecessor value.
Segment: The multiset of canonical-record occurrences assigned to
one emitted interval. It can be empty when the profile permits
emission of an empty interval.
Admission linearization point: The serialization point at which one
exact record is accepted and assigned to the open interval. It is
not a wall-clock instant.
Boundary-logic resolution: The smallest difference between elapsed-
time readings that the producer's interval-boundary logic can
distinguish.
Closed-unsealed interval: Internal producer state whose membership,
policy snapshot, close reason, counts, and serial allocation are
durably fixed but whose artifact is not yet durably persisted.
Authoritative segment artifact: The deterministic-CBOR record for
one emitted segment and the cryptographic source of truth for its
verification. It is referenced by artifacts.segment_cbor and is
also called the segment artifact.
Projection: Any non-authoritative representation derived from an
authoritative segment artifact.
Producer manifest: A non-authoritative JSON object that claims a
disclosure class and identifies disclosed artifacts, their
digests, and producer timestamp state.
Verifier result: The verifier-authored output reporting exercised
scope, chain conclusion, TSA channel status, overall outcome, and
failure reasons. It is neither a commitment input nor a producer
claim.
Evidence bundle: The producer manifest and disclosed artifacts
presented to a verifier as one unit.
El Khatabi Expires 10 March 2027 [Page 7]
Internet-Draft VTL September 2026
Bundle root: The single logical container relative to which every
manifest path is resolved. It can be a directory, archive,
object-store prefix, or equivalent closed namespace.
Safe resolver: A resolver that confines every consumed object to the
bundle root and prevents substitution between resolution and
consumption.
Disclosure class: The level of artifact disclosure claimed by the
producer, as defined in Section 7.
Verification scope: The validation boundaries a verifier actually
exercised and asserts in its result.
Verifier policy: The complete identified set of local inputs
governing scope, TSA trust and validation, resource limits, and
other policy decisions.
Primary-input boundary: The point at which the verifier-result
contract begins, as defined in Section 6.5.1.
Bundle-processing error: A rejection before the primary-input
boundary. This document defines no verifier-result object for it.
Baseline producer: A producer claiming the conformance defined in
Section 6.1.
Baseline verifier: A verifier claiming the conformance defined in
Section 6.1.
Baseline TSA channel: The mandatory timestamp channel defined in
Section 6.4. Its verifier-result key is tsa.
Timestamp Authority (TSA): An authority that issues timestamp
responses over submitted digests.
Timestamp artifacts: The exact TimeStampResp and any disclosed
supporting TimeStampReq.
Batch subtrees and batch openings are defined where they are
specified, in Section 4.4.6 and Section 5.1.
El Khatabi Expires 10 March 2027 [Page 8]
Internet-Draft VTL September 2026
3. System Roles
These roles participate at different sides of the profile boundary;
conformance is defined in Section 6.1. The *upstream admission
system* produces canonical-record byte strings after deployment-
specific source validation and mapping and is outside this profile.
The *ledger producer* accepts those exact byte strings at the profile
boundary, assigns them to serial-numbered segments, constructs
segment artifacts, and submits their digests for timestamping; one
physical gateway can implement both roles, but conformance begins
only at the byte-level handoff. The *verifier* recomputes
commitments and validates timestamp artifacts from disclosed bundles.
The *Timestamp Authority* issues timestamp responses over artifact
digests.
4. Data and Commitment Model
The input to this section is an exact canonical-record byte string
already produced by an upstream admission system. This section
covers admission, segment assignment, deterministic hashing and tree
calculation, segment formation, artifact construction, and chaining.
4.1. Canonical-Record Input Boundary
The profile input is one exact canonical-record byte string. It MUST
encode exactly one CBOR data item using the record shape below and
the deterministic encoding constraints in Section 4.2, and a ledger
producer MUST reject an input that does not satisfy those byte-level
constraints.
El Khatabi Expires 10 March 2027 [Page 9]
Internet-Draft VTL September 2026
A baseline producer MUST accept every conforming canonical-record
byte string whose total encoded length is no greater than 4096 octets
and whose payload nesting depth is no greater than 16. Payload
nesting depth is zero when payload is a scalar; each array or map on
a path beginning at payload increases depth by one, the payload depth
is the maximum over all such paths, and the outer seven-element
record array is not counted. A producer MAY accept conforming
records outside this shared acceptance envelope under its documented
resource policy, but a configured maximum below either dimension does
not satisfy baseline producer conformance. These are minimum
acceptance capabilities for bounded-resource interoperability, not
protocol maxima, and the octet value is not derived from a network
MTU. A record outside the envelope is not thereby nonconforming, but
a producer that admits one can produce bundles a conforming baseline
verifier rejects under identified policy. An implementation MAY
validate a byte string incrementally, but admission applies to one
complete byte string encoding exactly one canonical record; an
upstream system MAY instead produce multiple independently conforming
records, each a separate admitted occurrence, which this profile does
not treat as chunks of one record.
Once admitted, the exact supplied octets are authoritative. The
producer MUST use those octets, without modification, as the leaf
preimage under Section 4.3, and MUST NOT decode and re-encode,
normalize, enrich, remove, reorder, or otherwise substitute a
different byte string. Each admission event contributes one record
occurrence, including when two occurrences have identical byte
strings. Source transport, framing, authentication, decryption,
anti-replay processing, duplicate-submission policy, identifier and
message-type mapping, payload interpretation, and construction of the
byte string are upstream of this boundary and are neither specified
nor verified here; a physical gateway MAY perform those functions and
ledger production together, but its interoperability claim begins
only with the exact byte string passed across this boundary.
Each canonical-record byte string encodes the following fixed seven-
element CBOR array:
El Khatabi Expires 10 March 2027 [Page 10]
Internet-Draft VTL September 2026
canonical-record = [
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 ; Finite only; deterministic rules follow.
The positional labels are conventional names for inspecting disclosed
records and do not move source-to-record mapping into this profile.
version is the unsigned integer 1; device_id is an opaque 8-octet
identifier assigned upstream; fc is an unsigned upstream-supplied
sequence value with no replay or duplicate-suppression semantics
defined here; ingest_time is an unsigned count of whole non-leap
seconds since 1970-01-01T00:00:00Z and device_time is an unsigned
application timestamp or null whose epoch and unit are upstream
semantics. Neither value selects segment membership; kind is an
unsigned application discriminator; and payload is one recursively
restricted CBOR data item whose schema and meaning are outside this
profile.
Canonical-record identity is exact-octet identity, not numeric or
application-level equality. Within payload the integer 1 and the
floating-point value 1.0 are distinct, as are positive and negative
floating-point zero, whose shortest exact encodings are respectively
f90000 and f98000; a producer or verifier MUST NOT normalize negative
zero to positive zero or convert between an integer and a numerically
equal floating-point value. A different record array shape or byte-
level field type is a different commitment profile and requires a
distinct commitment_profile_id. Application schemas MAY separately
define field meanings, but successful verification does not validate
those external semantics.
El Khatabi Expires 10 March 2027 [Page 11]
Internet-Draft VTL September 2026
4.2. Deterministic CBOR Commitment Encoding
Commitment bytes MUST satisfy the core deterministic-encoding
requirements of Section 4.2.1 of [RFC8949]. Items MUST use definite-
length encoding; integers and finite floating-point values MUST use
their shortest exact encodings; and map keys MUST be ordered in the
bytewise lexicographic order of their deterministic encodings.
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, including
negative floating-point zero. The exact type, sign, and encoded-
octet distinctions in Section 4.1 are preserved by admission and
verification.
Because this profile permits only text-string map keys in their
preferred deterministic encodings, bytewise ordering of their encoded
heads orders them first by UTF-8 byte length and then by encoded
bytes, coinciding with the length-first order of Section 4.2.3 of
[RFC8949].
JSON projections are optional, 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.
Unless a rule explicitly says otherwise, every digest in this
document is computed over the exact received or disclosed octets, and
an implementation MUST NOT re-encode, normalize, or reserialize input
before hashing.
4.3. Deterministic Commitment Tree Calculation
For a given segment, this 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 [FIPS180-4];
[RFC6234] provides informative implementation descriptions and test
material.
Every SHA-256 invocation in this profile MUST produce the complete
32-octet digest; a truncated digest or a different SHA-2 function is
nonconformant. For tree hashing an implementation MUST use exactly
the 0x00 leaf prefix and 0x01 internal-node prefix and MUST NOT add,
omit, or substitute another tree-domain prefix.
El Khatabi Expires 10 March 2027 [Page 12]
Internet-Draft VTL September 2026
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 lexicographic (bytewise) order. The
authoritative artifact represents hash values as CBOR byte strings;
hexadecimal renderings in this document are for human-readable
vectors only.
Let VTLRoot(L) operate on the sorted list of already-computed leaf
hashes. VTLRoot([]) = SHA-256("") and VTLRoot([x]) = x. For a list
of n > 1 hashes, let k be the largest power of two strictly less than
n, and compute VTLRoot(L) = SHA-256(0x01 || VTLRoot(L[0:k]) ||
VTLRoot(L[k:n])). Implementations MUST NOT duplicate an unpaired
final hash. The prefixes provide leaf/parent domain separation, and
the recursive split gives every leaf count a unique tree shape.
For an emitted empty segment, record_count MUST be zero, batch_roots
MUST be an empty array, and segment_root MUST equal VTLRoot([]), the
SHA-256 digest of zero bytes:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.
For a non-empty segment, record_count MUST be positive and
batch_roots MUST contain at least one root.
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. Producer
conformance requires sorting the complete segment leaf multiset
before batching; verification of that global sort rule is complete
only under the public_recompute scope, and weaker scopes provide only
the ordering assurances defined for them in Section 6.5.3. Any
future change to this calculation that alters commitment bytes MUST
use a new commitment_profile_id.
4.4. Segment Formation and Closure
This section specifies how admitted records are assigned to logical
intervals, how those intervals close, how durable state survives
restart, and how the committed batch subtrees are derived.
4.4.1. Normal Interval Timing and Admission
Segment formation uses a non-decreasing producer elapsed-time source
that MUST progress during normal operation. Its boundary-logic
resolution MUST be no coarser than the smaller of 1000 milliseconds
and closure_policy.interval_ms; finer sampling is permitted. The
interval is a fixed positive uint64 millisecond duration and MUST NOT
be aligned to civil-time events. The first interval opens when the
producer durably activates the ledger, and reactivation resumes
durable state after shutdown. Every closure except shutdown opens
El Khatabi Expires 10 March 2027 [Page 13]
Internet-Draft VTL September 2026
the next interval immediately. Intervals continue across idle
periods; suppress affects emission and serial consumption, not the
elapsed schedule.
The producer MUST serialize the interval-boundary transition with the
admission linearization point so that each admitted input has exactly
one segment assignment. For an interval whose elapsed-time deadline
is T: a record whose acceptance linearizes before T belongs to the
current interval; at T or later the producer MUST process the
boundary before another acceptance can linearize, so a record
admitted at or after T belongs to the next interval even when its
upstream processing began earlier. Source arrival time, upstream
validation or record-construction time, device_time, and ingest_time
MUST NOT override this assignment.
Processing the boundary means completing the durable close transition
in Section 4.4.5, not sorting leaves, encoding or persisting the
artifact, submitting its digest, or obtaining a response. Deadline
expiry MUST use checked elapsed-time subtraction, not potentially
wrapping addition, and an unsafe elapsed-time comparison MUST invoke
recovery before another record is accepted.
4.4.2. Policy Changes and Early Closure
The producer MUST keep the opening-time closure_policy snapshot
unchanged through closure. A policy update that can wait applies to
the next interval. A reconfiguration request that is to take effect
before the current interval would otherwise close makes the
reconfigure condition true. The producer MUST close the current
interval under its old snapshot before applying the change. When
another condition is also true, Section 4.4.3 selects the committed
reason. Early closure is permitted only for its committed reason.
Late processing MUST NOT move a post-deadline admission into the
expired interval and SHOULD emit an operational signal as described
in Section 10.1.
The manual condition is true only when closure is requested through a
producer-provided administrative interface that is not driven by
elapsed-time, record_limit, or size_limit_bytes evaluation. The
producer MUST NOT select manual without such a request. Whether a
human operator or automation acting through that interface initiated
it does not change the condition. The request MUST be serialized
with admission and close under the current snapshot; the committed
reason follows Section 4.4.3 when multiple conditions are true. A
manual closure opens a successor and empty emission follows
empty_mode. shutdown closes for orderly cessation, MUST NOT open a
successor until reactivation, and MUST emit and consume a serial even
for an empty suppress interval.
El Khatabi Expires 10 March 2027 [Page 14]
Internet-Draft VTL September 2026
4.4.3. Limits and Close-Reason Selection
interval applies at the snapshotted deadline when no higher condition
applies. A non-null record_limit is the maximum admitted count; on
reaching it the producer MUST close the interval before another
acceptance can linearize. A non-null size_limit_bytes is a close
threshold for the summed admitted-record lengths; at or above it the
producer MUST close before another acceptance. The triggering record
remains assigned, so the field is not a pre-admission maximum and a
single oversized record forms a one-record interval. Byte-count
updates and comparisons MUST use checked arithmetic; before
acknowledging an unrepresentable total the producer MUST enter
recovery or stop acceptance.
If multiple close conditions are simultaneously true, the committed
close_reason MUST be selected by the following precedence, numbered
from highest to lowest. The selected reason does not change which
acceptances already linearized into the interval.
1. recovery
2. shutdown
3. reconfigure
4. manual
5. size_limit
6. record_limit
7. interval
4.4.4. Empty Intervals and Timer Continuity
With timer continuity, emit produces an artifact for every interval,
using the empty construction when needed. An empty suppress interval
emits nothing and consumes no serial, except that shutdown and
recovery always emit and consume one. The next artifact remains
contiguous. Suppression makes no completeness or no-event claim.
A host suspend interval counts toward the current logical interval
when the producer's elapsed-time source advances across the suspend.
When it does not, or when elapsed-time-source continuity is otherwise
uncertain, recovery MUST precede another acceptance.
El Khatabi Expires 10 March 2027 [Page 15]
Internet-Draft VTL September 2026
4.4.5. Recovery and Durable State
Before post-restart or failover acceptance, the producer MUST recover
ledger identity, next serial, policy, open state, and the ordered
closed-unsealed queue. It MUST NOT infer an uncertain boundary from
wall time; it MUST instead stop or close recoverable open material as
recovery, and that closure MUST emit and consume a serial, including
when empty under suppress. The producer MUST NOT synthesize missed
historical empty artifacts. A previously fixed close reason MUST
survive recovery; recovery applies only when the interval remained
open or its open state was uncertain at failure.
Admission is a durable transaction boundary: before acknowledgment
the producer MUST atomically make the exact record, membership,
counts, and recovery state durable or recoverable, and after a crash
an acceptance MUST be recovered exactly once in the same interval or
MUST be treated as never completed. The producer MUST serialize
close with admission. The close transition MUST atomically preserve
an emitting interval's exact membership, policy, reason, counts,
allocated serial, and ordered closed-unsealed state, and except at
shutdown MUST also make the successor state recoverable before an
admission to that successor is acknowledged. A suppressed empty
interval creates neither queue entry nor serial, except for the
shutdown and recovery cases above.
After close, successor admission and commitment preparation MAY
proceed while intervals remain unsealed. Artifacts MUST be finalized
durably in serial order with the exact predecessor and digest
available for each non-epoch artifact; sealing MUST NOT alter fixed
membership, policy, reason, counts, or serial, and MUST atomically
preserve the artifact, digest, queue advancement, and timestamp-
submission obligation, after which submission and response
acquisition can be asynchronous. Open, closed-unsealed, and merely
locally queued states have no conforming manifest: only an attempted
submission can be pending, a usable response is present, a terminal
attempt without one is unavailable, and a local job alone MUST NOT be
represented as pending.
Outstanding state MUST have finite recoverable capacity. Before
acknowledging an admission that would exceed it the producer MUST
apply backpressure or stop acceptance, and before lifecycle closures
exhaust it the producer MUST drain or shut down. Loss of exact
closed-unsealed state MUST stop acceptance under that ledger; a new
epoch is permitted, but the producer MUST NOT skip, reuse, or
fabricate material for the affected old-ledger serial. These are
observable outcomes, not mandated storage calls.
El Khatabi Expires 10 March 2027 [Page 16]
Internet-Draft VTL September 2026
4.4.6. Deterministic Aligned Batch Subtrees
A batch is not a chronological admission chunk. It is a consecutive
slice of the complete globally sorted leaf-hash list, formed only
after segment membership is fixed.
For a non-empty interval, compute the complete sorted leaf-hash list
defined in Section 4.3 and partition it into consecutive batches of B
= closure_policy.batch_record_limit hashes. B MUST be a positive
power of two no greater than 2^63. Batch zero contains the first B
hashes, batch one the next, and so on; only the last batch can
contain fewer than B. Compute each batch_roots[i] as VTLRoot over
that batch's already-computed leaf hashes. This is the sole baseline
batch partitioning rule and is independent of storage flushes, worker
scheduling, or input-file layout. An implementation MAY obtain the
required global leaf order through an order-maintaining index or
external sort and reduce each aligned batch incrementally, but
sorting tentative input chunks or batches independently is not
equivalent and MUST NOT replace the global sort; every optimization
MUST reproduce the exact commitment and artifact bytes defined here.
Requiring a power of two makes every full batch align with a
recursive VTLRoot split, so an aligned batch root can substitute
directly for its subtree without an auxiliary sibling path.
Let N be record_count. For N > 0 the number of batch roots MUST be 1
+ ((N - 1) / B) using integer division. To compose a range root from
those aligned roots, return the sole supplied root when the range
contains at most B leaves; otherwise let k be the largest power of
two strictly less than the range's leaf count, which is a batch
boundary because B is a power of two, recursively compose the roots
before and after that boundary, and return SHA-256(0x01 || left ||
right). The result MUST equal segment_root. This is subtree
substitution under the VTLRoot recursion in Sections 2.1.1 and 2.1.2
of [RFC9162]; it does not define a Certificate Transparency log or CT
wire object.
4.5. Authoritative Segment Artifact Schema
The segment artifact is a deterministic CBOR-encoded segment record
produced under Section 4.2 and 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, and is not a transport envelope, publication
statement, or complete verification claim. A JSON projection,
filename, and storage path are non-authoritative, and a verifier MUST
NOT trust a path or filename as the segment number. The artifact is
interpreted only under its in-band commitment_profile_id: because
that identifier is inside the artifact bytes, a valid timestamp token
El Khatabi Expires 10 March 2027 [Page 17]
Internet-Draft VTL September 2026
over its digest binds the commitment semantics. Profile dispatch
follows Section 8.
The segment record contains exactly these fields:
* version (uint): segment-record schema version, exactly 1.
* commitment_profile_id (tstr): a lowercase RFC 9562 UUID string.
* ledger_id (tstr): exactly 32 lowercase hexadecimal characters.
* segment_number (uint): serial number in the range 0..(2^64-1).
* closure_policy (map): the immutable segment closure policy
snapshot, containing exactly version equal to 1; positive uint64
interval_ms; power-of-two uint64 batch_record_limit no greater
than 2^63; 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 (bstr): 32-octet SHA-256 digest of the exact
bytes of the previous segment artifact, or the epoch predecessor
value in Section 4.6.
* record_count (uint): number of canonical-record occurrences
committed by the segment.
* batch_roots (array of bstr): ordered aligned-subtree roots, each
exactly 32 octets; empty for an empty emitted segment.
* segment_root (bstr): 32-octet deterministic segment root.
When record_count is zero, closure_policy.empty_mode MUST be emit
unless close_reason is shutdown or recovery, the mandatory lifecycle
artifacts that retain a committed suppress value; any other empty
artifact under suppress is invalid. Array position is the batch
number: the root at position i MUST commit the consecutive sorted-
leaf range beginning at i * batch_record_limit, with root count,
final-batch width, and composed segment root derived as in
Section 4.4.6.
A verifier MUST validate that the producer manifest segment_number is
the shortest unsigned decimal form defined in Appendix B, parse it as
a uint64, and compare that numeric value with the decoded CBOR uint.
A non-shortest decimal form is a manifest schema violation and
therefore a bundle-processing error; after a valid parse, a numeric
mismatch with the artifact is commitment_mismatch. The artifact uses
the registered application/cbor media type when media-type metadata
is carried, and implementations SHOULD use application/
vnd.vtl.segment+cbor once registered. Media-type metadata does not
determine artifact conformance or profile selection.
El Khatabi Expires 10 March 2027 [Page 18]
Internet-Draft VTL September 2026
4.6. Segment Chaining
Segment identity and chaining are defined within one stable ledger_id
and do not depend on UTC dates or elapsed idle time.
* The epoch segment MUST have segment_number equal to 0 and
prev_segment_sha256 equal to a 32-octet all-zero byte string.
* Every non-epoch segment MUST have a serial number exactly one
greater than its predecessor, MUST retain the same ledger_id and
commitment_profile_id, and MUST set prev_segment_sha256 to SHA-256
over the exact bytes of the predecessor's segment artifact.
* A producer MUST NOT reuse, skip, or wrap segment_number. Before
serial exhaustion it MUST stop the ledger and start a new one with
a new ledger_id.
* Configuration rollback follows these same transition rules and
MUST NOT mutate sealed artifacts, reuse a serial, or conceal a
chain discontinuity. A closure-policy change MUST take effect
only in a newly opened logical interval and does not reset
segment_number or ledger_id.
When a new ledger epoch begins, the producer MUST generate a new
ledger_id so that the probability of collision with any other ledger
identifier is negligible; a uniformly random 128-bit value from a
cryptographically strong random source satisfies this. If durable
sequence state cannot be recovered unambiguously, a producer MUST
stop acceptance or begin a new ledger with a fresh identifier and
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 segment artifacts MUST validate serial
continuity, exact commitment_profile_id equality, and predecessor-
digest linkage. A profile mismatch is a segment_chain_mismatch. A
partial disclosure omitting the predecessor can still support
validation of the disclosed artifact and its timestamp artifacts, but
the verifier MUST report chain_status as predecessor_not_disclosed.
El Khatabi Expires 10 March 2027 [Page 19]
Internet-Draft VTL September 2026
5. Artifacts and Verification Bundles
A deployment can store canonical records, segment artifacts, producer
manifests, verifier results, and timestamp artifacts in any 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 bundle claiming a disclosure
class MUST disclose the segment artifact and a producer manifest.
5.1. Producer Manifest
The producer manifest repeats the ledger identity, segment number,
commitment profile, claimed disclosure class, artifact digests, and
claimed producer timestamp state; the artifact's in-band
commitment_profile_id remains the cryptographically bound one. The
manifest MUST NOT contain a chain conclusion, verifier status,
failure reason, or overall outcome. Its schema is in Appendix B and
its shape per claimed class in Section 7. It uses application/json,
and application/vnd.vtl.manifest+json once registered, on the same
terms as the segment artifact. Deployment-specific data can be
carried only in explicit extension containers, whose presence MUST
NOT alter the semantics defined here, select an additional evidence
channel, or affect the baseline outcome.
For a non-epoch segment, a predecessor is disclosed for baseline
verification if and only if artifacts.predecessor_segment_cbor is
present and its referenced bytes are safely resolved; an extension
member or out-of-band artifact does not substitute for it or change
chain_status.
A _batch opening_ is an artifacts.record_batches entry disclosing
every canonical-record occurrence committed by the aligned batch
subtree identified by its batch_number, permitting recomputation of
that indexed root without disclosing other batches. Each nested
records entry represents one admitted occurrence. Duplicate entries
are permitted and MUST be counted separately; occurrences with
identical bytes MAY reference the same disclosed artifact and a
verifier MAY reuse a successful digest computation, but the leaf hash
MUST contribute once per listed occurrence, and reference order does
not assert admission order. An opening MUST disclose exactly the
number of occurrences derived for that batch from record_count and
batch_record_limit, and after hashing and sorting those exact octets
their VTLRoot value MUST equal the indexed batch_roots value.
Producer timestamp state is present when the response is disclosed,
pending when issuance was initiated but has not reached a terminal
state, and unavailable when issuance terminated without a usable
response; manifests MUST NOT use verifier states such as verified or
El Khatabi Expires 10 March 2027 [Page 20]
Internet-Draft VTL September 2026
failed. A pending or unavailable state MUST omit tsa_tsr and a
present state MUST reference it. When a disclosed response contains
a nonce the manifest MUST also reference tsa_req; producer
obligations for a nonce-bearing request are in Section 6.4.
5.2. Verifier Result
Verification under Section 6.5 produces a logical verifier result.
Only that result states the exercised scope, any chain conclusion,
TSA channel status, verifier-policy identifier, overall outcome, and
failure reasons; local diagnostics 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 claiming conformance MUST use the schema in
Appendix B and the application/json media type.
5.3. Portable Artifact References and Binding
Every path-bearing object consumed during verification, including a
manifest artifact reference or an extension object, MUST satisfy this
subsection. Each path is a UTF-8 string interpreted relative to the
bundle root, using / as the only separator. A path MUST be non-
empty, MUST NOT begin with /, \, or a drive-letter prefix, and 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 ... Verifiers MUST resolve and open every consumed path
through a safe resolver. These are semantic requirements and do not
depend on a regular-expression dialect or operating-system pathname
behavior.
Every artifact listed in the manifest MUST carry a lowercase
hexadecimal SHA-256 digest entry. The manifest's ledger_id,
segment_number, and commitment_profile_id MUST match the
corresponding artifact fields whenever those fields can be decoded;
segment-number comparison follows Section 4.5 and profile selection
follows Section 8. Failure mapping for unsafe or digest-mismatched
references is given once, in Section 6.5.5.
6. Anchoring and Verification
This section defines baseline conformance, the required timestamp
channel, verification inputs and scopes, and the result reduction
rules.
El Khatabi Expires 10 March 2027 [Page 21]
Internet-Draft VTL September 2026
6.1. Baseline Conformance
A baseline producer MUST emit the fixed commitment_profile_id defined
here, construct segment artifacts and producer manifests under this
profile, and initiate timestamp submission through the baseline TSA
channel for every emitted segment. Issuance MAY remain pending while
incomplete.
A baseline verifier MUST implement this commitment profile and the
baseline TSA channel, obtain the profile identifier from the segment
artifact, and use the result vocabulary and fixed TSA channel key
defined here. Every result claiming baseline conformance MUST
contain the tsa channel key, including when its status is
pending_claim, missing, or failed, and a baseline success result
requires successful timestamp validation.
A baseline verifier MUST configure finite resource limits for
variable-length primary and secondary inputs, decoded collections,
record and batch counts, certificate counts, and parser recursion.
Its canonical-record length and depth limits MUST admit the shared
acceptance envelope in Section 4.1. This document defines no
mandatory acceptance floor for the other dimensions. Rejection
before the primary-input boundary is a bundle-processing error;
rejection after it solely because an otherwise valid input exceeds
identified policy uses verifier_policy_rejection.
Extension data is opaque to baseline producers and verifiers, and its
presence, absence, or contents MUST NOT change a baseline channel
status or overall outcome. A separate specification can define an
additional evidence mechanism without changing the segment artifact
or this commitment profile.
6.2. TSA Channel Status Vocabulary
Verifier results MUST use exactly this vocabulary for the TSA
channel: verified, timestamp validation succeeded for the disclosed
artifact binding; pending_claim, the manifest claims submission was
attempted but no terminal response is disclosed, an incomplete
producer claim rather than an independently verified fact; missing,
an expected response is absent or is referenced but cannot be safely
resolved; and failed, validation was attempted and did not succeed.
Producer state pending maps deterministically to pending_claim and
unavailable maps to missing. Baseline verification does not
authenticate the claim or change its status based on elapsed time,
manifest provenance, receipt context, or other out-of-band inputs; a
later bundle disclosing a terminal response is a different fixed-byte
input. Outcome effects are in Section 6.5.6.
El Khatabi Expires 10 March 2027 [Page 22]
Internet-Draft VTL September 2026
The TSA-result reason value is human-readable diagnostic text.
producer_pending_claim is the only baseline machine-defined token;
any other value is free text and MUST NOT be interpreted as a
portable machine-actionable code. A pending_claim result MUST set
reason to producer_pending_claim; a missing or failed result MUST
include a free-text reason; a verified result MUST NOT include one.
Additional machine-readable detail MAY be placed in the channel
result's extensions member and is opaque to baseline verification.
6.3. Anchoring Contract
A producer computes the SHA-256 digest of the segment artifact and
submits it through the baseline TSA channel; verifiers MUST recompute
that digest over the exact artifact bytes. Timestamp validation and
message-imprint comparison do not depend on successful CBOR decoding
of the artifact. A token that validates with the artifact digest as
its message imprint binds the complete artifact bytes, including the
in-band commitment_profile_id, but binds no disclosure class,
producer manifest, verifier policy, or verifier result.
Consequently, a manifest received over an unauthenticated channel can
under-claim the available disclosure as Class C, omit record
openings, or direct the verifier to a different valid artifact.
Manifest digest checks establish consistency with the received
manifest, not its provenance. A relying party needing those
properties MUST obtain the authoritative artifact bytes or their
expected digest independently through an authenticated mechanism and
rerun verification from those bytes.
The producer MUST seal and durably write the segment artifact without
waiting for issuance completion. Alternative timestamping or
attestation mechanisms require a separate specification and do not
alter this baseline contract.
6.4. Baseline TSA Channel
This channel uses the timestamp protocol of [RFC3161], as updated by
[RFC5816] and restricted here. The TimeStampReq, TimeStampResp, and
token MUST conform to those specifications, and the token MUST
contain exactly one CMS SignerInfo as defined by [RFC5652]. These
restrictions define a narrower channel than generic use of that
protocol, so a conforming implementation cannot assume an arbitrary
deployed TSA is compatible; deployments SHOULD prequalify a TSA
before relying on it.
The producer MUST set TimeStampReq.messageImprint.hashAlgorithm to
SHA-256 and its hashedMessage to the exact 32-octet result of SHA-256
over the segment artifact bytes, MUST NOT hash that result again, and
El Khatabi Expires 10 March 2027 [Page 23]
Internet-Draft VTL September 2026
MUST set certReq to TRUE. A successful TimeStampResp.status.status
MUST be granted (0); a verifier MUST reject grantedWithMods (1), and
a producer receiving it MUST treat the terminal attempt as
unavailable and MUST NOT publish that response as usable baseline
evidence.
The signed attributes MUST contain exactly one SigningCertificateV2
attribute with exactly one value, as defined by [RFC5035], whose
first ESSCertIDv2.certHash MUST equal SHA-256 over the complete DER
encoding of the selected signer certificate; a present hashAlgorithm
MUST identify SHA-256, omission denoting that default, and a present
issuerSerial MUST identify that same certificate. The signed
attributes MUST NOT contain the legacy SigningCertificate attribute
of [RFC2634]. Because certReq is TRUE, SignedData.certificates MUST
contain exactly one X.509 certificate matching both SignerInfo.sid
and that first ESSCertIDv2; zero or multiple matches are a
verification failure. The set MAY also contain unrelated or path
certificates, and a verifier MUST NOT rewrite a received response or
reject it merely for containing additional nonmatching certificates.
A baseline verifier MUST NOT report this channel as verified unless
its identified verifier policy supplies accepted trust anchors,
accepted TSA policy identifiers, revocation policy including
acceptable evidence and the treatment of historical certificate
status at TSTInfo.genTime, acceptable signature and certificate
algorithms and strengths, any additional generation-time constraints,
a maximum acceptable future skew, and the verifier-local time source
used for that check. This document defines no long-term archival-PKI
validation profile beyond those inputs. Missing policy input after
the primary-input boundary is verifier_policy_rejection; if the
identified time source is unavailable at runtime, validation fails,
the channel status is failed, and the result includes
channel_failure.
artifacts.tsa_tsr carries the exact DER-encoded TimeStampResp. A
verifier MUST validate those exact referenced bytes, MUST NOT re-
encode the response before any digest or channel check, and MUST
recompute the segment artifact digest. Validation MUST include:
* response status granted (0) and required token presence;
* the CMS id-signedData and id-ct-TSTInfo content types;
* exact SHA-256 message-imprint equality with the recomputed digest;
* the CMS signature, signed attributes, and unambiguous signer-
certificate binding;
* the signer certificate's single critical extended-key-usage
extension containing only id-kp-timeStamping;
* path validation under [RFC5280] using TSTInfo.genTime as the date/
time input and configured trust anchors;
El Khatabi Expires 10 March 2027 [Page 24]
Internet-Draft VTL September 2026
* configured TSA policy and certificate-validation constraints;
* a genTime within the signer certificate's validity interval; and
* the configured maximum future skew.
The optional artifacts.tsa_req carries the exact DER-encoded
TimeStampReq as a non-authoritative supporting artifact. A producer
sending a nonce-bearing request MUST retain those exact bytes at
least as long as the corresponding response, MUST disclose the
request with that response, and MUST NOT treat a response that omits
or changes its nonce as successful issuance. Whenever tsa_req is
disclosed the verifier MUST validate its SHA-256 digest, require the
request message-imprint algorithm to be SHA-256 and its hashedMessage
to equal the recomputed artifact digest, and require certReq=TRUE.
If either disclosed object contains a nonce, both MUST contain one
and the values MUST be equal. A nonce-bearing response without
tsa_req, a nonce present in only one object, unequal nonces, or any
failure of these checks is a timestamp-channel verification failure
reported with channel_failure. If the response carries no nonce and
tsa_req is not disclosed, a verifier cannot determine whether the
original request contained one and the result makes no nonce-
correlation claim. Any failure of the validations in this section is
a timestamp-channel verification failure; the channel status MUST be
verified on success and failed on failure.
6.5. Verification
Verification addresses four distinct questions. The verifier result
identifies the selected scope, reports chain and timestamp status,
and combines applicable checks into an overall outcome.
Artifact validity:
Do the exact disclosed bytes decode as a segment artifact under a
supported commitment profile, with internally consistent counts,
batch roots, and segment root?
Record recomputation:
Do the disclosed occurrences reproduce their indexed batch roots?
Under public recomputation, does the complete globally sorted
record multiset also reproduce the segment root?
Chain continuity:
Does an epoch artifact carry the required initial values, or are
the artifact's serial number and predecessor digest consistent
with a disclosed predecessor?
Timestamp validation:
Does a timestamp token bind the exact artifact bytes under the
identified verifier policy?
El Khatabi Expires 10 March 2027 [Page 25]
Internet-Draft VTL September 2026
These conclusions must be distinguished. An artifact that fails to
decode can still carry a valid timestamp over its bytes, and a valid
timestamp establishes nothing about record contents. Verification
therefore begins at the primary-input boundary, selects one exercised
scope, applies the validations that scope supports, and reduces the
resulting conclusions to the verifier-result schema. The subsections
below fix the inputs and scope selection (Section 6.5.1), the order
in which validations are applied (Section 6.5.2), the structural and
record-level checks themselves (Section 6.5.3 and Section 6.5.4), and
how conclusions reduce to one outcome (Section 6.5.5 and
Section 6.5.6).
6.5.1. Inputs and Scope
The verifier-result contract applies only after the verifier has
obtained the exact producer-manifest bytes, fully parsed them as a
UTF-8 JSON producer manifest, applied every structural, lexical, and
manifest-only cross-field check that does not depend on the segment
artifact, determined every mandatory result field and the exact
artifacts.segment_cbor reference, and obtained the exact referenced
artifact bytes. Failure to obtain either primary input, structurally
invalid manifest bytes, a missing primary artifact reference, or
unsafe resolution of either primary input is a bundle-processing
error, which a verifier MUST reject but for which it MUST NOT emit a
verifier result; it is outside the result schema and is not an
insufficient_disclosure conclusion. Structurally invalid manifest
bytes include present without tsa_tsr, pending or unavailable with
tsa_tsr, and a missing, negative, non-integer, non-shortest, or
uint64-overflowing segment_number or batch_number; a configured
resource limit preventing the verifier from reaching the boundary
likewise produces one. After artifact decoding, duplicate or out-of-
range batch-opening numbers yield insufficient_disclosure.
Verifiers MUST then decode the artifact and determine the applicable
commitment_profile_id from its in-band field, applying the dispatch
precedence in Section 8. When that field decodes as a text string
the result's optional commitment_profile_id MUST echo its exact
value, including when unsupported. The identifier is the semantic
key for interpreting the artifact: a structurally well-formed
artifact and successful timestamp validation are insufficient for
semantic verification when it is absent or unsupported. When the
exact artifact bytes are present but do not decode as a valid segment
artifact, the result MUST be failure and include
invalid_segment_artifact; the verifier MUST still evaluate the TSA
channel independently over those exact bytes, and decoding failure
alone MUST NOT cause channel status failed or channel_failure.
El Khatabi Expires 10 March 2027 [Page 26]
Internet-Draft VTL September 2026
The manifest's disclosure_class is the producer-claimed class and the
result's claimed_disclosure_class MUST repeat it. The result's
verification_scope identifies the scope selected for the invocation:
public_recompute corresponds to Class A, disclosed_batch_recompute to
Class B, and anchor_only to Class C, ordered from strongest to
weakest. After satisfying the primary-input boundary the invocation
MUST select an intended scope; selection does not assert support,
which the verifier determines after artifact decoding and claimed-
class shape validation, and earlier fail-fast termination still
reports the selected scope without claiming it succeeded. The
claimed class determines manifest shape; the selected scope
determines which artifacts are consumed and which recomputation
claims are made. Results MUST NOT claim assurances outside the
exercised scope, and exercising a stronger scope does not rewrite the
claimed class. A verifier exercising anchor_only MUST NOT consume
record_batches, even when valid claimed-class shape requires those
entries to be present, and MUST NOT claim record-level or batch-
opening recomputation.
The result's manifest_sha256 MUST equal SHA-256 over the UTF-8 octets
of the validated manifest, and artifact_sha256 MUST equal SHA-256
over the referenced bytes of artifacts.segment_cbor, both under the
exact-octet rule in Section 4.2, with artifact_sha256 present even
when those bytes are malformed. These fields identify the validated
inputs and do not authenticate the result. The verifier MUST always
compare the recomputed artifact digest with
artifacts.segment_cbor.sha256, which checks manifest self-consistency
only and MUST NOT be counted as a timestamp binding, and MUST
likewise verify the sha256 value of every other manifest reference
consumed. A verifier MAY reuse one successful digest computation for
repeated references to the same bytes; duplicate occurrences
nevertheless contribute once per listed occurrence.
6.5.2. Verification Procedure
A verifier MUST perform every applicable validation required by the
sections referenced below. It SHOULD apply them in the fail-fast
order shown. This list summarizes ordering and does not create
requirements beyond those referenced sections.
1. Manifest shape against the claimed disclosure class (Section 7).
Claimed-class requirements do not determine which valid openings
a weaker selected scope consumes.
2. Segment artifact and manifest, including repeated identity fields
and the digest of every manifest reference consumed in later
steps (Section 6.5.1, Section 5.3).
El Khatabi Expires 10 March 2027 [Page 27]
Internet-Draft VTL September 2026
3. Chain status: serial zero and the zero predecessor for an epoch
segment, or ledger identity, exact commitment-profile identity,
contiguous serials, and prev_segment_sha256 against a disclosed
predecessor (Section 4.6).
4. Structural batch validations for every scope, including
record_count, the power-of-two batch limit, batch-root
cardinality, and composition of batch_roots into segment_root
(Section 6.5.3).
5. Scope-specific record and opening validation for public_recompute
or disclosed_batch_recompute, including independent recomputation
of segment_root under the stronger scope (Section 6.5.3,
Section 6.5.4).
6. Comparison of the recomputed artifact digest with the response's
messageImprint.hashedMessage, whether or not decoding succeeded;
a mismatch is a timestamp-channel verification failure, and a
producer pending claim lacks the external binding and yields
pending_claim.
7. Timestamp response validation and channel status (Section 6.4).
A referenced response that is unavailable is missing; one whose
validation is attempted and does not succeed is failed.
6.5.3. Batch-Subtree Validation
Verifiers MUST apply the structural validations below before
accepting any scope. Manifest-shape validation follows the claimed
class; opening validation follows the selected scope.
* batch_record_limit is a power of two in the permitted range;
* the number of 32-octet batch_roots values equals the value derived
from record_count and batch_record_limit, including the empty-
segment case;
* when record_count is zero, closure_policy.empty_mode is emit, or
close_reason is shutdown or recovery;
* when record_count is greater than zero, composition of the ordered
aligned subtree roots equals the authoritative segment_root; for
an empty segment the empty-root rule in Section 4.3 applies;
* for claimed-class shape, batch-opening numbers are unique and in
range and record_batches matches Section 7;
* for public_recompute, every disclosed opening is consumed,
contains exactly its derived number of occurrences, and has sorted
recomputed leaves that reduce to the indexed batch root, and the
globally sorted multiset of every disclosed occurrence reduces
independently to segment_root;
* for disclosed_batch_recompute, every opening selected for
consumption is complete and reduces to its indexed root, and the
selected batch numbers form a non-empty proper subset of the
authoritative batches; and
El Khatabi Expires 10 March 2027 [Page 28]
Internet-Draft VTL September 2026
* when consumed openings for batch numbers i and i+1 are both
disclosed, the greatest leaf hash in batch i is less than or equal
to the least leaf hash in batch i+1.
The adjacent-opening comparison is required under either recompute
scope whenever the relevant pair is consumed. A successful
disclosed_batch_recompute result verifies the global sort rule only
at those consumed boundaries, and Class C verifies no leaf-order
boundary. A later public_recompute result exposing a global ordering
violation MUST be failure with commitment_mismatch.
6.5.4. Disclosed Canonical-Record Validation
A verifier exercising public_recompute or disclosed_batch_recompute
MUST validate every record artifact consumed under that scope as one
exact canonical-record byte string before using it as a leaf
preimage. The verifier MUST use the exact disclosed artifact bytes
and MUST NOT reconstruct a record from source telemetry. The bytes
MUST contain exactly one CBOR data item with no trailing data, MUST
have the seven-element array shape and field constraints in
Section 4.1, and MUST satisfy the deterministic encoding, text-only
map-key, duplicate-key, UTF-8, tag, finite floating-point, and
permitted-value rules in Section 4.2 at every recursive payload
level, including the restricted payload shape.
The verifier MUST hash the exact validated octets. If consumed bytes
violate any canonical-record rule the result MUST be failure with
invalid_canonical_record, even when those bytes hash to the leaf
value the producer committed; if a separately observed record digest,
batch root, segment root, artifact digest, or binding also
mismatches, the result MUST additionally include commitment_mismatch.
A baseline verifier exercising either scope MUST accept every
conforming disclosed canonical-record artifact consumed under that
scope that lies within the shared acceptance envelope of Section 4.1.
It MAY accept conforming records outside that envelope under
identified policy. A conforming record outside the envelope is not
an invalid_canonical_record; rejection after the primary-input
boundary is verifier_policy_rejection.
6.5.5. Failure Reasons
A result whose overall value is failure MUST contain one or more
machine-usable failure_reasons drawn only from the categories below.
A category MUST NOT occur more than once in one result, and failure
reasons MUST be absent when overall is success or incomplete.
Deployment-specific detail belongs in extensions; this document
creates no extension namespace for failure-reason values. A missing
El Khatabi Expires 10 March 2027 [Page 29]
Internet-Draft VTL September 2026
primary segment artifact is a bundle-processing error, not a failure
reason.
unsupported_commitment_profile: The in-band profile identifier is
present but unsupported.
invalid_canonical_record: A disclosed canonical-record byte string
violates the required record shape, field constraints, restricted
payload model, or deterministic CBOR profile.
invalid_segment_artifact: Present artifact bytes are malformed or
violate the required artifact syntax or cross-field rules.
commitment_mismatch: Commitment material, including a manifest/
artifact identity field, record digest, batch, Merkle root, or
artifact digest, does not validate. A safely resolved reference
whose bytes fail their declared digest uses this category.
segment_chain_mismatch: A disclosed predecessor cannot be safely
resolved or fails ledger identity, commitment-profile identity,
serial-continuity, or predecessor-digest validation. The
accompanying chain_status is failed.
channel_failure: The timestamp response is missing, invalid, or
otherwise unacceptable, or its binding to the artifact digest
fails. An absent or unsafely referenced response is reported with
channel status missing and this category.
insufficient_disclosure: The disclosed artifacts do not support the
claimed class or asserted scope. This includes a required batch
opening or record artifact that is absent or cannot be safely
resolved.
scope_not_exercised: The inputs support a stronger scope required by
identified policy, but the verifier intentionally exercised a
weaker one.
verifier_policy_rejection: The inputs do not satisfy an applicable
local verifier policy for a reason not more specifically
represented above.
6.5.6. Overall Outcome
A chain_status of predecessor_not_disclosed does not by itself
degrade the outcome; it makes no chain-adjacency claim. The
following reduction is normative and total after the primary-input
boundary has been satisfied and the exercised scope and identified
verifier policy have been fixed. A verifier MUST evaluate every
applicable failure condition and include every distinct failure
reason it reaches; multiple failure conditions can apply to one
invocation, and the two terminal conditions apply only when no
failure condition applies. Extension data is not a channel and MUST
NOT affect this evaluation.
El Khatabi Expires 10 March 2027 [Page 30]
Internet-Draft VTL September 2026
+=================================+=================================+
| Condition | Required effect |
+=================================+=================================+
| The in-band profile | Add |
| identifier is a well-formed | unsupported_commitment_profile. |
| but unsupported UUID. | |
+---------------------------------+---------------------------------+
| After the primary-input | Add verifier_policy_rejection. |
| boundary, an otherwise valid | |
| input or required validation | |
| is rejected solely by | |
| identified verifier policy, | |
| including a configured | |
| resource limit or missing | |
| required policy input. | |
+---------------------------------+---------------------------------+
| The verifier intentionally | Add scope_not_exercised. |
| exercises a weaker supported | |
| scope when identified policy | |
| requires the stronger scope. | |
+---------------------------------+---------------------------------+
| A required structural, | Add every applicable baseline |
| commitment, chain, | failure category. |
| disclosure, artifact- | |
| reference, canonical-record, | |
| or other non-channel | |
| validation fails. | |
+---------------------------------+---------------------------------+
| The baseline TSA channel is | Add channel_failure. |
| failed or missing. | |
+---------------------------------+---------------------------------+
| One or more failure reasons | Set overall to failure. |
| were added above. | |
+---------------------------------+---------------------------------+
| No failure condition applies | Set overall to incomplete; |
| and the channel is | failure_reasons absent. |
| pending_claim. | |
+---------------------------------+---------------------------------+
| No failure condition applies | Set overall to success; |
| and the channel is verified. | failure_reasons absent. |
+---------------------------------+---------------------------------+
Table 1: Overall Outcome Reduction
El Khatabi Expires 10 March 2027 [Page 31]
Internet-Draft VTL September 2026
Exercising a weaker supported scope has no independent outcome effect
when identified policy does not require the stronger scope, though
the selected scope still limits the result's claims. A bundle-
processing error produces no result and does not enter this
reduction.
Every result MUST include a non-empty verifier_policy_id that stably
identifies the complete policy applied to the invocation within the
issuing verifier's namespace, and the same issuing verifier MUST NOT
reuse one identifier for materially different policies. That policy
includes trust anchors, accepted TSA policy identifiers, revocation
policy, algorithm constraints, and generation-time and future-skew
constraints, and baseline pending-claim reduction does not depend on
it or on out-of-band context. When exact bytes of a corresponding
policy artifact are available the result MUST include
verifier_policy_sha256 computed over those exact bytes; otherwise
that member MAY be absent, and a bare digest is not sufficient policy
identification. Verifier output MUST NOT be represented as proving
more than the exercised scope.
6.5.7. Chain-Claim Composition
A manifest and its verifier result cover one segment artifact. A
relying party claiming continuous chaining across a disclosed range
MUST have one validated manifest/result pair for every segment in
that range. Every pair MUST carry the same ledger_id and
commitment_profile_id under their applicable exact-comparison rules,
and segment numbers MUST be contiguous. The first result MUST have
chain_status equal to epoch, or to validated after validation against
its disclosed predecessor, and every later result MUST have
validated. A gap, identity mismatch, failed link, or unavailable
required predecessor prevents a continuous-range claim. Successful
composition establishes continuity only across that range; it does
not establish global dataset completeness or the absence of
undisclosed ledgers.
7. Disclosure Classes
Verification claims depend on what is disclosed. This section is the
single normative statement of manifest shape per claimed class. The
producer claims one class in the manifest; the verifier independently
reports the scope selected for its invocation (Section 6.5.1).
El Khatabi Expires 10 March 2027 [Page 32]
Internet-Draft VTL September 2026
+===============+=======================+===========================+
| Class | Required | Supported scope |
| | record_batches | |
| | shape | |
+===============+=======================+===========================+
| A (Public | Non-empty segment: | public_recompute or |
| Recompute) | MUST open every | anchor_only; |
| | batch exactly once, | disclosed_batch_recompute |
| | with all record | only when the artifact |
| | artifacts needed to | contains at least two |
| | recompute the | batches |
| | claimed segment | |
| | root. Empty | |
| | segment: MUST omit. | |
+---------------+-----------------------+---------------------------+
| B (Partner | MUST open a non- | disclosed_batch_recompute |
| Audit) | empty proper subset | or weaker |
| | of a non-empty | |
| | segment's batches, | |
| | each opening | |
| | complete. Empty | |
| | and single-batch | |
| | segments cannot | |
| | support Class B. | |
+---------------+-----------------------+---------------------------+
| C (Anchor- | MUST omit. | anchor_only |
| Only) | | |
+---------------+-----------------------+---------------------------+
Table 2: Disclosure Classes and Manifest Shape
The disclosed_batch_recompute scope is supported only when the
authoritative artifact contains at least two batches and the verifier
consumes a non-empty proper subset of them. Selecting that scope for
an empty or single-batch segment MUST produce failure with
insufficient_disclosure; a verifier can instead select anchor_only.
Every bundle MUST include the segment artifact, the producer
manifest, and the tsa member in anchoring, with the response
disclosed when the producer state is present. An emitted empty
segment MAY be disclosed as Class A or Class C and MUST NOT be
disclosed as Class B; both omit record_batches, and the claimed class
and exercised scope distinguish an empty public recomputation from
anchor-only verification.
A Class A manifest claims disclosure sufficient for public_recompute;
it does not claim that a verifier exercised that scope. A missing
required opening or record artifact yields insufficient_disclosure.
El Khatabi Expires 10 March 2027 [Page 33]
Internet-Draft VTL September 2026
A successful public_recompute result additionally requires complete
record and root recomputation; unsupported profiles, invalid records,
and digest or commitment failures use their separately defined
reasons. Class B outputs MUST NOT be represented as publicly
recomputable; a Class B bundle MAY include a policy artifact
describing withheld material, and a verifier exercising
disclosed_batch_recompute makes no claim about unopened batch
preimages. Every scope composes the complete authoritative
batch_roots list into segment_root. Class C does not mean without
leaf hashes: a singleton batch root equals its unsalted leaf hash, so
Class C is not a confidentiality guarantee for low-entropy records.
A Class C disclosure MUST be labeled as such and MUST NOT claim
record-level reproducibility.
This caveat applies to every successful result: VTL establishes
internal consistency and timestamp binding for the disclosed bundle,
not completeness of observed or emitted telemetry, physical truth,
omitted device lifecycle state, or authorization for autonomous
action.
8. Versioning
A document revision does not select commitment semantics, and schema
version fields identify only individual object shapes; neither
substitutes for commitment_profile_id. This document defines one
shape each for the canonical record, segment record, closure policy,
producer manifest, and verifier result, so their CDDL rule names
carry no version suffix. The first four carry a local version value
of 1; an incompatible change to one of them MUST increment that value
and a parser MUST reject an unsupported one, but that needs a new
commitment identifier only if commitment semantics also change. The
verifier result carries no version member: it is verifier-authored
output rather than a producer-supplied input, and the
verifier_policy_id required by Section 6.5.6 already identifies the
rules under which it was produced. A consumer MUST interpret a
verifier result under the member semantics defined in Appendix B and
MUST NOT infer them from a version member, a media type, a filename,
storage, or carriage; none of these are dispatch inputs.
This document defines one randomly generated UUIDv4
commitment_profile_id and requests no registry for it (Section 11).
Baseline producers MUST emit exactly that UUID, and verifiers MUST
apply dispatch in this order:
1. a missing or non-text identifier, or a text value that is not a
well-formed lowercase RFC 9562 UUID, is an
invalid_segment_artifact;
El Khatabi Expires 10 March 2027 [Page 34]
Internet-Draft VTL September 2026
2. a well-formed lowercase UUID the verifier does not support is an
unsupported_commitment_profile, and MUST NOT be classified as
invalid_segment_artifact solely because it differs from this
document's UUID; and
3. exact string equality with this document's UUID selects the
semantics defined here.
A verifier encountering an unsupported well-formed UUID MUST report
unsupported_commitment_profile rather than applying fallback
semantics. The identifier selects the canonical-record syntax
(Section 4.1), deterministic byte encoding (Section 4.2), tree
calculation (Section 4.3), aligned-subtree calculation
(Section 4.4.6), artifact bytes (Section 4.5), and chain-link
calculation (Section 4.6). It does not select minimum-size
capability, output-preserving scheduling or persistence, media
registration or carriage, manifest or result schemas, or external
evidence profiles, and implementations MUST NOT infer commitment
semantics from those properties, a filename, a manifest, an informal
name, or identifier parsing. No namespace for additional values is
defined.
A selected-semantic change MUST use a new identifier and ledger
epoch; an excluded, output-preserving change does not, and the UUID
MUST NOT be rebound. A verifier with policy knowledge of conflicting
semantics MUST NOT use this profile and MUST report
verifier_policy_rejection. A future profile MUST publish a distinct
UUID and begin a new epoch with a fresh ledger_id, serial zero, and
the all-zero predecessor; producers MUST NOT link across profiles or
relabel, re-encode, or reinterpret sealed artifacts. Rollout SHOULD
preserve historical verification support and rollback MUST begin
another new epoch. A baseline chain claim cannot cross a profile
boundary; associating epochs requires a separately authenticated
statement that is not a VTL commitment input. Until RFC publication
the identifier binding is provisional and artifacts make only an
experimental Internet-Draft conformance claim. If the selected
commitment semantics change before publication, the changed profile
MUST use a new UUID. Publication can retain this UUID only if those
selected semantics remain unchanged.
9. Conformance Vectors
This section is informative. Appendix A supplies the normative
commitment known-answer vectors: exact record bytes and numeric
distinctions, leaf hashes, aligned batch roots, a segment root and
artifact, empty lifecycle closure, and duplicate occurrences. It
does not supply a complete protocol test suite or timestamp-response
fixtures; a non-normative machine-readable corpus maintained with the
draft source can carry the larger and malformed cases.
El Khatabi Expires 10 March 2027 [Page 35]
Internet-Draft VTL September 2026
A positive suite ought to cover:
* a 4096-octet record at payload depth 16 and a conforming record at
depth 17 outside the mandatory envelope;
* linked and empty segments, varied and duplicate leaf counts, and a
five-leaf, three-batch recursive composition;
* boundary ordering, close-reason precedence, recovery, profile
migration, ordered closed-unsealed queues, and backpressure;
* Classes A through C, deliberate down-scoping, every outcome
condition, and unsupported profiles; and
* one nonce-bearing valid request and response satisfying
Section 6.4.
A negative suite ought to cover:
* primary-input rejection and identity, record, boundary, policy,
serial, predecessor, tree, batch, opening, and single-batch
faults;
* sorting performed only within tentative batches;
* lost or relabeled closed state, omitted mandatory empty shutdown
or recovery artifacts, and out-of-order sealing;
* invalid timestamp-state and reference combinations, unsafe
references, malformed-versus-unsupported profile classification,
and locally queued work represented as pending; and
* imprint, nonce, token, attribute, and certificate violations,
including grantedWithMods, multiple SignerInfo values, and the
legacy SigningCertificate attribute.
Cross-implementation checks verify byte parity across at least two
implementations. The normative vector's interval_ms value of
86400000 is an elapsed duration retained for vector continuity and
implies no civil-day, time-zone, daylight-saving, or leap-second
alignment.
10. Operational Considerations
10.1. Operational Signals and Deployment
This section follows [RFC5706] and is guidance; the normative rules
are in the sections referenced. Deployments SHOULD expose admission,
sealing, submission, issuance completion, and verification as
distinct states so delayed issuance is not confused with a malformed
artifact, and SHOULD emit structured signals with stable event codes
for handoff and durability failures, ledger identity and serial
conflicts, elapsed-timer health and closure delay, artifact writes
and roots, TSA backlog and per-segment status, and storage pressure.
Deployments SHOULD document the supported record size and depth,
admission backpressure, closure policy, retention, accepted TSA
El Khatabi Expires 10 March 2027 [Page 36]
Internet-Draft VTL September 2026
identities and policies, generation-time and skew constraints,
verifier policy, and whether reconfiguration can request application
before the current interval would otherwise close; and SHOULD
periodically verify a recent representative bundle, alerting on
failures and on issuance pending beyond policy. Before first
admission an operator SHOULD durably provision a fresh ledger_id,
configure verifier policy and TSA trust inputs, and prequalify the
TSA against Section 6.4. Long-lived deployments can use an external
renewal profile such as [RFC4998]. This document defines no
management data model, event-code registry, or management-protocol
binding.
For predictable bounded operation a deployment SHOULD configure at
least one of record_limit or size_limit_bytes, or enforce a finite
admission capacity with backpressure; capacity planning for
size_limit_bytes needs to accommodate the admitted record that
crosses the threshold. For N > 0 records and batch limit B the
artifact carries 1 + ((N - 1) / B) roots, each costing 34 CBOR
octets, so 100000 records with B = 1024 produce 98 roots and about
3332 octets. Larger batches reduce artifact size but enlarge the
minimum Class B disclosure unit, and when a non-null record_limit is
no greater than batch_record_limit every segment formed under that
policy has at most one batch and cannot support Class B. Timestamp
request rate is one per emitted segment, so sealing and response
acquisition SHOULD be decoupled through finite recoverable state
sized on the maximum emission rate and the expected service outage
rather than on interval_ms alone. Verifiers SHOULD avoid resolving
artifacts outside the selected scope and MAY cache a successful
record digest for identical referenced bytes while counting every
disclosed occurrence separately.
11. IANA Considerations
This document has no IANA actions. The application/
vnd.vtl.segment+cbor and application/vnd.vtl.manifest+json media
types used by this profile are being registered independently of this
document under Section 3.2 of [RFC6838]; the vendor tree is used for
these project-specific VTL artifact and manifest formats, and this
Independent Submission requests no standards-tree registration.
Until those registrations complete, implementations use the
registered generic application/cbor and application/json types as
specified in Section 4.5 and Section 5.1. No specialized media type
is requested for verifier results, which use application/json.
This document also requests no CBOR tag, CoAP Content-Format, or IANA
registry for commitment_profile_id: the fixed identifier is a
randomly generated UUIDv4 under [RFC9562] and needs no central
allocation. The absence of a registry provides no discovery of
El Khatabi Expires 10 March 2027 [Page 37]
Internet-Draft VTL September 2026
conflicting third-party semantic bindings, a residual issue addressed
in Section 12.1; a future registry requires a separate specification
defining its registration policy. The explicit statement of no IANA
actions follows [RFC8126].
12. Security Considerations
This profile introduces no new cryptographic primitives. Its
security depends on a byte-preserving handoff, deterministic
commitment encoding, trustworthy admission and elapsed-time handling,
accurate verifier reporting, and disciplined artifact and timestamp
handling, and assumes the collision and second-preimage resistance of
SHA-256 and the soundness of the [RFC9162] construction as
specialized here. Threats are stated in the style of [RFC3552].
Unless stated otherwise, success establishes only internal
consistency with this profile and successful timestamp validation.
The specialization sorts leaf hashes before reduction and so commits
to a multiset rather than an ordered list. Because mapping a
multiset of leaf hashes, including occurrence counts, to its
ascending sorted list is injective, distinct multisets yield distinct
ordered inputs and the collision-resistance argument of [RFC9162]
applies unchanged. The 0x00 leaf and 0x01 parent prefixes preserve
domain separation and prevent a leaf hash from being reinterpreted as
an internal node without finding a collision.
12.1. Artifact and Bundle Integrity
The formats contain no executable content or intrinsic compression
but provide no confidentiality. A manifest directs a verifier to
bundle-relative paths, creating traversal, indirection, and
substitution risks; verifiers MUST use the safe resolver in
Section 5.3, because a pathname check followed by an independent open
is unsafe. A timestamp over the artifact authenticates neither the
manifest nor the result.
El Khatabi Expires 10 March 2027 [Page 38]
Internet-Draft VTL September 2026
An attacker can exploit differences in CBOR validation, re-encoding,
occurrence handling, or tree composition, or present metadata that
does not match the artifact; fixed syntax and encoding, exact-octet
hashing, the in-band profile binding, and identity comparison
mitigate these. With no profile registry there is no discovery
mechanism for a third party assigning different commitment semantics
to the same UUID, so verifiers obtain mappings from identified policy
and deployments accepting unoperated producers SHOULD pin the
expected identifier. Independent artifact-digest recomputation
detects mutation or substitution, but bare leaves and roots omit
ledger, serial, and profile identity, so identical multisets produce
identical roots across ledgers: a verifier or relying party MUST NOT
substitute a bare leaf, batch root, or segment_root for
authoritative-artifact and external-binding validation.
12.2. Producer, Sequence, and Lifecycle Threats
An attacker or failed multi-writer deployment can reuse or roll back
a serial, emit conflicting artifacts, substitute a predecessor, or
disclose only a chain fragment. Fresh ledger identity, fencing,
contiguous serials, and predecessor-digest validation detect
conflicts when the relevant artifacts are disclosed but do not prove
global completeness. A ledger_id must remain unique while evidence
can be compared, whereas predictability of segment_number is a
required consequence of serial contiguity; operators SHOULD audit
identifier generation and alert on reuse of a ledger or ledger/serial
pair.
A compromised producer or upstream handoff can fabricate, suppress,
substitute, replay, or misassign byte strings. VTL makes outputs
tamper-evident only after commitment; upstream transport,
credentials, decryption, mapping, and parsing are outside this
document, and successful verification MUST NOT be reported as
validating those properties. Each admission is a distinct
occurrence, so a replay is indistinguishable here from a genuine
repeated observation, and successful verification of a false record
can make it durably and independently recomputable: a relying party
MUST NOT treat a successful result as corroboration of the recorded
value.
An attacker can alter the interval, elapsed-time source, policy,
close reason, or boundary processing. Committing the snapshot and
reason makes the producer claim tamper-evident after sealing but does
not prove honest elapsed time or the event that caused closure; a
verifier cannot distinguish an honest manual or reconfigure claim
from another asserted close reason. False upstream UTC values remain
false admitted values, and UTC changes MUST NOT affect membership or
reopen a sealed segment. A closed-unsealed interval has no artifact
El Khatabi Expires 10 March 2027 [Page 39]
Internet-Draft VTL September 2026
or external binding, so compromise or loss of that state before
sealing can block finalization of every later artifact in the chain;
durable close state, ordered sealing, finite recoverable queues, and
backpressure limit accidental loss but do not make that state
externally tamper-evident. An operator MUST NOT represent such state
as a sealed segment or a locally queued timestamp job as initiated
issuance.
12.3. TSA Trust and Algorithm Lifetime
This profile defines no producer signing key. The TSA is the only
signing authority in the baseline and signs an artifact digest rather
than attesting the producer's identity or the truth of producer
claims; deployments requiring producer attribution MUST obtain it
outside this profile.
An attacker can delay or withhold responses, present pending
placeholders as final, or exploit ignored missing responses; the
status vocabulary and outcome reduction constrain these cases. An
incomplete outcome contains no validated external binding and is the
outcome an adversary can induce by suppressing a response, so a
relying party MUST NOT treat incomplete as equivalent to success and
SHOULD reverify from a later bundle disclosing a terminal response.
Successful validation depends on the TSA key and trust anchors: a key
holder can mint a well-formed token over any digest and asserted
genTime. Validation proves only that bound bytes existed no later
than the asserted time under identified policy; it proves neither
producer nor source identity, nor when the segment opened. A nonce-
free response disclosed without tsa_req provides no nonce-correlation
assurance.
The identified verifier policy controls acceptable signature and key
strength; this profile sets no additional universal strength floor.
That policy MUST define later-compromise reevaluation, acceptable
historical revocation evidence, and whether a retired trust anchor
remains acceptable for a token at its TSTInfo.genTime, and a verifier
MUST NOT report verified unless the selected path and anchor are
acceptable under the policy identified in that result. Relying
parties comparing results from different verifiers therefore need to
compare policy identifiers and, when present, policy digests.
SHA-256 is embedded in every commitment in this profile. Retiring it
requires a new commitment profile, and Section 8 requires that
profile to begin a new epoch with a fresh ledger_id and serial zero.
No VTL commitment links the terminated chain to its successor;
association requires a separately authenticated statement.
Deployments whose retention horizon can exceed the acceptable service
life of SHA-256 MUST plan how pre-migration evidence remains
El Khatabi Expires 10 March 2027 [Page 40]
Internet-Draft VTL September 2026
verifiable and how the epoch boundary is authenticated. An external
renewal profile such as [RFC4998] can support long-term preservation
but is not defined here.
12.4. Resource Exhaustion
Producers need input-size limits, rate controls, finite recoverable
queues, and backpressure, with the normative rules in Section 4.4.5.
Verifiers need finite limits on encoded lengths, collection and
certificate counts, and recursion, with baseline requirements and
failure mapping in Section 6.1 and Section 6.5.6. Limits need
checking before unbounded allocation or recursion, and arithmetic
needs to be checked. A limit preventing acquisition or sufficient
parsing before the primary-input boundary produces no result; after
that boundary, rejection of an otherwise valid input solely for an
identified policy limit reports verifier_policy_rejection. Because
this document sets acceptance floors only for canonical-record length
and depth, two conforming verifiers can differ on inputs exceeding
their other limits. These controls reduce exposure but are not a
complete denial-of-service defense.
12.5. Verification Scope, Disclosure, and Privacy
Success can be misread as completeness, physical truth, or
authorization; the caveat in Section 7 applies to every result and
stronger claims require external controls. Class B establishes
sorting only within consumed openings and across consumed adjacent
boundaries and anchor-only establishes none, so a later Class A
disclosure can reveal a global-sort violation without contradicting
an earlier narrower result. Likewise a segment with a non-conforming
record can verify under anchor_only but MUST fail with
invalid_canonical_record under any later scope consuming that record.
Leaf hashes are unsalted and a singleton batch root is exactly its
leaf hash, which occurs for every batch when batch_record_limit is
one and for the final batch whenever the record count modulo the
batch limit is one; even a Class C artifact can therefore disclose
individual unsalted leaf hashes, and disclosed low-entropy material
permits offline guessing, since omitting record preimages does not
omit leaf hashes. A high-entropy application-layer nonce can help
but is outside this profile. Because batches are contiguous sorted
slices, an opening bounds earlier and later unopened hashes and
openings on both sides bound the intervening range, so deployments
SHOULD minimize the number and sorted-order spread of openings.
Identical segment_root values reveal identical multisets and MUST be
considered when roots cross privacy domains.
El Khatabi Expires 10 March 2027 [Page 41]
Internet-Draft VTL September 2026
Even without payloads, manifests, artifacts, and timestamp artifacts
reveal counts, layout, outage windows, delay, intervals, close
reasons, and emission cadence, and repeated pseudonymous identifiers
can link records and enable re-identification. Operators SHOULD
minimize personal data, avoid unnecessary stable identifiers, assess
Class A linkability, and apply suitable access and retention
controls. Privacy-preserving disclosures MUST NOT be called publicly
recomputable unless Class A conditions are met.
12.6. Extension Boundaries
Separate specifications can define upstream admission, exported
bundle types, SCITT or COSE publication, other timestamping or
attestation, withheld-material disclosure, or other commitment
profiles; opaque extensions do not affect baseline results. A
separate disclosure specification can staple RFC 9162 paths or a
reduced-tree construction inspired by [RFC4998], whose objects are
not interchangeable with VTL batch roots. Any change to commitment
bytes or calculations requires a distinct commitment_profile_id.
13. References
13.1. Normative References
[FIPS180-4]
National Institute of Standards and Technology, "Secure
Hash Standard (SHS)", FIPS PUB 180-4,
DOI 10.6028/NIST.FIPS.180-4, August 2015,
<https://doi.org/10.6028/NIST.FIPS.180-4>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC2634] Hoffman, P., "Enhanced Security Services for S/MIME",
RFC 2634, DOI 10.17487/RFC2634, June 1999,
<https://www.rfc-editor.org/info/rfc2634>.
[RFC3161] Adams, C., Cain, P., Pinkas, D., and R. Zuccherato,
"Internet X.509 Public Key Infrastructure Time-Stamp
Protocol (TSP)", RFC 3161, DOI 10.17487/RFC3161, August
2001, <https://www.rfc-editor.org/rfc/rfc3161>.
[RFC5035] Schaad, J., "Enhanced Security Services (ESS) Update:
Adding CertID Algorithm Agility", RFC 5035,
DOI 10.17487/RFC5035, August 2007,
<https://www.rfc-editor.org/rfc/rfc5035>.
El Khatabi Expires 10 March 2027 [Page 42]
Internet-Draft VTL September 2026
[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
Housley, R., and T. Polk, "Internet X.509 Public Key
Infrastructure Certificate and Certificate Revocation List
(CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
<https://www.rfc-editor.org/rfc/rfc5280>.
[RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)", STD 70,
RFC 5652, DOI 10.17487/RFC5652, September 2009,
<https://www.rfc-editor.org/rfc/rfc5652>.
[RFC5816] Santesson, S. and N. Pope, "ESSCertIDv2 Update for RFC
3161", RFC 5816, DOI 10.17487/RFC5816, March 2010,
<https://www.rfc-editor.org/rfc/rfc5816>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8259] Bray, T., "The JavaScript Object Notation (JSON) Data
Interchange Format", STD 90, RFC 8259,
DOI 10.17487/RFC8259, December 2017,
<https://www.rfc-editor.org/rfc/rfc8259>.
[RFC8610] Bormann, C. and P. Hoffman, "Concise Data Definition
Language (CDDL): A Notational Convention to Express CBOR
and JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
June 2019, <https://www.rfc-editor.org/rfc/rfc8610>.
[RFC8949] Bormann, C. and P. Hoffman, "Concise Binary Object
Representation (CBOR)", STD 94, RFC 8949,
DOI 10.17487/RFC8949, December 2020,
<https://www.rfc-editor.org/rfc/rfc8949>.
[RFC9162] Laurie, B., Messeri, E., and R. Stradling, "Certificate
Transparency Version 2.0", RFC 9162, DOI 10.17487/RFC9162,
December 2021, <https://www.rfc-editor.org/rfc/rfc9162>.
[RFC9562] Davis, K., Peabody, B., and P. Leach, "Universally Unique
IDentifiers (UUIDs)", RFC 9562, DOI 10.17487/RFC9562, May
2024, <https://www.rfc-editor.org/info/rfc9562>.
13.2. Informative References
[RFC3552] Rescorla, E. and B. Korver, "Guidelines for Writing RFC
Text on Security Considerations", BCP 72, RFC 3552,
DOI 10.17487/RFC3552, July 2003,
<https://www.rfc-editor.org/rfc/rfc3552>.
El Khatabi Expires 10 March 2027 [Page 43]
Internet-Draft VTL September 2026
[RFC4998] Gondrom, T., Brandner, R., and U. Pordesch, "Evidence
Record Syntax (ERS)", RFC 4998, DOI 10.17487/RFC4998,
August 2007, <https://www.rfc-editor.org/info/rfc4998>.
[RFC5706] Harrington, D., "Guidelines for Considering Operations and
Management of New Protocols and Protocol Extensions",
RFC 5706, DOI 10.17487/RFC5706, November 2009,
<https://www.rfc-editor.org/info/rfc5706>.
[RFC6234] Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms
(SHA and SHA-based HMAC and HKDF)", RFC 6234,
DOI 10.17487/RFC6234, May 2011,
<https://www.rfc-editor.org/info/rfc6234>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013,
<https://www.rfc-editor.org/info/rfc6838>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>.
[RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON
Canonicalization Scheme (JCS)", RFC 8785,
DOI 10.17487/RFC8785, June 2020,
<https://www.rfc-editor.org/rfc/rfc8785>.
[RFC9052] Schaad, J., "CBOR Object Signing and Encryption (COSE):
Structures and Process", STD 96, RFC 9052,
DOI 10.17487/RFC9052, August 2022,
<https://www.rfc-editor.org/info/rfc9052>.
[RFC9943] Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande,
Y., and S. Lasker, "An Architecture for Trustworthy and
Transparent Digital Supply Chains", RFC 9943,
DOI 10.17487/RFC9943, June 2026,
<https://www.rfc-editor.org/info/rfc9943>.
Appendix A. Compact Commitment Known-Answer Vectors
Wrapped hexadecimal values in this appendix are presentation-only; a
verifier or implementer obtains each exact value by concatenating
adjacent lines without inserting whitespace.
El Khatabi Expires 10 March 2027 [Page 44]
Internet-Draft VTL September 2026
The following normative canonical-record vectors differ only in the
final payload item. They demonstrate that the integer 1, floating-
point 1.0, positive floating-point zero, and negative floating-point
zero retain distinct deterministic encodings and produce distinct
leaf hashes.
integer_1_record =
87014800000000000000010100f60001
integer_1_leaf =
61d6b5be58a51d90b833cc8f2558d3b0e30a0c41cae971a81a92596013ca4e5c
float_1_record =
87014800000000000000010100f600f93c00
float_1_leaf =
793c53c545002c8b872ff84d1f479c1243f36e4ba57dbc8b387ec52c47fe62df
positive_zero_record =
87014800000000000000010100f600f90000
positive_zero_leaf =
5cd7c34a8083929449188288272e339f87fe06f64738b2f8f84a2c317ee40c27
negative_zero_record =
87014800000000000000010100f600f98000
negative_zero_leaf =
a45dabed6caf13fe4901f9bd596325e65e13d006dbb1ec8f1180b671537ffccb
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 uses
segment_number = 0, and prev_segment_sha256 is a 32-octet all-zero
byte string. The segment uses batch_record_limit = 2 and carries two
aligned subtree roots.
segment_cbor is 462 octets and commits three leaves in two aligned
batch subtrees. segment_sha256 is SHA-256 over those exact
segment_cbor octets. It is the authoritative artifact digest
submitted through the baseline TSA channel and carried by a
successor's prev_segment_sha256; it is not an additional field
encoded in this artifact.
El Khatabi Expires 10 March 2027 [Page 45]
Internet-Draft VTL September 2026
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 =
aa6776657273696f6e01696c65646765725f6964782062376131643565343063
366634333865396137356462323763393666333161616b62617463685f726f6f
7473825820554491e4edf28061622396b83a870db4652211557127c664c6be1c
4ad66471ff5820b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70
e379e853796d266c636c6f73655f726561736f6e68696e74657276616c6c7265
636f72645f636f756e74036c7365676d656e745f726f6f745820bc6502552ed0
c515f58d1c632e54db37594042609b59838eb0d5b3d5842aa0546e636c6f7375
72655f706f6c696379a66776657273696f6e016a656d7074795f6d6f64656873
757070726573736b696e74657276616c5f6d731a05265c006c7265636f72645f
6c696d6974f67073697a655f6c696d69745f6279746573f67262617463685f72
65636f72645f6c696d6974026e7365676d656e745f6e756d6265720073707265
765f7365676d656e745f73686132353658200000000000000000000000000000
00000000000000000000000000000000000075636f6d6d69746d656e745f7072
6f66696c655f6964782463303861646534652d313738352d346562362d393634
382d623730303364373632383864
segment_sha256 =
2672cb72d5f06863110af1b30660c7e5ba495c0b2ce7d084b0436e010e99388d
three_identical_record_1_root =
05ddc48e556d67534bf7960a70209696ca9eeb6f18d5595358e7f4804ec87701
four_identical_record_1_root =
d5d26faa3f54d81d8173700a48d9286179c9d35685d464183a99b1e966f1dfd8
El Khatabi Expires 10 March 2027 [Page 46]
Internet-Draft VTL September 2026
The following 394-octet artifact is the empty successor to the
segment above. It uses the same ledger, policy, and profile, sets
segment_number to 1 and prev_segment_sha256 to the preceding
segment_sha256, and exercises the lifecycle exception in which an
empty shutdown artifact retains empty_mode equal to suppress. Its
empty batch_roots array and segment_root equal to SHA-256 over zero
octets are normative.
empty_shutdown_suppress_segment_cbor =
aa6776657273696f6e01696c65646765725f6964782062376131643565343063
366634333865396137356462323763393666333161616b62617463685f726f6f
7473806c636c6f73655f726561736f6e6873687574646f776e6c7265636f7264
5f636f756e74006c7365676d656e745f726f6f745820e3b0c44298fc1c149afb
f4c8996fb92427ae41e4649b934ca495991b7852b8556e636c6f737572655f70
6f6c696379a66776657273696f6e016a656d7074795f6d6f6465687375707072
6573736b696e74657276616c5f6d731a05265c006c7265636f72645f6c696d69
74f67073697a655f6c696d69745f6279746573f67262617463685f7265636f72
645f6c696d6974026e7365676d656e745f6e756d6265720173707265765f7365
676d656e745f73686132353658202672cb72d5f06863110af1b30660c7e5ba49
5c0b2ce7d084b0436e010e99388d75636f6d6d69746d656e745f70726f66696c
655f6964782463303861646534652d313738352d346562362d393634382d6237
30303364373632383864
empty_shutdown_suppress_segment_sha256 =
cde8b546adc5afa446195bb9cc4e519d4bd1c9529d1678bf6e076ef6d24e229e
three_identical_record_1_root and four_identical_record_1_root are
segment_root values for segments containing respectively three and
four occurrences of the exact record_1 bytes. They are independent
of batch_record_limit; that field changes the aligned subtree
representation, not the RFC 9162 reduction of the complete sorted
leaf multiset.
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.
Appendix B. Producer Manifest and Verifier Result CDDL
This appendix defines the CDDL ([RFC8610]) shape for the producer
manifest and the separate verifier result. Both MUST be UTF-8 JSON
texts under [RFC8259]; parsers MUST reject duplicate object member
names and generators MUST NOT emit them.
These prose constraints apply in addition to the shape below. json-
hex32 is exactly 32 lowercase hexadecimal characters and json-hex64
exactly 64. segment_number is a JSON string holding the shortest
unsigned base-10 form of a uint64 (0, or a digit 1 through 9 followed
El Khatabi Expires 10 March 2027 [Page 47]
Internet-Draft VTL September 2026
by zero or more digits) whose value MUST NOT exceed
18446744073709551615, which avoids loss of precision where a JSON
implementation's exact integer range ends at 2^53-1. relative-path is
intentionally structural because RFC 8610 regular expressions cannot
portably express cross-platform containment checks; implementations
MUST apply the semantic path rules in Section 5.3 to every consumed
path-bearing object, including extensions.
Both commitment_profile_id members are generic tstr so that a
manifest can repeat, and a result can echo, a future or unsupported
artifact value; neither relaxes the baseline producer requirement in
Section 8, and the result member is optional because a malformed
artifact might not decode far enough to recover it. chain_status MUST
be present whenever the artifact decodes far enough to support one of
the chain conclusions defined here and MUST be absent otherwise,
absence making no chain claim; failure_reasons MUST be present and
non-empty exactly when overall is failure. Both the anchoring and
channels maps MUST contain exactly the tsa key, and extension
containers MUST NOT add channel keys or alter a baseline status or
outcome. Violating either direction of the state-to-reference rule
in Section 5.1 makes the manifest structurally invalid, whereas a
nonce-bearing response without tsa_req is a timestamp-channel
verification failure rather than a manifest-structure error, because
a nonce is learned only by inspecting the response.
producer-manifest = {
"version": 1,
"ledger_id": json-hex32,
"segment_number": uint64-decimal,
"commitment_profile_id": tstr,
"disclosure_class": disclosure-class,
"artifacts": artifacts,
"anchoring": anchoring,
? "extensions": { * tstr => json-data },
}
artifacts = {
"segment_cbor": artifact-ref,
? "predecessor_segment_cbor": artifact-ref,
? "record_batches": [+ record-batch-opening],
? "tsa_req": artifact-ref,
? "tsa_tsr": artifact-ref,
? "extensions": { * tstr => artifact-ref }
}
record-batch-opening = {
"batch_number": uint64-decimal,
"records": [+ artifact-ref]
El Khatabi Expires 10 March 2027 [Page 48]
Internet-Draft VTL September 2026
}
artifact-ref = {
"path": relative-path,
"sha256": json-hex64
}
anchoring = {
"tsa": producer-tsa-state
}
producer-tsa-state = {
"status": "present" / "pending" / "unavailable"
}
verifier-result = {
"artifact_sha256": json-hex64,
"manifest_sha256": json-hex64,
? "commitment_profile_id": tstr,
"claimed_disclosure_class": disclosure-class,
"verification_scope":
"public_recompute" / "disclosed_batch_recompute" / "anchor_only",
? "chain_status": chain-status,
"channels": channels,
"verifier_policy_id": non-empty-tstr,
? "verifier_policy_sha256": json-hex64,
"overall": "success" / "incomplete" / "failure",
? "failure_reasons": [+ baseline-failure-reason],
? "extensions": { * tstr => json-data }
}
chain-status =
"epoch" /
"validated" /
"predecessor_not_disclosed" /
"failed"
baseline-failure-reason =
"unsupported_commitment_profile" /
"invalid_canonical_record" /
"invalid_segment_artifact" /
"commitment_mismatch" /
"segment_chain_mismatch" /
"channel_failure" /
"insufficient_disclosure" /
"scope_not_exercised" /
"verifier_policy_rejection"
El Khatabi Expires 10 March 2027 [Page 49]
Internet-Draft VTL September 2026
channels = { "tsa": verifier-tsa-result }
verifier-tsa-result =
{
"status": "verified",
? "extensions": { * tstr => json-data }
} /
{
"status": "pending_claim",
"reason": "producer_pending_claim",
? "extensions": { * tstr => json-data }
} /
{
"status": "missing" / "failed",
"reason": non-empty-tstr,
? "extensions": { * tstr => json-data }
}
disclosure-class = "A" / "B" / "C"
relative-path = tstr
uint64-decimal = tstr
json-hex32 = (tstr .regexp "[0-9a-f]{32}") .size 32
json-hex64 = (tstr .regexp "[0-9a-f]{64}") .size 64
non-empty-tstr = tstr .size (1..18446744073709551615)
json-data =
; For JSON null; finite-float restrictions are normative prose.
nil / bool / int / float / tstr /
[* json-data] / { * tstr => json-data }
Appendix C. Authoritative Segment Artifact CDDL
This appendix gives the structural CDDL for the authoritative segment
artifact. The lexical and cross-field requirements in Section 4.5,
the encoding rules in Section 4.2, the commitment-tree and empty-
segment rules in Section 4.3, the formation rules in Section 4.4, and
the chain rules in Section 4.6 are normative in addition to this
shape. cbor-hex32 is distinct from the JSON rule in Appendix B and is
exactly 32 lowercase hexadecimal characters. CDDL cannot express the
power-of-two restriction or the upper bound of 2^63 on
batch_record_limit; both prose constraints apply in addition to
power-of-two-uint64.
El Khatabi Expires 10 March 2027 [Page 50]
Internet-Draft VTL September 2026
segment-record = {
"version": 1,
"commitment_profile_id": tstr,
"ledger_id": cbor-hex32,
"segment_number": uint64,
"closure_policy": segment-closure-policy,
"close_reason": close-reason,
"prev_segment_sha256": sha256-value,
"record_count": uint64,
"batch_roots": [* sha256-value],
"segment_root": sha256-value
}
segment-closure-policy = {
"version": 1,
"interval_ms": positive-uint64,
"batch_record_limit": power-of-two-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
power-of-two-uint64 = positive-uint64
cbor-hex32 = (tstr .regexp "[0-9a-f]{32}") .size 32
sha256-value = bstr .size 32
Acknowledgments
The author thanks Joe Clarke for OPSDIR review feedback that improved
the operational considerations and deployment guidance.
Author's Address
Bilal El Khatabi
Independent
Rabat
Morocco
El Khatabi Expires 10 March 2027 [Page 51]
Internet-Draft VTL September 2026
Email: elkhatabibilal@gmail.com
El Khatabi Expires 10 March 2027 [Page 52]