<?xml version="1.0" encoding="UTF-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     ipr="trust200902"
     category="info"
     submissionType="independent"
     docName="draft-elkhatabi-verifiable-telemetry-ledgers-08"
     version="3">
  <front>
    <title abbrev="VTL">Verifiable Telemetry Ledgers for Resource-Constrained Environments</title>
    <seriesInfo name="Internet-Draft" value="draft-elkhatabi-verifiable-telemetry-ledgers-08"/>

    <author fullname="Bilal El Khatabi" initials="B." surname="El Khatabi">
      <organization>Independent</organization>
      <address>
        <postal>
          <country>Morocco</country>
        </postal>
        <email>elkhatabibilal@gmail.com</email>
      </address>
    </author>

    <date year="2026" month="July" day="15"/>
    <area>General</area>
    <workgroup>Independent Submission</workgroup>
    <keyword>telemetry</keyword>
    <keyword>merkle</keyword>
    <keyword>timestamping</keyword>
    <keyword>iot</keyword>

    <abstract>
      <t>
        This document profiles a verifiable-telemetry ledger for
        resource-constrained deployments. Its interoperability boundary begins
        with exact canonical-record byte strings that an upstream system has
        already produced. The profile fixes admission and assignment of those
        byte strings to serial-numbered segments, deterministic commitment-tree
        calculation, a Concise Binary Object Representation (CBOR) segment
        artifact, a verification manifest, three disclosure classes, and
        binding of the segment-artifact digest to external timestamp channels.
        Transport framing, decryption, anti-replay processing, payload
        interpretation, and source-telemetry-to-record mapping are outside this
        profile. Segment closure uses a deployment-configured elapsed-time
        interval and does not depend on source or gateway calendar dates.
        RFC 3161 timestamp responses are the mandatory-to-implement
        interoperable timestamp channel. OpenTimestamps (OTS) and peer
        signatures are optional parallel channels.
      </t>
      <t>
        The profile enables independent recomputation and audit of disclosed
        evidence from the admitted canonical-record bytes onward. It does not
        verify how source telemetry was authenticated, interpreted, or mapped
        to those bytes, and it does not cover device onboarding, end-to-end
        security of sensor values, or safety decisions.
      </t>
    </abstract>
  </front>

  <middle>
    <section numbered="true" toc="include" anchor="introduction">
      <name>Introduction</name>
      <t>
        Long-lived telemetry deployments need evidence that record bytes
        disclosed later are the same bytes a ledger producer committed when
        they were admitted, even when upstream delivery is intermittent and
        verification happens later.
      </t>
      <t>
        Two trust questions must be distinguished. The first is whether a
        source was genuine, authorized, and mapped correctly. The second is
        whether, after exact record bytes were selected for commitment, a later
        verifier can determine that those bytes, the ledger artifact, and
        external evidence still agree. This profile standardizes the second
        question.
      </t>
      <t>
        This memo is an Independent Submission. It is not an Internet
        Standard and has not been evaluated as having IETF community
        consensus.
      </t>
      <t>
        The profile begins at an explicit byte-level handoff. An upstream
        admission system constructs one deterministic-CBOR canonical-record
        byte string and presents it to the ledger producer. Source
        eligibility, transport security, anti-replay processing, payload
        interpretation, and source-to-record mapping occur before that handoff
        and are outside this profile. The interoperability contract begins
        with the exact byte string presented for admission.
      </t>
      <t>Protocol at a Glance</t>
      <t>
        The following informative summary provides a reading path through the
        normative requirements that follow:
      </t>
      <ol>
        <li>Admission. The ledger producer validates the byte-level
        profile and admits the unchanged canonical-record bytes into the
        logical interval open at the admission linearization point. Each
        admission is one record occurrence, including when two admitted
        occurrences have identical bytes.</li>
        <li>Commitment. The producer computes each leaf as
        <tt>SHA-256(0x00 || record)</tt>, sorts the leaf hashes, and calculates
        <tt>segment_root</tt> over the complete sorted list using the
        domain-separated tree construction in <xref target="merkle-policy"/>.
        It partitions the same list deterministically into the batch objects
        embedded in the segment artifact. Batch roots describe their respective
        batches; they are not combined to calculate <tt>segment_root</tt>.</li>
        <li>Sealing. The producer encodes the authoritative segment
        artifact using deterministic CBOR. The artifact carries the commitment
        profile identifier, ledger and segment identity, closure claim,
        predecessor-artifact digest, batch objects, and segment root.</li>
        <li>External evidence. The producer computes SHA-256 over the
        exact segment-artifact bytes and submits that digest to at least one
        timestamping channel. Producers and verifiers implement
        <xref target="RFC3161"/>; a deployment can use OTS instead for a
        particular segment. Peer signatures are optional attestations over the
        same digest and do not by themselves satisfy the timestamping
        requirement.</li>
        <li>Verification. A verifier starts from the authoritative
        segment artifact and performs the checks supported by the disclosed
        bundle. Class A supports public record-level recomputation. Class B
        supports controlled audit when some record material is withheld. Class
        C is anchor-only and does not support record-level or batch
        recomputation. The verifier reports executed and skipped checks and
        validates chain adjacency only when the predecessor artifact is
        disclosed.</li>
      </ol>
      <table>
        <name>Principal Object Authority</name>
        <thead>
          <tr><th>Object</th><th>Status</th><th>Principal role</th></tr>
        </thead>
        <tbody>
          <tr><td>Canonical-record bytes</td><td>Authoritative admitted input</td><td>Exact leaf preimage after admission</td></tr>
          <tr><td>Segment CBOR</td><td>Authoritative segment artifact</td><td>Hashed, chained, and externally timestamped</td></tr>
          <tr><td>Manifest</td><td>Producer claim; non-authoritative</td><td>Indexes the bundle and claims disclosure class</td></tr>
          <tr><td>Verifier result</td><td>Verifier-authored scoped output</td><td>Reports scope, checks, channels, and outcome</td></tr>
        </tbody>
      </table>
      <t>
        Segment intervals are ledger batching rules, not source-reporting
        periods or civil-time claims. The producer assigns each admitted
        record to the logical interval open at its admission linearization
        point and uses a non-decreasing elapsed-time source for interval
        closure. Source arrival time, upstream processing time,
        <tt>ingest_time</tt>, <tt>device_time</tt>, and UTC do not select
        segment membership. Segment identity is
        <tt>(ledger_id, segment_number)</tt>, and a sealed segment is not
        reopened. Section 4.4 specifies boundary ordering, empty intervals,
        size-triggered closure, policy changes, and recovery behavior.
      </t>
      <figure anchor="arch-flow">
        <name>Evidence Path and Interoperability Boundary</name>
        <artwork type="ascii-art"><![CDATA[

Source telemetry
      |
      v
+----------------------------+       OUTSIDE THIS PROFILE
| Upstream admission system  |
| auth / replay / projection |
+----------------------------+
      | exact canonical-record bytes
======|================================================ boundary
      v
+----------------------------+ --> segment CBOR ------> Verifier
| Ledger producer            |
| admit / assign / commit    | --> artifact digest
| seal / chain               |          |
+----------------------------+          +--> timestamp: RFC 3161 / OTS
                                        +--> attestation: peers (optional)
]]></artwork>
      </figure>
      <t>
        Successful verification establishes consistency within the scope
        reported by the verifier. When the necessary material is disclosed,
        it can show that exact record bytes produce the claimed commitments,
        that the authoritative artifact produces the digest bound by the
        disclosed external evidence, and that disclosed predecessor artifacts
        form the claimed chain adjacency. It does not establish source
        authenticity, correct source-to-record mapping, dataset completeness,
        physical truth, or the absence of selective drops before admission.
      </t>
      <section numbered="true" toc="include" anchor="evidence-plane-boundary">
        <name>Scope Boundary</name>
        <t>
          This profile covers the ledger evidence path beginning with admission
          of an already-formed canonical-record byte string:
        </t>
        <ul>
          <li>byte-preserving record validation, admission, and segment
          assignment;</li>
          <li>deterministic hashing, batching, and chaining into authoritative
          segment artifacts;</li>
          <li>binding the segment-artifact digest to external timestamping or
          attestation evidence;</li>
          <li>verifier-facing manifests, disclosure, and export behavior; and</li>
          <li>scoped independent verification and reporting.</li>
        </ul>
        <t>
          It does not specify source transport or framing, authentication,
          decryption or other transport security, anti-replay processing,
          manufacturer identity, onboarding, fleet inventory, PKI policy,
          network admission, source buffering, identifier or message-type
          mapping, payload schemas, source-to-record projection, or firmware
          orchestration. Those functions can be colocated with the ledger
          producer, but they remain outside the interoperability claim made by
          this document.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="gateway-trust-boundary">
        <name>Ledger Producer Trust Boundary</name>
        <t>
          The ledger producer is trusted to validate and admit each accepted
          byte string, assign it to one segment, preserve its exact octets,
          maintain durable segment state, and construct the specified
          artifacts. An upstream system that constructs the record bytes is
          separately trusted for their source semantics but is outside this
          profile.
        </t>
        <t>
          This profile makes post-admission inconsistency detectable. It does
          not prove that upstream admission was correct, reveal a source event
          that was never admitted, establish ingestion completeness, validate
          a source-to-record mapping, or show that a committed measurement was
          physically true.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="document-roadmap">
        <name>Document Roadmap</name>
        <t>
          Section 2 defines the common terminology, and Section 3 identifies
          the system roles. Producer implementers should focus on Sections 4
          through 6, Section 9, and Section 10. Verifier implementers should
          focus on Sections 4 through 7, Section 9, and Appendices A through D.
          Operators should additionally read Sections 10 through 12 and
          Section 14. Commitment-profile, versioning, and registry designers
          should read Sections 8, 13, and 15.
        </t>
      </section>

    </section>

    <section numbered="true" toc="include" anchor="terminology">
      <name>Conventions and Terminology</name>
      <t>
        The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
        "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>",
        "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>",
        "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>",
        "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and
        "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
        described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
        when, and only when, they appear in all capitals, as shown here.
      </t>
      <t>Terms:</t>
      <ul>
        <li>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.</li>
        <li>Canonical-record byte string: The exact deterministic-CBOR byte string presented at the interoperability boundary and admitted as one commitment input. "Canonical" describes its byte-level encoding under the commitment profile; it does not assert physical truth or correct derivation from source telemetry.</li>
        <li>Commitment profile: The canonical-record byte syntax, deterministic encoding constraints, hash and tree rules, and segment-artifact rules that produce deterministic commitment outputs from admitted byte strings.</li>
        <li>Commitment contract: The full interoperable behavior defined by this profile, including byte-preserving canonical-record admission, segment assignment, commitment encoding, segment-artifact structure, verifier-facing manifests, disclosure classes, and verification rules.</li>
        <li>Ledger: One ordered chain of segment artifacts identified by a fresh unpredictable 128-bit <tt>ledger_id</tt>, rendered as 32 lowercase hexadecimal characters. Segment serial numbers are scoped to this identifier.</li>
        <li>Ledger epoch: The lifetime of one ledger sequence under a single <tt>ledger_id</tt>. The epoch segment is segment zero and carries the zero predecessor value. A ledger epoch is distinct from a transport-key epoch.</li>
        <li>Segment: The multiset of admitted canonical-record byte strings assigned to one emitted ledger interval. Depending on <tt>empty_mode</tt>, a segment can be empty. Segment membership is selected by the admission linearization point and a non-decreasing elapsed-time close rule, not by record timestamps.</li>
        <li>Segment artifact: The authoritative canonical segment record, normally written as <tt>segments/&lt;segment-number&gt;.cbor</tt>, where <tt>&lt;segment-number&gt;</tt> is the 20-digit, zero-padded decimal rendering of <tt>segment_number</tt>.</li>
        <li>Segment closure policy: The committed versioned policy containing a positive <tt>interval_ms</tt> and <tt>empty_mode</tt>. It is a gateway configuration claim, not independent proof that the gateway observed the claimed elapsed duration.</li>
        <li>Authoritative: Used for the canonical artifact that verifiers MUST treat as the cryptographic source of truth.</li>
        <li>Projection: A non-authoritative representation (for example JSON) derived from an authoritative artifact.</li>
        <li>Batch metadata: A standalone projection of a batch object (for example <tt>batches/00000000000000000007-00000000000000000000.batch.json</tt>) exported for convenience. When disclosed, it MUST match the corresponding batch object in the authoritative segment artifact.</li>
        <li>OTS metadata sidecar: <tt>segments/&lt;segment-number&gt;.ots.meta.json</tt>, a separate non-authoritative metadata file associated with an OTS proof and authoritative segment artifact, linking the artifact digest to the proof path. It is not a commitment input.</li>
        <li>Anchor evidence: The proof artifacts and binding metadata disclosed for an external timestamping or attestation channel.</li>
        <li>Peer signature quorum: A deployment-defined set or threshold of peer signatures over the same segment-artifact digest, treated as one optional parallel attestation channel.</li>
        <li>Verification scope: The set of disclosed artifacts, checks executed, and claim boundaries that a verifier actually asserts for a verification result.</li>
        <li>Admission linearization point: The ledger-producer-local instant at which one exact canonical-record byte string is accepted as a commitment input and assigned to the currently open segment. Implementations MUST serialize boundary closure and admission so that each admitted input has exactly one segment assignment.</li>
        <li>Disclosure class: The level of artifact disclosure associated with a verification claim.</li>
      </ul>
    </section>

    <section numbered="true" toc="include" anchor="roles">
      <name>System Roles</name>
      <t>
        In this document, optional parallel attestation channels are not
        required for baseline conformance. A conforming deployment MUST
        use at least one timestamping channel and MUST implement the
        <xref target="RFC3161"/> channel. OTS (<xref target="OTS"/>) and peer
        signatures are optional; when present, they MUST bind to the same
        authoritative segment-artifact digest and verifiers MUST report their
        results separately.
      </t>
      <ul>
        <li>Upstream admission system: Produces canonical-record byte strings after applying deployment-specific source validation and mapping. This role is outside the profile.</li>
        <li>Gateway / ledger producer: Accepts exact canonical-record byte strings at the profile boundary, assigns them to serial-numbered segments, constructs authoritative artifacts, and anchors segment-artifact digests. A gateway can implement both the upstream and ledger-producer roles, but conformance under this document begins only at the byte-level handoff.</li>
        <li>Verifier: Recomputes commitments and validates proofs from disclosed artifacts.</li>
        <li>OpenTimestamps calendar(s): provide OTS attestations for segment-artifact hashes.</li>
        <li>Timestamp authority (TSA): a timestamp authority under <xref target="RFC3161"/> over the same digest, when that mandatory-to-implement channel is selected for deployment use.</li>
        <li>Peers: Co-sign segment-artifact digests for short-term provenance, when that optional channel is used.</li>
      </ul>
    </section>

    <section numbered="true" toc="include" anchor="data-model">
      <name>Data and Commitment Model</name>
      <t>
        The normative input to this section is an exact canonical-record byte
        string that has already been produced by an upstream admission system.
        The interoperable core begins at that byte-level handoff and covers
        record admission, segment assignment, deterministic hashing and tree
        calculation, segment artifacts, disclosure, and verification. No
        source transport, decryption, anti-replay, payload interpretation, or
        source-to-record projection is defined by this document.
      </t>

      <section numbered="true" toc="include" anchor="canonical-record-input">
        <name>Canonical-Record Input Boundary</name>
        <t>
          The protocol input defined by this document is one exact
          canonical-record byte string. The byte string MUST encode exactly one
          CBOR data item using the record shape below and the deterministic
          encoding constraints in <xref target="cbor-profile"/>. A ledger
          producer MUST reject a proposed input that does not satisfy those
          byte-level constraints.
        </t>
        <t>
          Once admitted, the exact supplied octets are authoritative. The
          ledger producer MUST use those octets, without modification, as the
          leaf preimage under <xref target="merkle-policy"/>. It MUST NOT decode
          and re-encode, normalize, enrich, remove, reorder, or otherwise
          substitute a different byte string for commitment. Each admission
          event contributes one record occurrence, including when two admitted
          occurrences have identical byte strings.
        </t>
        <t>
          Source transport, framing, authentication, decryption, anti-replay
          processing, duplicate-submission policy, device-identifier mapping,
          message-type mapping, payload interpretation, and construction of the
          canonical-record byte string are upstream of this boundary and are
          not specified or verified here. A physical gateway MAY perform those
          functions and ledger production in one implementation, but its
          interoperability claim under this document begins only with the exact
          byte string passed across this logical boundary.
        </t>
        <t>
          For <tt>verifiable-telemetry-canonical-cbor-v2</tt>, each
          canonical-record byte string encodes the following fixed seven-element
          CBOR array:
        </t>
        <sourcecode type="cddl"><![CDATA[
canonical-record-v1 = [
  version: 1,
  device_id: bstr .size 8,
  fc: uint,
  ingest_time: uint,
  device_time: uint / nil,
  kind: uint,
  payload: any
]
]]></sourcecode>
        <t>
          The positional labels are conventional names for inspecting disclosed
          records; they do not move source-to-record mapping into this profile.
          Their byte-level requirements are:
        </t>
        <ul>
          <li><tt>version</tt> is the unsigned integer <tt>1</tt>.</li>
          <li><tt>device_id</tt> is an opaque 8-octet identifier assigned upstream. This document defines no mapping from a transport or deployment alias to this value.</li>
          <li><tt>fc</tt> is an unsigned upstream-supplied sequence value. This document defines no replay or duplicate-suppression semantics for it.</li>
          <li><tt>ingest_time</tt> is an unsigned count of whole non-leap seconds since <tt>1970-01-01T00:00:00Z</tt>. Its assignment and accuracy are upstream responsibilities, and it MUST NOT select segment membership.</li>
          <li><tt>device_time</tt> is an unsigned application timestamp or <tt>null</tt>. Its epoch and unit are upstream semantics, and it MUST NOT select segment membership.</li>
          <li><tt>kind</tt> is an unsigned application discriminator. This document defines no message-type or payload-family mapping for it.</li>
          <li><tt>payload</tt> is one CBOR data item permitted by <xref target="cbor-profile"/>. Its schema and meaning are outside this profile.</li>
        </ul>
        <t>
          A different record array shape or different byte-level field type is
          a different commitment profile and requires a distinct
          <tt>commitment_profile_id</tt>. Application schemas MAY separately
          define the meanings of <tt>device_id</tt>, <tt>fc</tt>,
          <tt>device_time</tt>, <tt>kind</tt>, and <tt>payload</tt>, but
          successful verification under this document does not validate those
          external semantics.
        </t>
        <t>
          Class A recomputation starts with the disclosed canonical-record byte
          strings. It demonstrates that those exact bytes produce the disclosed
          leaf digests, roots, and authoritative segment artifact. It does not
          reconstruct the bytes from source telemetry. Conformance vectors for
          this profile therefore MUST begin with exact canonical-record byte
          strings; transport messages and upstream projection fixtures, if
          supplied, are informative and are not inputs to baseline conformance.
        </t>
      </section>
      <section numbered="true" toc="include" anchor="cbor-profile">
        <name>Deterministic Concise Binary Object Representation (CBOR) Commitment Encoding</name>
        <t>
          This section does not define a new general-purpose CBOR variant. It
          records the narrow deterministic CBOR encoding used for commitment
          bytes by this profile.
          The identifier <tt>verifiable-telemetry-canonical-cbor-v2</tt> names
          this commitment recipe so verifiers can tell which byte-level rules
          were used; see <xref target="iana-profile-id-policy"/> for allocation
          policy.
        </t>
        <t>
          The authoritative commitment artifacts, namely CBOR canonical-record
          artifacts and the canonical segment artifact, use a constrained
          subset of the length-first core deterministic encoding requirements
          in Section 4.2.3 of <xref target="RFC8949"/>. For commitment bytes
          in this profile, the following concrete choices apply:
        </t>
        <ul>
          <li>All commitment-path items MUST use definite-length encoding.</li>
          <li>Integers MUST use the shortest encoding width permitted by <xref target="RFC8949"/>.</li>
          <li>Map keys MUST be CBOR text strings.</li>
          <li>Map keys MUST be sorted by encoded key length ascending, then by lexicographic order of the encoded key bytes.</li>
          <li>Duplicate map keys and invalid UTF-8 text strings MUST be rejected.</li>
          <li>Finite floating-point values MUST be encoded using the shortest of float16, float32, or float64 that exactly preserves the value.</li>
          <li>NaN, positive infinity, and negative infinity MUST be rejected in commitment paths.</li>
          <li>CBOR tags MUST NOT appear in commitment bytes.</li>
          <li>Supported values are unsigned integers, negative integers, byte strings, text strings, arrays, maps, booleans, null, and deterministic finite floats.</li>
        </ul>
        <t>
          Implementations MUST NOT accept generic CBOR serializers as
          authoritative commitment encoders. An encoder is acceptable only
          if it yields the same bytes as these rules.
        </t>
        <t>
          JSON projections of canonical-record artifacts and segment artifacts are
          optional and non-authoritative. They MUST NOT be used as
          commitment inputs. When produced, such projections SHOULD follow
          <xref target="RFC8785"/>.
        </t>
        <t>
          Upstream systems MAY use any transport or internal encoding. Only the
          exact canonical-record byte string admitted at
          <xref target="canonical-record-input"/> is an authoritative record
          commitment input. A different record encoding is not this profile
          unless it is identified by a distinct
          <tt>commitment_profile_id</tt> and verified under its own rules.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="merkle-policy">
        <name>Deterministic Commitment Tree Calculation</name>
        <t>
          For a given segment <tt>S</tt>, the current commitment profile
          computes <tt>segment_root</tt> from canonical-record bytes using the
          domain-separated tree shape of Section 2.1.1 of
          <xref target="RFC9162"/>, specialized to SHA-256 and to the multiset
          ordering below. SHA-256 is defined by <xref target="RFC6234"/>.
        </t>
        <t>
          For each exact canonical-record byte string <tt>record</tt>, compute
          <tt>leaf_hash = SHA-256(0x00 || record)</tt>. Sort the resulting raw
          32-octet leaf hashes in ascending byte order. Lowercase hexadecimal
          is only their artifact representation; sorting those fixed-width
          lowercase strings is equivalent to sorting the raw bytes.
        </t>
        <t>
          Let <tt>MTH(L)</tt> operate on the sorted list of already-computed
          leaf hashes. <tt>MTH({}) = SHA-256("")</tt> and
          <tt>MTH({x}) = x</tt>. For a list of <tt>n &gt; 1</tt> hashes, let
          <tt>k</tt> be the largest power of two strictly less than <tt>n</tt>,
          and compute
          <tt>MTH(L) = SHA-256(0x01 || MTH(L[0:k]) || MTH(L[k:n]))</tt>.
          Implementations MUST NOT duplicate an unpaired final hash. The
          prefixes <tt>0x00</tt> and <tt>0x01</tt> provide leaf/parent domain
          separation, and the recursive split gives every leaf count a unique
          tree shape.
        </t>
        <t>
          For an emitted empty segment, <tt>batches</tt> MUST be an empty array
          and <tt>segment_root</tt> MUST equal <tt>MTH({})</tt>, the SHA-256 digest of zero bytes:
          <tt>e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855</tt>.
          Its <tt>closure_policy.empty_mode</tt> MUST be <tt>emit</tt>; an empty
          artifact under <tt>suppress</tt> mode is invalid.
          For a non-empty segment, <tt>batches</tt> MUST contain at least one
          non-empty batch. The resulting <tt>segment_root</tt> is deterministic
          for the multiset of committed canonical records. Because leaf
          digests are sorted before reduction, the root does not commit to
          admission order. Admission order selects segment membership at the
          boundary but is not itself a verifier-visible total-order claim.
        </t>
        <t>
          Any future change to this calculation that alters commitment bytes
          MUST use a new
          <tt>commitment_profile_id</tt>.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="segment-formation">
        <name>Segment Formation and Closure</name>
        <t><em>Normal Interval Timing and Admission</em></t>
        <t>
          Segment formation uses a gateway elapsed-time source that MUST be
          non-decreasing and MUST progress during normal operation while an
          interval is open. Its resolution MUST be no greater than the configured
          <tt>interval_ms</tt>. The configured <tt>interval_ms</tt> is a fixed
          elapsed duration. It is not a civil-
          time duration and MUST NOT be aligned by local midnight, UTC
          midnight, time zone, daylight-saving transition, or leap second.
          The first logical interval of an epoch opens when the ledger is activated.
          Each normal or early closure immediately opens the next logical
          interval. Logical intervals continue across idle periods in both
          empty modes; <tt>suppress</tt> changes artifact emission and serial
          consumption, not the elapsed-time schedule.
        </t>
        <t>
          The gateway MUST serialize the interval-boundary transition with the
          admission linearization point. For an interval whose elapsed-time
          deadline is <tt>T</tt>:
        </t>
        <ul>
          <li>A record whose acceptance linearizes before <tt>T</tt> belongs to the current logical interval.</li>
          <li>At <tt>T</tt> or later, the gateway MUST process the boundary before another acceptance can linearize.</li>
          <li>Upstream processing can begin before <tt>T</tt>, but if canonical-record admission linearizes at or after <tt>T</tt>, the record belongs to the next logical interval.</li>
          <li>Source arrival time, upstream validation or record-construction time, <tt>device_time</tt>, and <tt>ingest_time</tt> MUST NOT override this assignment.</li>
        </ul>
        <t>
          The gateway MUST determine deadline expiry by checked elapsed-time
          subtraction; it MUST NOT add <tt>interval_ms</tt> to an absolute
          counter in a way that can wrap. If elapsed time cannot be represented
          or compared safely, the gateway MUST enter the recovery procedure
          below before accepting another record.
        </t>
        <t><em>Policy Changes and Early Closure</em></t>
        <t>
          The gateway snapshots <tt>closure_policy</tt> when a logical interval
          opens. That snapshot MUST remain unchanged through closure. A normal
          configuration update becomes effective for the next logical
          interval. An immediate update MUST first close the current logical
          interval under the old snapshot. It emits an artifact with
          <tt>close_reason</tt> equal to <tt>reconfigure</tt> unless the interval
          is empty under <tt>suppress</tt> mode, in which case it emits no
          artifact and consumes no segment number.
        </t>
        <t>
          Early closure is permitted only for a condition represented by the
          committed <tt>close_reason</tt>. A gateway MUST NOT place a record
          whose acceptance linearizes after the interval deadline into the
          expired interval merely because closure processing was late. Late
          closure is an operational fault and SHOULD generate an alarm.
        </t>
        <t><em>Limits and Close-Reason Selection</em></t>
        <t>
          <tt>closure_policy.record_limit</tt>, when non-null, is the maximum
          number of admitted records in one logical interval. The interval
          closes immediately after the acceptance that makes the record count
          equal to <tt>record_limit</tt>.
        </t>
        <t>
          <tt>closure_policy.size_limit_bytes</tt>, when non-null, is a close
          threshold for the sum of the lengths of the exact admitted
          canonical-record byte strings. After an acceptance has linearized, if
          the resulting byte total is greater than or equal to
          <tt>size_limit_bytes</tt>, the producer MUST close that logical
          interval before another acceptance can linearize. The triggering
          record remains assigned to the interval because segment assignment is
          final at the admission linearization point. Consequently,
          <tt>size_limit_bytes</tt> is not a hard pre-admission maximum and an
          emitted segment can exceed the threshold by the contribution of its
          final admitted record. If a single record admitted to an empty
          interval exceeds <tt>size_limit_bytes</tt>, that record forms a
          one-record interval, which MUST close before another acceptance can
          linearize. Threshold comparisons and byte-count updates MUST use
          checked arithmetic; the producer MUST enter recovery or stop
          acceptance before acknowledging a record if the new total cannot be
          represented safely.
        </t>
        <t>
          If multiple close conditions are simultaneously true, the committed
          <tt>close_reason</tt> MUST be selected by this precedence, from
          highest to lowest: <tt>recovery</tt>, <tt>shutdown</tt>,
          <tt>reconfigure</tt>, <tt>size_limit</tt>, <tt>record_limit</tt>,
          <tt>interval</tt>, then <tt>manual</tt>. The selected reason does not
          change which acceptances already linearized into the interval.
        </t>
        <t><em>Empty Intervals and Timer Continuity</em></t>
        <t>
          While elapsed-timer continuity is maintained, in <tt>emit</tt> mode
          every logical interval produces an artifact;
          an empty interval uses the empty construction in
          <xref target="merkle-policy"/>. In <tt>suppress</tt> mode, an empty
          logical interval produces no artifact and consumes no segment number.
          The next emitted artifact uses the next contiguous number. A
          suppressed interval makes no completeness or non-observation claim.
        </t>
        <t>
          Suspend time counts toward <tt>interval_ms</tt> when the selected
          elapsed-time source advances across suspend. If it does not, or if
          its continuity is uncertain, the gateway MUST apply the recovery
          procedure before accepting another record.
        </t>
        <t><em>Recovery and Durable State</em></t>
        <t>
          After restart or failover, the gateway MUST recover the active
          <tt>ledger_id</tt>, next segment number, policy snapshot, and any open
          interval state before accepting more telemetry. If elapsed-time or
          open-interval state is uncertain, the gateway MUST NOT infer the
          boundary from a possibly regressed wall clock. It MUST either stop
          acceptance or seal recoverable material with <tt>close_reason</tt>
          equal to <tt>recovery</tt> before accepting into a new interval. It
          MUST NOT synthesize historical empty artifacts and represent them as
          having been sealed at missed deadlines.
        </t>
        <t>
          The admission linearization point is a durable transaction boundary.
          Before acknowledging acceptance, the producer MUST make the exact
          canonical-record octets, their membership in the open interval, the
          interval record count and byte count, and the corresponding recovery
          state atomically durable or recoverable. After a crash, an acceptance
          MUST be recovered exactly once in the same logical interval, or it
          MUST be treated as never having completed. Segment sealing MUST
          atomically persist the authoritative artifact, its digest, the next
          serial allocation, and the new open-interval state before admission
          resumes.
        </t>
        <t><em>Deterministic Batch Partitioning</em></t>
        <t>
          For a non-empty interval, compute the complete sorted leaf-hash list
          defined in <xref target="merkle-policy"/>. Partition that list into
          consecutive batches of at most
          <tt>closure_policy.batch_record_limit</tt> hashes. Batch zero contains
          the first hashes, batch one the next hashes, and so on; only the last
          batch can contain fewer than the limit. This rule is the sole
          baseline batch partitioning rule and is independent of storage flushes,
          worker scheduling, or input-file layout.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="segment-artifact-schema">
        <name>Segment Artifact Schema</name>
        <t>
          The authoritative segment artifact is a deterministic CBOR-encoded
          segment record produced under <xref target="cbor-profile"/>. It is the
          stable segment-scoped object of commitment verification. It commits
          to one record multiset, its ledger identity, serial number, closure
          policy and reason, and predecessor artifact. It is not a transport
          envelope, publication statement, or complete verification claim.
        </t>
        <t>
          A segment artifact is interpreted only under its in-band
          <tt>commitment_profile_id</tt>. Because that identifier is inside the
          authoritative bytes, every proof over the segment-artifact digest
          binds the commitment semantics. A verifier-facing manifest MUST
          repeat the same value and verifiers MUST reject a mismatch. Verifiers
          MUST NOT infer the commitment profile from the file name, media type,
          segment-record <tt>version</tt>, or proof sidecar alone.
        </t>
        <t>The segment record contains exactly these fields:</t>
        <ul>
          <li><tt>version</tt> (uint): segment-record schema version, exactly <tt>2</tt>.</li>
          <li><tt>commitment_profile_id</tt> (tstr): exactly <tt>verifiable-telemetry-canonical-cbor-v2</tt>.</li>
          <li><tt>ledger_id</tt> (tstr): stable ledger identifier consisting of exactly 32 lowercase hexadecimal characters.</li>
          <li><tt>site_id</tt> (tstr): non-empty site identifier.</li>
          <li><tt>segment_number</tt> (uint): serial number in the range 0..(2^64-1).</li>
          <li><tt>closure_policy</tt> (map): immutable policy snapshot for this logical interval, containing exactly <tt>version</tt> equal to <tt>1</tt>; positive uint64 <tt>interval_ms</tt> and <tt>batch_record_limit</tt>; <tt>record_limit</tt> and <tt>size_limit_bytes</tt>, each a positive uint64 or null; and <tt>empty_mode</tt> equal to <tt>emit</tt> or <tt>suppress</tt>.</li>
          <li><tt>close_reason</tt> (tstr): exactly one of <tt>interval</tt>, <tt>reconfigure</tt>, <tt>record_limit</tt>, <tt>size_limit</tt>, <tt>shutdown</tt>, <tt>recovery</tt>, or <tt>manual</tt>.</li>
          <li><tt>prev_segment_sha256</tt> (tstr): SHA-256 digest of the exact previous authoritative segment-artifact bytes, as 64 lowercase hexadecimal characters, or the epoch predecessor value defined in <xref target="segment-chaining"/>.</li>
          <li><tt>batches</tt> (array): authoritative batch objects sorted by <tt>batch_number</tt>; exactly empty for an empty emitted segment.</li>
          <li><tt>segment_root</tt> (tstr): deterministic segment root as 64 lowercase hexadecimal characters.</li>
        </ul>
        <t>Each batch object contains exactly these fields:</t>
        <ul>
          <li><tt>version</tt> (uint): batch-record schema version, exactly <tt>2</tt>.</li>
          <li><tt>ledger_id</tt> (tstr): the containing segment's <tt>ledger_id</tt>.</li>
          <li><tt>site_id</tt> (tstr): the containing segment's <tt>site_id</tt>.</li>
          <li><tt>segment_number</tt> (uint): the containing segment's <tt>segment_number</tt>.</li>
          <li><tt>batch_number</tt> (uint): batch serial in the range 0..(2^64-1), unique within the segment.</li>
          <li><tt>merkle_root</tt> (tstr): batch Merkle root as 64 lowercase hexadecimal characters.</li>
          <li><tt>count</tt> (uint): positive number of committed canonical records in the batch.</li>
          <li><tt>leaf_hashes</tt> (non-empty array of tstr): leaf hashes sorted as lowercase hexadecimal strings.</li>
        </ul>
        <t>
          The batch objects embedded in the segment artifact are authoritative
          batch metadata. For a non-empty segment, batch objects MUST be sorted
          by ascending <tt>batch_number</tt>, and batch numbers MUST be unique
          and contiguous starting at zero. Their leaf lists MUST be the
          consecutive partitions of the complete sorted segment leaf list
          required by <xref target="segment-formation"/>.
        </t>
        <ul>
          <li>For each batch, <tt>ledger_id</tt>, <tt>site_id</tt>, and <tt>segment_number</tt> MUST equal the containing segment fields.</li>
          <li>For each batch, <tt>count</tt> MUST equal the length of <tt>leaf_hashes</tt> and MUST be greater than zero.</li>
          <li>For each batch, <tt>merkle_root</tt> MUST equal the Merkle reduction of that batch's <tt>leaf_hashes</tt> under <xref target="merkle-policy"/>.</li>
          <li>The multiset union of all batch <tt>leaf_hashes</tt> MUST equal the segment leaf-digest multiset from which <tt>segment_root</tt> is computed.</li>
        </ul>
        <t>
          <tt>segments/&lt;segment-number&gt;.cbor</tt> is authoritative. The
          corresponding <tt>segments/&lt;segment-number&gt;.json</tt> file is a
          projection only. The path label is the 20-digit, zero-padded decimal
          rendering of the unsigned serial number; it is not a protocol field.
          A verifier MUST compare the decoded <tt>segment_number</tt> with the
          manifest claim rather than trusting the file name.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="segment-chaining">
        <name>Segment Chaining</name>
        <t>
          Segment identity and chaining are defined within one stable
          <tt>ledger_id</tt>. They do not depend on UTC dates or elapsed idle
          time.
        </t>
        <ul>
          <li>The epoch segment MUST have <tt>segment_number</tt> equal to <tt>0</tt> and <tt>prev_segment_sha256</tt> equal to 64 zero characters, representing 32 zero bytes.</li>
          <li>Every non-epoch segment MUST have a serial number exactly one greater than its predecessor, MUST retain the same <tt>ledger_id</tt> and <tt>site_id</tt>, and MUST set <tt>prev_segment_sha256</tt> to <tt>SHA-256</tt> over the predecessor's exact authoritative CBOR bytes.</li>
          <li>A producer MUST NOT reuse, skip, or wrap <tt>segment_number</tt>. Before serial exhaustion, it MUST stop the ledger and start a new ledger with a new <tt>ledger_id</tt>.</li>
          <li>A closure-policy change MUST take effect only in a newly opened logical interval. It does not reset <tt>segment_number</tt> or <tt>ledger_id</tt>.</li>
        </ul>
        <t>
          When a new epoch begins, the producer MUST generate <tt>ledger_id</tt> from a
          cryptographically strong random source. If durable sequence state
          cannot be recovered unambiguously, a producer MUST stop acceptance or
          begin a new ledger with a fresh identifier; it MUST NOT reset the
          serial under the old identifier. Redundant gateways MUST use single-
          writer fencing or an atomic shared allocator so that they cannot emit
          different artifacts for the same
          <tt>(ledger_id, segment_number)</tt>.
        </t>
        <t>
          A verifier given adjacent segment artifacts MUST validate serial
          continuity and predecessor-digest linkage. A partial disclosure that
          omits the predecessor can still support validation of the disclosed
          artifact and its external proof, but the verifier MUST report segment
          chain validation as skipped because the predecessor is unavailable.
        </t>
      </section>
    </section>

    <section numbered="true" toc="include" anchor="artifacts">
      <name>Artifacts and Verification Bundles</name>
      <t>Illustrative artifact layout:</t>
      <ul>
        <li><tt>records/&lt;record-id&gt;.cbor</tt> - authoritative canonical records</li>
        <li><tt>records/&lt;record-id&gt;.json</tt> - optional projections</li>
        <li><tt>segments/&lt;segment-number&gt;.cbor</tt> - authoritative canonical segment artifact</li>
        <li><tt>segments/&lt;segment-number&gt;.json</tt> - optional projection</li>
        <li><tt>segments/&lt;segment-number&gt;.verify.json</tt> - verifier-facing segment manifest</li>
        <li><tt>segments/&lt;segment-number&gt;.result.json</tt> - optional verifier-produced result</li>
        <li><tt>batches/&lt;segment-number&gt;-&lt;batch-number&gt;.batch.json</tt> - optional standalone batch-metadata projection of one batch object</li>
        <li><tt>segments/&lt;segment-number&gt;.cbor.sha256</tt> - optional convenience digest</li>
        <li><tt>segments/&lt;segment-number&gt;.tsr</tt> - RFC 3161 timestamp response</li>
        <li><tt>segments/&lt;segment-number&gt;.cbor.ots</tt> - OTS proof</li>
        <li><tt>segments/&lt;segment-number&gt;.ots.meta.json</tt> - OTS binding metadata</li>
      </ul>
      <t>
        Each disclosed <tt>records/&lt;record-id&gt;.cbor</tt> file contains the
        exact canonical-record octets admitted at the boundary in
        <xref target="canonical-record-input"/>. A storage or bundle layer MUST
        NOT add a wrapper to those file octets or replace them with a
        re-encoding. File names are non-authoritative and are not leaf inputs.
      </t>
      <t>
        Deployments MAY store artifacts differently and MAY export them as
        bundles. The path shapes above are illustrative. In those shapes,
        <tt>&lt;segment-number&gt;</tt> and <tt>&lt;batch-number&gt;</tt> are 20-digit,
        zero-padded decimal renderings of their uint64 values.
      </t>
      <t>
        Standalone batch metadata files are convenience projections of batch
        objects already carried in the authoritative segment artifact. They are not
        additional commitment inputs. Verifiers that process disclosed
        standalone batch-metadata projections MUST compare them with the
        corresponding batch object in the authoritative segment artifact and
        reject mismatches.
      </t>
        <t>
          Every verification bundle that claims a disclosure class under this
          document MUST disclose the authoritative segment artifact and the
          producer-supplied manifest <tt>segments/&lt;segment-number&gt;.verify.json</tt>.
          The artifact's in-band <tt>commitment_profile_id</tt> is the
          cryptographically bound profile identifier. The manifest repeats the
          ledger identity, segment number, commitment profile, claimed
          disclosure class, artifact digests, and claimed channel state. It
          MUST NOT contain <tt>checks_executed</tt>,
          <tt>checks_skipped</tt>, or an overall verification outcome.
        </t>
        <t>
          Each entry in <tt>artifacts.records</tt> represents one admitted
          record occurrence. Duplicate entries are permitted and MUST be counted
          separately. When two or more occurrences have identical canonical-
          record bytes, their entries MAY reference the same disclosed artifact;
          a Class A verifier MUST hash its exact octets once for each listed
          occurrence. Artifact-reference order does not assert admission order.
        </t>
        <t>
          A verifier MAY emit a separate
          <tt>segments/&lt;segment-number&gt;.result.json</tt>. Only that
          verifier-produced result states the checks actually executed or
          skipped, the per-channel validation status, policy, and overall
          outcome. A producer manifest and a verifier result MUST NOT be
          represented as the same object.
        </t>
      <t>
        Verifier-facing manifests MUST be portable. Artifact paths in the
        manifest are UTF-8 strings interpreted relative to the disclosed
        evidence bundle root, using <tt>/</tt> as the only separator. A path
        MUST be non-empty; MUST NOT begin with <tt>/</tt>, <tt>\</tt>, or a
        drive-letter prefix; MUST NOT contain <tt>\</tt>, 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 <tt>.</tt> or <tt>..</tt>; and after
        resolution MUST remain below the bundle root. Verifiers MUST reject a
        symbolic link, reparse point, or equivalent filesystem indirection, or
        MUST use a containment-enforcing open operation that prevents such
        indirection from changing the target between validation and access.
        Path validation and file opening MUST be one race-resistant operation;
        a check-then-open sequence that permits target substitution is
        non-conformant. These checks are semantic requirements and do not depend
        on a regular-expression dialect. Every artifact listed in the manifest
        MUST carry a lowercase hexadecimal SHA-256 digest entry.
      </t>
      <t>
        The verifier-facing metadata binds claim semantics to the stable
        segment artifact. A bundle that discloses
        <tt>segments/&lt;segment-number&gt;.cbor</tt> and a
        timestamp proof can obtain the applicable
        <tt>commitment_profile_id</tt> from the artifact itself. If a manifest
        is also disclosed, its repeated identifier MUST match the in-band
        value.
      </t>
      <t>
        The verification manifest is the primary disclosure surface for
        verifier-visible producer claims. Its schema is defined in
        <xref target="appendix-c"/>. Deployment-specific data can be carried
        only in the explicit operational-summary or extension containers and
        MUST preserve the semantics defined here.
      </t>
      <t>At minimum, an OTS sidecar MUST bind:</t>
      <ul>
        <li><tt>artifact</tt>,</li>
        <li><tt>artifact_sha256</tt>, and</li>
        <li><tt>ots_proof</tt>.</li>
      </ul>
      <t>
        Verifiers MUST recompute the segment artifact digest and compare it with
        the sidecar before accepting any proof validation result.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="anchoring-verification">
      <name>Anchoring and Verification</name>

      <section numbered="true" toc="include" anchor="anchoring-contract">
        <name>Anchoring Contract</name>
        <t>
          The generic anchoring contract is simple: a gateway computes the
          SHA-256 digest of the authoritative segment artifact and submits that
          digest to one or more external timestamping channels. Verifiers MUST
          first recompute the segment artifact digest locally; proof validation
          occurs only after digest binding validation succeeds.
        </t>
        <t>
          A timestamp or attestation over the segment-artifact digest binds the
          complete artifact bytes, including the in-band
          <tt>commitment_profile_id</tt>. It does not bind a disclosure class,
          producer manifest, verifier policy, or checks exercised unless the
          timestamped object separately includes those items.
        </t>
        <t>
          A deployment conforming to this profile MUST use at least one
          timestamping channel for each emitted segment. Conforming producers
          and verifiers MUST implement the <xref target="RFC3161"/> channel
          defined below. Implementation support is mandatory, but a deployment
          MAY use OTS (<xref target="OTS"/>) instead of RFC 3161 for a
          particular emitted segment. Peer signatures are optional attestations
          and do not by themselves satisfy the timestamping-channel requirement.
          OTS and peer signatures are not baseline interoperable timestamp
          profiles.
        </t>
        <figure anchor="time-flow">
          <name>Illustrative Commitment and Proof Lifecycle</name>
          <artwork type="ascii-art"><![CDATA[
time ------------------------------------------------------------>

Upstream |--record bytes-->|      |--record bytes-->|              |
Ledger   | admit exact bytes      | admit exact bytes              |
         |----- segment N open for configured elapsed interval ----|
         |          write segments/SEGMENT-N.cbor                  |
         |---------- submit digest to OTS / RFC 3161 ------------->|
Channel  |                pending / delayed proof        | upgrade |
Verifier |                                      verify later from  |
         |<---------------- disclosed bundle --------------------->|
]]></artwork>
        </figure>
        <t>
          <xref target="time-flow"/> illustrates the current lifecycle. The
          upstream path can be intermittent, although it lies outside this
          profile. Proof completion or later publication can lag behind the
          authoritative segment-artifact write.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="rfc3161-profile">
        <name>RFC 3161 Interoperable Timestamp Channel</name>
        <t>
          Conforming producers and verifiers MUST implement this channel. As
          specified in <xref target="anchoring-contract"/>, a deployment is not
          required to use it for every segment.
        </t>
        <t>
          When this channel is used, the producer MUST set
          <tt>TimeStampReq.messageImprint.hashAlgorithm</tt> to SHA-256 and its
          <tt>hashedMessage</tt> to the exact 32-octet result of SHA-256 over
          the authoritative segment-artifact bytes. The producer MUST NOT hash
          that 32-octet result again.
        </t>
        <t>
          A deployment using this channel MUST define the accepted TSA trust
          anchors and any required TSA policy OIDs or other validation
          constraints.
        </t>
        <t>
          A verifier evaluating disclosed RFC 3161 evidence MUST recompute the
          segment-artifact digest and validate the TimeStampResp and time-stamp
          token under <xref target="RFC3161"/>. Validation MUST include response
          status, confirmation that TSTInfo.messageImprint uses SHA-256 and
          contains the recomputed digest, the token signature, and the TSA
          signer certificate and certification path under the configured trust
          anchors and policy constraints. Successful validation MUST be
          reported as <tt>tsa_verification</tt>.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="ots-profile">
        <name>Optional OTS Channel</name>
        <t>
          When <xref target="OTS"/> is used, the gateway stamps
          <tt>SHA-256(segments/&lt;segment-number&gt;.cbor)</tt> and stores an OTS
          proof plus an OTS sidecar.
        </t>
        <t>
          OpenTimestamps is referenced here as a deployed public timestamping
          ecosystem rather than an IETF-standardized proof format.
          Implementations claiming OTS support depend on the interoperable
          behavior of the public OTS project, its calendar servers, and
          compatible client tooling. OTS proof-format interoperability is
          therefore defined operationally by that ecosystem and its reference
          implementations. A verifier reports this deployment-specific check
          using an extension identifier beginning with <tt>x-</tt>, for example
          <tt>x-ots-verification</tt>; it MUST NOT report
          <tt>tsa_verification</tt> for an OTS proof.
        </t>

        <section numbered="true" toc="include" anchor="ots-lifecycle">
          <name>OTS Anchoring Lifecycle</name>
          <ol>
            <li><em>Submission</em>: the gateway submits the segment artifact digest to one or more OTS calendars.</li>
            <li><em>Pending</em>: a calendar can return an incomplete proof while awaiting Bitcoin commitment.</li>
            <li><em>Upgrade</em>: the gateway or a background process can later upgrade the proof to include completed attestations.</li>
            <li><em>Verification</em>: a verifier recomputes the artifact digest and validates the proof.</li>
          </ol>
          <t>
            Calendar selection and multi-calendar availability guidance are
            described in <xref target="ops-config"/>.
          </t>
        </section>

        <section numbered="true" toc="include" anchor="delayed-anchoring">
          <name>Handling Delayed or Failed Anchoring</name>
          <t>
            If OTS submission fails, times out, or yields only an incomplete
            proof, the gateway MUST still write the authoritative segment artifact
            and MUST treat OTS as a separate channel whose state is not yet
            complete. Any later replacement or upgrade of the OTS proof MUST
            continue to bind to the same authoritative segment-artifact digest.
            Operator handling and verifier reporting for pending or absent
            proofs are described in <xref target="ops-health"/>,
            <xref target="ops-config"/>, and
            <xref target="ops-fault-results"/>.
          </t>
        </section>

        <section numbered="true" toc="include" anchor="proof-status-vocabulary">
          <name>Proof Status Vocabulary</name>
          <t>
            Verifier results SHOULD use the following status vocabulary for
            timestamp and optional parallel attestation channels:
          </t>
          <ul>
            <li><tt>verified</tt>: proof validation succeeded for the disclosed artifact binding.</li>
            <li><tt>pending</tt>: a proof exists but is incomplete or awaiting upgrade; this is not equivalent to invalid.</li>
            <li><tt>missing</tt>: the expected proof or channel artifact is absent.</li>
            <li><tt>failed</tt>: validation was attempted and did not succeed.</li>
            <li><tt>skipped</tt>: validation was not attempted because of disclosure class, verifier configuration, or local policy.</li>
          </ul>
          <t>
            Whether <tt>missing</tt>, <tt>pending</tt>, or <tt>skipped</tt>
            is verifier-fatal depends on the disclosure class, local verifier
            policy, and whether the relevant channel is required.
          </t>
        </section>
      </section>

      <section numbered="true" toc="include" anchor="parallel-attestation">
        <name>Optional Parallel Attestation</name>
        <t>Deployments MAY also produce:</t>
        <ul>
          <li>An OTS proof over the same segment-artifact digest.</li>
          <li>A deployment-specific peer signature quorum over the same segment-artifact digest.</li>
        </ul>
        <t>
          This document does not define an interoperable peer-signature
          validation profile. Peer-signature validation MUST be reported under
          an extension identifier beginning with <tt>x-</tt>, for example
          <tt>x-peer-quorum-verification</tt>. A future specification can
          register interoperable peer-signature semantics.
        </t>
        <t>
          When multiple channels are present, verifiers SHOULD validate all
          available channels independently and report per-channel results.
        </t>
        <t>
          If a verifier is configured in strict mode for optional channels,
          failure of those channels MUST cause overall verification failure.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="verify">
        <name>Verification</name>
        <t>
          Verifiers MUST first decode the authoritative segment artifact and
          determine the applicable <tt>commitment_profile_id</tt> from its
          in-band field. The verifier MUST reject an absent or unsupported
          value. When a verifier-facing manifest is disclosed, its repeated
          value MUST exactly match the artifact field.
        </t>
        <t>
          The verifier MUST treat <tt>commitment_profile_id</tt> as the semantic
          key for interpreting the authoritative segment artifact. A structurally
          well-formed segment artifact and a valid timestamp proof are insufficient
          for semantic verification if the applicable
          <tt>commitment_profile_id</tt> is absent or unsupported. A manifest
          mismatch is a verification failure even when the artifact and
          timestamp are otherwise valid.
        </t>
        <t>
          Verifiers MUST determine the applicable verification scope from the
          disclosed artifacts, the claimed disclosure class, and local
          verifier policy. Reported outcomes MUST NOT claim checks or
          assurances outside that scope.
        </t>
        <t>
          Producer manifests do not report executed or skipped checks. A
          verifier produces those lists only in its separate result after
          validating the disclosed artifacts.
        </t>
        <t>
          Verifiers SHOULD apply checks in the following fail-fast order,
          subject to the claimed disclosure class:
        </t>
        <ol>
          <li>Validate that disclosed artifacts are sufficient for the claimed disclosure class, and report <tt>bundle_disclosure_validation</tt>.</li>
          <li>Validate the authoritative segment artifact and, when disclosed or consumed, the verifier-facing manifest, and report <tt>segment_artifact_validation</tt> and <tt>verification_manifest_validation</tt> as applicable.</li>
          <li>For an epoch segment, validate serial zero and the zero predecessor value. For a non-epoch segment whose predecessor is disclosed, validate ledger and site identity, contiguous serials, and <tt>prev_segment_sha256</tt>. Report <tt>segment_chain_validation</tt> as executed or, when the predecessor is unavailable, as skipped with reason <tt>predecessor_not_disclosed</tt>.</li>
          <li>For Class A bundles, validate each disclosed canonical-record CBOR artifact, hash its exact disclosed octets without re-encoding, validate the batch metadata contract, and recompute <tt>segment_root</tt>. Compare the recomputed result to the authoritative <tt>segment_root</tt>, and report <tt>record_level_recompute</tt> and <tt>batch_metadata_validation</tt>. Do not attempt to reconstruct a record from source telemetry.</li>
          <li>For Class B bundles, validate the authoritative segment artifact and any disclosed batch metadata. If withheld material prevents public recomputation, report <tt>record_level_recompute</tt> in <tt>checks_skipped</tt>. Deployment-specific withheld-material checks MAY be reported only through extension names beginning with <tt>x-</tt>.</li>
          <li>For Class C bundles, report <tt>record_level_recompute</tt> and <tt>batch_metadata_validation</tt> in <tt>checks_skipped</tt> as out of scope, and treat the result as anchor-only evidence.</li>
          <li>Recompute <tt>SHA-256(segments/&lt;segment-number&gt;.cbor)</tt> and compare it with every applicable disclosed binding value: the manifest's <tt>artifacts.segment_cbor.sha256</tt> value, an RFC 3161 <tt>messageImprint.hashedMessage</tt>, an OTS sidecar <tt>artifact_sha256</tt>, or deployment-specific peer-attestation binding metadata. A mismatch in any consumed binding is a verification failure. Report <tt>segment_digest_binding</tt>. If no binding value is disclosed, report the check as skipped with reason <tt>missing_binding_metadata</tt>; the bundle is then insufficient for any disclosure class defined here.</li>
          <li>Validate an <xref target="RFC3161"/> timestamp response when present or required by verifier policy, and report <tt>tsa_verification</tt>.</li>
          <li>Validate OTS proofs or peer attestations as configured and report them only through distinct <tt>x-</tt> extension check identifiers.</li>
        </ol>
        <t>
          When batch metadata is within the exercised verification scope,
          verifiers MUST apply the following checks before accepting a result:
        </t>
        <ul>
          <li>each batch <tt>count</tt> equals the length of its <tt>leaf_hashes</tt>;</li>
          <li>each batch repeats the containing <tt>ledger_id</tt>, <tt>site_id</tt>, and <tt>segment_number</tt> exactly;</li>
          <li>batch numbers are unique, contiguous from zero, and ordered numerically;</li>
          <li>batch leaf lists are the consecutive partitions of the sorted segment leaf list under the committed <tt>batch_record_limit</tt>;</li>
          <li>each batch <tt>merkle_root</tt> equals the Merkle reduction of its <tt>leaf_hashes</tt>;</li>
          <li>the union multiset of batch <tt>leaf_hashes</tt> equals the leaf digest multiset derived from disclosed canonical records when canonical-record artifacts are available; and</li>
          <li>any standalone batch-metadata projection matches the corresponding batch object in the authoritative segment artifact.</li>
        </ul>
        <t>
          Verifier implementations SHOULD expose machine-usable failure
          categories:
        </t>
        <ul>
          <li>malformed or missing artifacts,</li>
          <li>missing or unsupported <tt>commitment_profile_id</tt>,</li>
          <li>Merkle mismatch,</li>
          <li>batch metadata mismatch,</li>
          <li>segment serial, ledger identity, site identity, or predecessor-digest mismatch,</li>
          <li>missing or invalid required timestamp proof,</li>
          <li>sidecar mismatch or digest mismatch,</li>
          <li>insufficient disclosure for the claimed verification level, and</li>
          <li>optional-channel failure.</li>
        </ul>
        <t>
          Verifier output SHOULD state the claimed disclosure class, the
          verification scope actually exercised, the per-channel proof
          status, which checks were executed, which checks were skipped, and
          whether the resulting claim is public recompute, partial
          verification, or anchor-only evidence.
        </t>
        <t><strong>Standardized Check Identifiers</strong></t>
        <t>
          When verifier results report
          <tt>checks_executed</tt> or <tt>checks_skipped</tt>, this profile
          defines the following interoperable check identifiers:
        </t>
        <ul>
          <li><tt>bundle_disclosure_validation</tt>: disclosure-class sufficiency was validated.</li>
          <li><tt>verification_manifest_validation</tt>: the verifier-facing manifest was validated.</li>
          <li><tt>segment_artifact_validation</tt>: the authoritative segment artifact was validated structurally and semantically under the claimed profile.</li>
          <li><tt>segment_chain_validation</tt>: epoch-segment state or adjacent segment serial, identity, and predecessor-artifact digest linkage were validated.</li>
          <li><tt>record_level_recompute</tt>: record-level recomputation from disclosed canonical-record artifacts was performed.</li>
          <li><tt>batch_metadata_validation</tt>: authoritative or disclosed batch metadata was validated against the segment artifact and disclosed record material within scope.</li>
          <li><tt>segment_digest_binding</tt>: the recomputed <tt>SHA-256(segments/&lt;segment-number&gt;.cbor)</tt> digest was compared with disclosed binding metadata.</li>
          <li><tt>tsa_verification</tt>: the <xref target="RFC3161"/> timestamp channel was validated.</li>
        </ul>
        <t>
          A verifier result that reports one of these standardized
          checks MUST use the exact identifier listed here. For any
          standardized check whose applicability conditions are met within the
          exercised verification scope, the verifier result MUST
          report that check exactly once in either <tt>checks_executed</tt> or
          <tt>checks_skipped</tt>. The same standardized identifier MUST NOT
          appear in both lists and MUST NOT appear more than once. Silent
          omission of an applicable standardized check is non-conformant.
        </t>
        <t>
          Applicability is determined as follows:
        </t>
        <ul>
          <li><tt>bundle_disclosure_validation</tt> and <tt>segment_artifact_validation</tt> apply whenever verification proceeds on a disclosed bundle.</li>
          <li><tt>verification_manifest_validation</tt> applies when a verifier-facing manifest is disclosed or consumed to obtain verifier-visible metadata.</li>
          <li><tt>segment_chain_validation</tt> applies to every disclosed segment. For an epoch segment it validates the zero predecessor and serial zero. For a non-epoch segment, it MUST be executed when the predecessor is disclosed and otherwise MUST be reported as skipped.</li>
          <li>For Class A bundles, <tt>record_level_recompute</tt>, <tt>batch_metadata_validation</tt>, and <tt>segment_digest_binding</tt> apply. If required artifacts for one of these checks are absent, that check MUST appear in <tt>checks_skipped</tt> with a reason indicating insufficient disclosure or missing artifacts.</li>
          <li>For Class B bundles, <tt>batch_metadata_validation</tt> and <tt>segment_digest_binding</tt> apply when the corresponding artifacts are disclosed. If withheld material prevents public recomputation, <tt>record_level_recompute</tt> MUST appear in <tt>checks_skipped</tt>.</li>
          <li>For Class C bundles, <tt>record_level_recompute</tt> and <tt>batch_metadata_validation</tt> MUST appear in <tt>checks_skipped</tt> as out of scope, while <tt>segment_digest_binding</tt> applies when the segment artifact and binding metadata are disclosed.</li>
          <li><tt>tsa_verification</tt> applies when the RFC 3161 channel is disclosed or required by verifier policy. Other channels use <tt>x-</tt> extension identifiers.</li>
        </ul>
        <t>
          Additional deployment-specific checks MAY be reported, but they MUST
          NOT redefine these identifiers and MUST use a distinct extension
          name beginning with <tt>x-</tt>.
        </t>
        <t>
          Verifier output MUST NOT be represented as proving more than the
          exercised verification scope. In particular, a successful result does
          not by itself establish dataset completeness, physical truth of
          measurements, or suitability for autonomous actuation or sanctions.
        </t>
      </section>
    </section>

    <section numbered="true" toc="include" anchor="disclosure-bundles">
      <name>Disclosure Classes</name>
      <t>
        Verification claims depend on what artifacts are disclosed. This
        profile defines three disclosure classes.
      </t>
      <ul>
        <li><strong>Class A (Public Recompute)</strong>: sufficient material for independent record-level recomputation.</li>
        <li><strong>Class B (Partner Audit)</strong>: controlled disclosure with redacted or partitioned record material.</li>
        <li><strong>Class C (Anchor-Only)</strong>: existence and timestamp evidence only.</li>
      </ul>
      <t>
        Disclosure classes are verifier behavior, not prose intent. A verifier
        MUST decide each class from the artifacts it can recompute, the
        artifacts it cannot recompute, and the checks it reports as executed or
        skipped. A verifier claim for any disclosure class MUST be limited to
        the verification scope supported by the disclosed artifacts and MUST
        NOT be represented as proving dataset completeness, physical truth of
        measurements, omitted device lifecycle state, omitted external channels,
        or suitability for autonomous actuation or sanctions.
      </t>
      <t><strong>Class A (Public Recompute)</strong></t>
      <t>
        Class A is appropriate when public recomputation from disclosed
        canonical records and authoritative artifacts is required. A Class A
        bundle MUST include all canonical-record artifacts required to
        recompute the claimed segment root, the canonical segment artifact including
        its authoritative batch objects, any disclosed standalone
        batch-metadata projections, the verifier-facing segment manifest, and
        at least one proof artifact plus its binding metadata. The segment
        artifact itself records the
        <tt>commitment_profile_id</tt>.
      </t>
      <t>
        A Class A verifier can perform record-level recomputation,
        batch-metadata validation, segment-root recomputation, segment-artifact digest
        validation, manifest artifact-digest validation, and enabled anchor or
        publication-proof validation when the corresponding artifacts are
        disclosed. It MUST report recomputation, profile, and manifest status. A
        public-recompute claim is invalid if required record artifacts are
        missing, root recomputation was skipped, the in-band profile is absent
        or unsupported, or digest checks fail.
      </t>
      <t><strong>Class B (Partner Audit)</strong></t>
      <t>
        Class B is appropriate for controlled disclosure where some record
        material is withheld while commitment and anchor evidence remain
        auditable. Class B outputs MUST NOT be represented as publicly
        recomputable. A Class B bundle MUST include the canonical segment
        artifact, the verifier-facing segment manifest, and at least one
        timestamp proof plus binding metadata. It MAY include standalone
        batch-metadata projections, commitments covering
        withheld material, and a policy artifact describing withheld or
        partitioned material.
      </t>
      <t>
        Class B validation is limited to the authoritative segment artifact,
        disclosed batch metadata, any disclosed withheld-material commitments,
        any auditor-supplied material, and any anchor channels present in the
        bundle. Verifier output SHOULD explicitly state when record-level
        recomputation was partial or was not attempted for withheld material.
        It MUST report <tt>record_level_recompute</tt> as skipped when public
        record-level recomputation is impossible and MUST report that the
        result is not publicly recomputable. Deployment-specific checks for
        withheld-material commitments or policy artifacts MUST use extension
        names beginning with <tt>x-</tt>.
      </t>
      <t><strong>Class C (Anchor-Only)</strong></t>
      <t>
        Class C is appropriate when only existence and timestamp evidence is
        disclosed. A Class C disclosure MUST be labeled as existence and
        timestamp evidence only and MUST NOT claim record-level
        reproducibility. A Class C bundle MUST include the canonical segment
        artifact, the verifier-facing segment manifest, and at least one
        timestamp proof artifact plus the metadata needed to bind it to the
        segment artifact digest. The in-band
        <tt>commitment_profile_id</tt> supplies the profile identity.
      </t>
      <t>
        A Class C verifier can validate segment-artifact digest binding, manifest
        digests, chain or anchor existence, and timestamp or publication status
        when the relevant artifacts are present. Class C verifier output SHOULD
        be reported as anchor-only evidence. It MUST report record-level and
        batch recomputation as skipped. It MUST NOT report
        <tt>segment_chain_validation</tt> as executed for a non-epoch segment
        unless the predecessor artifact is disclosed.
      </t>
      <t>
        The verifier-facing manifest MUST include:
      </t>
      <ul>
        <li><tt>ledger_id</tt> and <tt>segment_number</tt>,</li>
        <li><tt>disclosure_class</tt>,</li>
        <li><tt>commitment_profile_id</tt>,</li>
        <li>artifact path and digest entries,</li>
        <li>claimed per-channel anchor status.</li>
      </ul>
      <t>
        A separate verifier result MUST identify the artifact digest and
        commitment profile it evaluated, the claimed disclosure class, checks
        executed, checks skipped with reasons, per-channel validation results,
        verifier policy, and overall outcome.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="versioning">
      <name>Versioning</name>
      <t>
        This profile has several independent version surfaces:
      </t>
      <ul>
        <li>Document revision (for example <tt>-00</tt>, <tt>-01</tt>) is editorial and is not part of commitment output.</li>
        <li>Artifact schema versions are carried by the <tt>version</tt> fields in segment, batch, verification-manifest, and verifier-result records.</li>
        <li><tt>commitment_profile_id</tt> identifies the canonical CBOR, hash, and Merkle rules that define commitment outputs.</li>
      </ul>
      <t>
        The commitment profile defined in this document is
        <tt>verifiable-telemetry-canonical-cbor-v2</tt>. If a verifier encounters an unsupported
        <tt>commitment_profile_id</tt>, it MUST reject the verification claim
        rather than silently using a fallback interpretation.
      </t>
      <t>
        This revision defines exactly one non-private
        <tt>commitment_profile_id</tt>. Additional non-private profile
        identifiers are allocated as described in
        <xref target="iana-profile-id-policy"/> and require a stable public
        specification before they are used for interoperability claims.
      </t>
      <t>
        The move from calendar-day artifacts to serial-numbered segments is a
        commitment-format migration, not an editorial alias. It changes the
        authoritative artifact family, schema bytes, paths, chain input, and
        verifier semantics. Therefore this revision uses segment and batch
        schema version <tt>2</tt>, verification-manifest version <tt>2</tt>,
        the new media type in <xref target="iana-media-type"/>, and
        <tt>verifiable-telemetry-canonical-cbor-v2</tt>. A producer MUST NOT
        label v2 bytes with the v1 identifier. Migration from a v1 day ledger
        starts a fresh v2 <tt>ledger_id</tt> at segment zero; any cross-profile
        migration statement requires a separately specified artifact and is
        not a normal <tt>prev_segment_sha256</tt> link.
      </t>
      <t>
        The fixed canonical-record array retains its in-band record
        discriminator value <tt>1</tt>. The v2 profile uses domain-separated
        leaf and parent hashes, the uniquely determined recursive tree shape
        in <xref target="merkle-policy"/>, and deterministic batch
        partitioning. Its roots are therefore not interchangeable with roots
        produced by the legacy duplicate-last construction.
      </t>
      <t>
        The authoritative segment artifact carries the applicable
        <tt>commitment_profile_id</tt> in-band. A verifier-facing manifest
        repeats it and MUST match the artifact. Timestamping the artifact
        digest therefore binds the profile identifier without relying on an
        unprotected manifest association.
      </t>
      <t>
        A segment-record <tt>version</tt> identifies the schema of the segment artifact
        under a known commitment profile. It is not a substitute for
        <tt>commitment_profile_id</tt>. Likewise, a media type or file extension
        can identify the artifact family, but it does not authorize a verifier
        to select canonical CBOR, hash, or Merkle rules without an explicit
        commitment profile.
      </t>
      <t>
        The following migration rules apply to the public contract surfaces:
      </t>
      <dl newline="true" spacing="normal">
        <dt>New <tt>commitment_profile_id</tt></dt>
        <dd>
          Required for changes to authoritative fact, batch, or segment commitment
          bytes; deterministic CBOR encoding rules; accepted integer, float,
          null, timestamp, or unknown-field behavior for commitment inputs;
          hash algorithm; Merkle leaf ordering; parent construction; odd-leaf
          policy; segment-artifact chaining semantics; or disclosure-class
          recomputation semantics.
        </dd>
        <dt>New schema version or schema identifier</dt>
        <dd>
          Required for changes to a public schema's required fields,
          closed-field policy, field type, enum vocabulary, or field meaning
          while preserving the same artifact family and commitment profile.
        </dd>
        <dt>New artifact family</dt>
        <dd>
          Required for a new primary evidence object, trust domain, publication
          statement, disclosure package, rejection-audit public contract,
          sealed-state object, or non-segment commitment unit.
        </dd>
        <dt>Verifier tolerance only</dt>
        <dd>
          Appropriate for accepting legacy aliases, optional historical fields,
          alternate discovery locations, or stricter and looser validation
          lanes when produced commitments and verifier truth claims do not
          change. Material tolerance behavior MUST be reported by verifier
          output.
        </dd>
        <dt>Projection change only</dt>
        <dd>
          Appropriate for SensorThings output, JSON presentation, CLI
          rendering, report formatting, non-authoritative labels, or read-only
          consumer exports that are not hashed into commitments and do not
          change verifier claims.
        </dd>
      </dl>
      <t>
        A change can trigger more than one action. For example, a new
        publication statement that also changes commitment bytes requires both
        a new artifact family and a new <tt>commitment_profile_id</tt>.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="conformance-vectors">
      <name>Conformance Vectors</name>
      <t>
        The deterministic rules in this profile can be exercised with
        machine-readable conformance vectors. Vector suites SHOULD cover the
        positive and negative cases below.
      </t>
      <t>Positive coverage should include:</t>
      <ul>
        <li>exact canonical-record byte strings with fixed decoded field types and values,</li>
        <li>an epoch segment and a normal successor linked by the predecessor artifact digest,</li>
        <li>an empty emitted interval and an empty suppressed interval,</li>
        <li>a single canonical record,</li>
        <li>odd leaf count,</li>
        <li>power-of-two leaf count,</li>
        <li>duplicate leaf hashes,</li>
        <li>three and four identical record occurrences producing distinct roots,</li>
        <li>a record immediately before and exactly at an elapsed-time boundary,</li>
        <li>device and UTC timestamp changes that do not alter segment membership,</li>
        <li>a closure-policy update that becomes effective only in the next interval,</li>
        <li>restart recovery without serial reuse,</li>
        <li>multi-batch ordering and aggregation, and</li>
        <li>a full Class A disclosure example.</li>
      </ul>
      <t>Negative coverage should include:</t>
      <ul>
        <li>missing, negative, non-integer, or overflowing segment numbers and interval values,</li>
        <li>duplicate CBOR map keys, invalid UTF-8, non-shortest encodings, and pure-bytewise rather than length-first map ordering,</li>
        <li>serial reuse, decrease, gap, wrap, and conflicting writers for one ledger and serial,</li>
        <li>a nonzero epoch predecessor and an incorrect non-epoch predecessor artifact digest,</li>
        <li>a predecessor from a different ledger or site,</li>
        <li>assignment based on source arrival, upstream validation or record-construction time, <tt>device_time</tt>, or <tt>ingest_time</tt>,</li>
        <li>placing an exactly-at-deadline acceptance into the expired interval or reopening a sealed segment,</li>
        <li>unsupported empty mode, in-place policy mutation, and an inaccurate close reason,</li>
        <li>duplicate-last reduction, missing leaf or parent domain prefix, or an incorrect recursive split,</li>
        <li>batch identity, number, count, deterministic partition, ordering, root, or leaf-union mismatch,</li>
        <li>manifest/artifact profile mismatch, unsafe or racy manifest path resolution, and producer claims of executed verifier checks,</li>
        <li>legacy day fields or mixed v1/v2 identifiers in a v2 artifact,</li>
        <li>a proof over <tt>segment_root</tt> instead of the authoritative segment-artifact digest, and</li>
        <li>reporting <tt>segment_chain_validation</tt> as executed without the required predecessor.</li>
      </ul>
      <t>
        Cross-implementation checks SHOULD verify byte-for-byte parity across
        at least two independent implementations. Interval tests MUST use a
        controllable fake elapsed-time source and restart tests MUST inject
        failures at persistence boundaries; conformance tests SHOULD NOT wait for
        real elapsed time. The canonical-record bytes are test inputs, not
        outputs reconstructed from transport fixtures. Any mismatch in leaf
        digests, artifact bytes, artifact digests, roots, assignments, or
        expected failures is a conformance failure.
      </t>
      <t>
        Vector bundles SHOULD include the
        <tt>commitment_profile_id</tt>.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="operations">
      <name>Operational Considerations</name>
      <t>
        This section consolidates deployment guidance for operators and
        follows the operational topics described in
        <xref target="I-D.ietf-opsawg-rfc5706bis"/>. It does not make
        operator policy part of the cryptographic commitment output, but it
        identifies the state and configuration that determine whether the
        committed evidence remains useful and verifiable.
      </t>
      <section numbered="true" toc="include" anchor="ops-time">
        <name>Record Timestamps and UTC Health</name>
        <t>
          Any <tt>ingest_time</tt> or <tt>device_time</tt> value is already part
          of the canonical-record byte string at the profile boundary. Its
          assignment, source authentication, accuracy, leap-second handling,
          and clock-health policy are upstream responsibilities. The ledger
          producer MUST preserve that value unchanged and MUST NOT use it for
          segment selection, renumbering, or reopening. Segment closure uses
          only the elapsed-time rules in <xref target="ops-segment"/>.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="ops-segment">
        <name>Segment Sequencing and Closure</name>
        <t>
          Operators MUST persist the active <tt>ledger_id</tt>, next emitted
          segment number, current closure-policy snapshot, open-interval state,
          record and byte counters, and artifact-write state across restart.
          Admission, artifact publication, and sequence-state advancement MUST
          use the atomic or recoverable protocol in
          <xref target="segment-formation"/> so a crash cannot lose an accepted
          record or reuse a published serial. Redundant
          gateways MUST use single-writer fencing or atomic shared allocation.
        </t>
        <t>
          Operators SHOULD monitor elapsed-timer health, closure delay,
          unexpected early-close reasons, serial conflicts, policy changes,
          and recovery closures. If deadline state cannot be recovered, the
          gateway MUST follow <xref target="segment-formation"/> rather than
          consulting UTC to reconstruct elapsed boundaries.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="ops-health">
        <name>Health and Fault Management</name>
        <t>
          Operators SHOULD monitor at least the following signals:
        </t>
        <ul>
          <li>canonical-record handoff, validation, admission, and durable-persistence failures,</li>
          <li>ledger-identity and segment-sequence persistence, writer fencing, and serial-conflict events,</li>
          <li>elapsed-timer health, closure delay, closure reason, and closure-policy revision,</li>
          <li>invalid canonical-record encoding and oversize-input rejection rates,</li>
          <li>segment-artifact write success, digest production, and segment-root calculation,</li>
          <li>anchoring backlog, calendar reachability, and proof-upgrade lag for OTS,</li>
          <li>status of the mandatory-to-implement <xref target="RFC3161"/> channel when selected for deployment use and of peer-signature channels when configured, and</li>
          <li>local storage pressure for retained record artifacts, segment artifacts, proof artifacts, and manifests.</li>
        </ul>
        <t>
          An operator-visible fault state SHOULD distinguish an invalid
          commitment artifact from a delayed or failed external anchoring
          channel. A delayed OTS proof, for example, is not by itself evidence
          that the authoritative segment artifact is malformed.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="ops-config">
        <name>Configuration Management</name>
        <t>
          Deployments SHOULD document the maximum canonical-record byte length,
          admission backpressure and durable-write behavior,
          <tt>closure_policy</tt>, record and size limits, permitted early-close
          triggers, artifact and proof retention periods, OTS calendars,
          optional TSA identities, anchoring policy, verifier strictness for
          optional channels, and any peer-signature quorum threshold and
          identity set. These settings are distinct and MUST NOT be silently
          substituted for one another.
        </t>
        <t>
          Transport, decryption, anti-replay, source buffering, source identity,
          and source-to-record mapping configuration are upstream of this
          profile. When one implementation contains both upstream and ledger
          functions, operator documentation SHOULD still identify the
          byte-level handoff and distinguish upstream failures from ledger
          admission or commitment failures. A configuration change that alters
          the canonical-record byte syntax or another commitment output requires
          the versioning action specified in <xref target="versioning"/>.
        </t>
        <t>
          When OTS is used, ledger producers SHOULD submit to multiple calendars
          operated by administratively distinct entities and retain disclosed
          OTS proof artifacts for at least as long as the corresponding segment
          artifacts remain available for verification.
        </t>
      </section>
      <section numbered="true" toc="include" anchor="ops-fault-results">
        <name>Fault-to-Verifier-Result Mapping</name>
        <t>
          Operational faults do not all have the same verifier meaning. Verifier
          output MUST distinguish at least the following cases when the
          condition is visible from disclosed artifacts or local verifier
          policy:
        </t>
        <dl newline="true" spacing="normal">
          <dt>OTS proof exists but is incomplete or awaiting upgrade</dt>
          <dd>
            Report the OTS channel as <tt>pending</tt>. Place
            <tt>x-ots-verification</tt> in <tt>checks_skipped</tt> with reason
            <tt>pending_proof</tt> unless validation was attempted and failed.
            Overall success is permitted only when local policy does not
            require completed OTS evidence.
          </dd>
          <dt><xref target="RFC3161"/> timestamp response is absent</dt>
          <dd>
            Report the TSA channel as <tt>missing</tt> when required by
            policy, or <tt>skipped</tt> with reason <tt>disabled</tt> when the
            channel is not configured. Report <tt>tsa_verification</tt> exactly
            once in either executed or skipped checks when applicable.
          </dd>
          <dt>Canonical-record handoff or admission durability is reported as uncertain</dt>
          <dd>
            Report the operational continuity condition and do not claim input
            completeness. Verification of a disclosed sealed segment can still
            succeed when its artifacts are internally consistent, but that
            success does not establish which upstream records should have been
            admitted.
          </dd>
          <dt>Segment sequence or elapsed-time state is lost</dt>
          <dd>
            Report a continuity break and any recovery closure. Do not report
            <tt>segment_chain_validation</tt> as successful across an unknown
            predecessor, serial conflict, or newly created ledger.
          </dd>
        </dl>
      </section>

      <section numbered="true" toc="include" anchor="ops-scaling">
        <name>Performance and Scaling</name>
        <t>
          Artifact size grows primarily with the number of accepted canonical
          records and the number of batches in a segment. Class A verification
          requires access to the disclosed canonical-record artifacts and scales
          with the number of records that must be decoded, hashed, and reduced
          into the segment root. Class C verification can be substantially smaller
          because it validates the segment-artifact digest and disclosed proof
          channels without public record-level recomputation. OTS submission
          traffic is one digest submission per emitted segment artifact per selected
          calendar; using multiple calendars increases availability but also
          increases submission attempts and proof-status tracking.
        </t>
        <t>
          Shorter segment intervals reduce the normal time to sealing and
          anchoring but increase artifact count, anchor submissions, storage,
          verifier work, and cadence metadata leakage. Longer intervals reduce
          that overhead but increase the amount of unsealed material and the
          size of each record-level verification. In <tt>emit</tt> mode, idle
          deployments also pay one artifact and anchor submission per interval;
          <tt>suppress</tt> mode avoids that cost but makes no continuous-
          coverage claim.
        </t>
      </section>

      <section numbered="true" toc="include" anchor="ops-verifying">
        <name>Verifying Correct Operation</name>
        <t>
          Operators SHOULD periodically run an independent verifier against a
          recently produced bundle using the same disclosure class that consumers
          are expected to rely on. A healthy run should confirm that disclosed
          artifacts are present, the <tt>commitment_profile_id</tt> is supported,
          the authoritative segment artifact is well formed, the segment-artifact digest
          matches binding metadata, disclosed adjacency passes segment-chain
          validation, expected checks appear exactly once in either
          <tt>checks_executed</tt> or <tt>checks_skipped</tt>, and configured
          proof channels report a status permitted by local policy and
          reported according to <xref target="ops-fault-results"/>. Operators SHOULD
          alert when required checks are silently absent, when OTS proofs remain
          pending beyond local policy, or when canonical-record handoff,
          elapsed-timer health, serial allocation, writer fencing, or segment-
          artifact-write faults occur.
        </t>
      </section>
    </section>

    <section numbered="true" toc="include" anchor="security">
      <name>Security Considerations</name>
      <t>
        This profile does not introduce new cryptographic primitives. Its
        security depends on a byte-preserving canonical-record handoff,
        deterministic commitment encoding, trustworthy ledger admission and
        elapsed-time handling, accurate verifier reporting, and disciplined
        artifact and proof handling. The threats below are stated in the threat-and-
        remediation style described by <xref target="RFC3552"/>. Unless
        explicitly stated otherwise, a successful verification result
        establishes only that the disclosed artifacts are internally
        consistent with this profile and with any validated proof channels.
      </t>
      <t><strong>Gateway Compromise and Pre-Commit Omission</strong></t>
      <t>
        An attacker can compromise the ledger producer or its canonical-record
        handoff and then fabricate byte strings, suppress proposed inputs before
        commitment, substitute different bytes, or assign a record to the wrong
        segment. This profile does not by itself detect a malicious producer; it
        makes outputs tamper-evident only after commitment, as described in
        <xref target="gateway-trust-boundary"/>. Operational guidance for
        admission persistence, elapsed time, health, and verification checks is
        consolidated in <xref target="operations"/>.
      </t>
      <t><strong>Segment Sequence Rollback, Fork, and Truncation</strong></t>
      <t>
        An attacker or failed multi-writer deployment can reuse or roll back a
        segment number, emit conflicting artifacts for one ledger and serial,
        substitute a predecessor from another ledger, or disclose only a chain
        prefix or suffix. Fresh ledger identity, single-writer fencing,
        contiguous serials, and full predecessor-artifact digest validation
        detect conflicts when the relevant artifacts are disclosed. They do
        not prove global completeness to an isolated verifier: a producer can
        still withhold undisclosed segments or a chain suffix. Verifier output
        MUST therefore distinguish validated adjacency from a completeness
        claim.
      </t>
      <t><strong>Upstream Admission and Semantic Substitution</strong></t>
      <t>
        An attacker can exploit an upstream transport, replay mechanism,
        credential system, decryption path, identifier mapping, or payload
        parser so that incorrect, duplicated, or misattributed record bytes are
        presented at the profile boundary. Those controls are outside this
        document. This profile neither prevents nor detects such an attack once
        the resulting byte string has been admitted. A separate upstream
        specification is needed for claims about source authentication,
        anti-replay, confidentiality, or source-to-record semantics, and a
        successful ledger verification MUST NOT be reported as validation of
        those claims.
      </t>
      <t><strong>Canonicalization, Profile, and Metadata Confusion</strong></t>
      <t>
        An attacker can exploit differences in CBOR validation, re-encoding,
        record occurrence handling, hash composition, or non-authoritative
        metadata handling while implementations still claim the same
        <tt>commitment_profile_id</tt>. An attacker can also present a
        verifier-facing manifest, batch-metadata projection, or OTS sidecar
        that does not match the authoritative segment artifact in the hope that a
        verifier will treat convenience metadata as authoritative. The
        mitigation is that this profile fixes the canonical-record byte syntax,
        deterministic encoding, and hash rules; requires producers and
        verifiers to hash the exact authoritative record bytes without
        re-encoding; treats the authoritative segment artifact as the
        cryptographic source of truth; requires verifiers to recompute
        commitment material from authoritative artifacts; requires the applicable
        <tt>commitment_profile_id</tt> to be disclosed and bound to the same
        segment-artifact digest, and requires standalone metadata projections and
        sidecars to match the authoritative artifact. Any future semantic or
        hash-composition change MUST use a new
        <tt>commitment_profile_id</tt>.
      </t>
      <t><strong>Artifact Mutation and Proof Substitution</strong></t>
      <t>
        An attacker can modify a committed segment artifact after disclosure, or
        can present a valid proof over the wrong artifact digest. The
        mitigation is that verifiers recompute the authoritative segment-artifact
        digest independently and compare it with the disclosed binding
        metadata before accepting any proof result. Mutation or substitution
        therefore changes the digest or its binding and causes verification to
        fail.
      </t>
      <t><strong>Calendar Withholding and Optional-Channel Downgrade</strong></t>
      <t>
        An attacker can operate or compromise a timestamping or attestation
        service so that proof issuance is delayed, withheld, or selectively
        unavailable, can present pending or placeholder proofs as if they were
        final attestations, or can exploit verifier policy that silently
        ignores a missing required channel. The channel-status vocabulary is
        defined in <xref target="proof-status-vocabulary"/>, and operational
        reporting for missing or pending channels is described in
        <xref target="ops-fault-results"/>.
      </t>
      <t><strong>UTC Timestamp Manipulation</strong></t>
      <t>
        An attacker can alter an upstream UTC source so that canonical records
        carry misleading <tt>ingest_time</tt> or <tt>device_time</tt> values.
        Timestamp assignment and source authentication are outside this
        profile, as described in <xref target="ops-time"/>. Verification can
        detect byte or artifact inconsistencies, but it cannot reconstruct true
        real-world time from a false admitted value. UTC changes MUST NOT affect
        segment membership or reopen sealed segments.
      </t>
      <t><strong>Segment Policy and Elapsed-Time Manipulation</strong></t>
      <t>
        An attacker can lengthen the closure interval, regress or freeze the
        elapsed-time source, alter an active policy, misstate a close reason, or
        race boundary processing in order to delay anchoring or assign a record
        to a different segment. Committing the policy snapshot and close reason
        makes the gateway's claim tamper-evident after sealing, while the
        serialized boundary algorithm and operational monitoring reduce
        accidental races. These controls do not independently prove that the
        gateway honestly observed real elapsed time. Likewise, a validated OTS
        proof establishes that the artifact existed no later than the validated
        timestamp; it does not prove when the segment opened or that every
        configured deadline was honored.
      </t>
      <t><strong>Resource Exhaustion</strong></t>
      <t>
        An attacker can flood a ledger producer with malformed, oversized, or
        excessive-rate canonical-record inputs in order to exhaust admission
        capacity, artifact storage, or verifier computation. Producers need
        deployment-appropriate input-size limits, rate controls, and
        backpressure at the byte-level handoff; relevant operational signals
        and sizing considerations are described in
        <xref target="ops-health"/> and <xref target="ops-scaling"/>. This
        profile does not define a complete denial-of-service defense.
      </t>
      <t><strong>Verification Scope, Completeness, and Disclosure</strong></t>
      <t>
        An attacker can rely on a successful verification result being
        misread as proof of dataset completeness, physical truth of
        measurements, or authorization for autonomous actuation. An attacker
        can also obtain sensitive information if disclosed bundles expose more
        record material than intended for the chosen disclosure class. This
        profile mitigates those risks only partially: verifier output is
        required to state the exercised verification scope, a successful
        result establishes internal consistency and proof binding for the
        disclosed bundle rather than completeness of all observed or emitted
        telemetry, and disclosure classes constrain what is expected to be
        published. Deployments that need stronger completeness, safety, or
        confidentiality guarantees must add external operational controls,
        independent observation, and access-control and retention policies
        that match the sensitivity of the disclosed artifacts.
      </t>
      <t>
        Even when payloads are withheld, manifests, segment artifacts, proof
        sidecars, and operational summaries can disclose source-activity
        metadata such as record counts, outage windows, and anchoring delay.
        Segment serials, interval values, close reasons, and
        the difference between emitted and suppressed empty intervals can add
        cadence and activity information. Deployments SHOULD account for that
        metadata exposure in disclosure and retention policy.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="privacy">
      <name>Privacy Considerations</name>
      <t>
        Telemetry payloads can include sensitive operational data. Operators
        should:
      </t>
      <ul>
        <li>minimize personally identifiable data in committed artifacts,</li>
        <li>separate identity metadata from measurement payload when possible,</li>
        <li>apply retention and access controls, and</li>
        <li>publish only data appropriate for the chosen disclosure class.</li>
      </ul>
      <t>
        Privacy-preserving disclosures remain valid, but they MUST NOT be
        described as publicly recomputable unless Class A conditions are met.
      </t>
      <t>
        Disclosure of verifier-facing manifests, canonical-record artifacts,
        segment artifacts, proof sidecars, and operational summaries can reveal
        source-activity patterns, outage windows, configured segment duration, empty-interval policy,
        anchoring cadence, and operational incidents even when payload values
        are withheld. Short intervals and <tt>suppress</tt> mode can make
        activity timing especially visible. Operators SHOULD treat these
        artifacts as metadata-bearing evidence and apply disclosure, retention,
        and access-control policy accordingly.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="iana">
      <name>IANA Considerations</name>
      <t>
        This section follows the guidance in <xref target="RFC8126"/> and
        provides the complete instructions for the Internet Assigned
        Numbers Authority (IANA).
      </t>

      <section numbered="true" toc="default" anchor="iana-media-type">
        <name>Media Types Registry</name>
        <t>
          IANA is requested to register the following media types in the
          standards tree of the "Media Types" registry in accordance with
          <xref target="RFC6838"/>:
        </t>
        <t>
          Because this document is intended for publication on the Independent
          Submission Stream, the standards-tree registrations in this section
          require IESG approval under <xref target="RFC6838"/>.
        </t>
        <t>
          Type name: <tt>application</tt>
        </t>
        <t>
          Subtype name: <tt>verifiable-telemetry-segment+cbor</tt>
        </t>
        <t>
          Required parameters: none
        </t>
        <t>
          Optional parameters: none
        </t>
        <t>
          Encoding considerations: binary
        </t>
        <t>
          Security considerations: see <xref target="security"/>, especially
          profile and metadata confusion, artifact mutation, proof
          substitution, disclosure scope, and resource exhaustion.
        </t>
        <t>
          Interoperability considerations: this media type identifies the
          authoritative segment-artifact family defined by
          <xref target="cbor-profile"/>, <xref target="merkle-policy"/>,
          <xref target="segment-formation"/>,
          <xref target="segment-artifact-schema"/>, and
          <xref target="segment-chaining"/>. A recipient uses the artifact's
          in-band <tt>commitment_profile_id</tt> to select canonical CBOR, hash,
          and Merkle semantics for a verification claim.
        </t>
        <t>
          Published specification: this document, especially
          <xref target="cbor-profile"/>, <xref target="merkle-policy"/>,
          <xref target="segment-formation"/>,
          <xref target="segment-artifact-schema"/>, and
          <xref target="segment-chaining"/>.
        </t>
        <t>
          Applications that use this media type: producers, verifiers,
          disclosure tools, and archival or audit systems that exchange or
          retain authoritative segment artifacts.
        </t>
        <t>
          Fragment identifier considerations: no fragment identifier syntax is
          defined by this document for
          <tt>application/verifiable-telemetry-segment+cbor</tt>.
          Fragment identifiers, if present, are processed according to the
          <tt>+cbor</tt> structured syntax suffix rules in
          <xref target="RFC8949"/>.
        </t>
        <t>
          Additional information:
        </t>
        <ul>
          <li>Magic number(s): none</li>
          <li>File extension(s): none</li>
          <li>Macintosh file type code(s): none</li>
        </ul>
        <t>
          Person &amp; email address to contact for further information:
          Bilal El Khatabi &lt;elkhatabibilal@gmail.com&gt;
        </t>
        <t>
          Intended usage: COMMON
        </t>
        <t>
          Restrictions on usage: none
        </t>
        <t>
          Author: Bilal El Khatabi
        </t>
        <t>
          Change controller: IESG
        </t>

        <t>
          Type name: <tt>application</tt>
        </t>
        <t>
          Subtype name: <tt>verifiable-telemetry-manifest+json</tt>
        </t>
        <t>
          Required parameters: none
        </t>
        <t>
          Optional parameters: none
        </t>
        <t>
          Encoding considerations: binary
        </t>
        <t>
          Security considerations: see <xref target="security"/>, especially
          profile and metadata confusion, artifact mutation, stale or
          substituted manifests, disclosure scope, and resource exhaustion.
        </t>
        <t>
          Interoperability considerations: this media type identifies the
          verification manifest defined by <xref target="artifacts"/>,
          <xref target="verify"/>, and <xref target="appendix-c"
          format="title"/>. The
          manifest is a metadata and digest-binding surface;
          it is not an authoritative commitment artifact. A recipient still
          needs the referenced authoritative artifact and MUST compare the
          manifest's <tt>commitment_profile_id</tt> with the artifact's in-band
          value to interpret and verify a claim. The JSON representation
          conforms to <xref target="RFC8259"/>.
        </t>
        <t>
          Published specification: this document, especially
          <xref target="artifacts"/>, <xref target="verify"/>, and
          <xref target="appendix-c" format="title"/>.
        </t>
        <t>
          Applications that use this media type: producers, verifiers,
          disclosure tools, publication services, and archival or audit
          systems that exchange verification manifests.
        </t>
        <t>
          Fragment identifier considerations: no fragment identifier syntax is
          defined by this document for
          <tt>application/verifiable-telemetry-manifest+json</tt>.
        </t>
        <t>
          Additional information:
        </t>
        <ul>
          <li>Magic number(s): none</li>
          <li>File extension(s): none</li>
          <li>Macintosh file type code(s): none</li>
        </ul>
        <t>
          Person &amp; email address to contact for further information:
          Bilal El Khatabi &lt;elkhatabibilal@gmail.com&gt;
        </t>
        <t>
          Intended usage: COMMON
        </t>
        <t>
          Restrictions on usage: none
        </t>
        <t>
          Author: Bilal El Khatabi
        </t>
        <t>
          Change controller: IESG
        </t>
      </section>

      <section numbered="true" toc="default" anchor="iana-no-cbor-tag">
        <name>No CBOR Tag Allocation</name>
        <t>
          This document requests no new CBOR tag allocation. Commitment bytes
          defined by <xref target="cbor-profile"/> forbid CBOR tags, and the
          authoritative segment artifact defined by
          <xref target="segment-artifact-schema"/> does not require additional tag
          semantics for exchange.
        </t>
      </section>

      <section numbered="true" toc="default" anchor="iana-profile-id-policy">
        <name>commitment_profile_id Registry</name>
        <t>
          IANA is requested to create the Verifiable Telemetry Ledger
          Commitment Profiles registry under a new Verifiable Telemetry Ledger
          Parameters registry group. This registry is tied to the
          <tt>application/verifiable-telemetry-segment+cbor</tt> media type
          registered in <xref target="iana-media-type"/> and records values of
          the <tt>commitment_profile_id</tt> sub-code carried in that
          representation. Registry change control belongs to the Independent
          Stream. The registry records four columns:
          <tt>Identifier</tt>, <tt>Description</tt>, <tt>Reference</tt>, and
          <tt>Change Controller</tt>.
        </t>
        <t>
          A registered identifier is 1 through 63 lower-case ASCII characters.
          It begins with a letter, ends with a letter or digit, and otherwise
          contains only lower-case letters, digits, and single hyphens between
          non-hyphen characters. Comparison is case-sensitive; an identifier
          containing an upper-case letter is invalid. Identifiers beginning
          with <tt>x-</tt> are reserved for Private Use, are not registered,
          and MUST NOT be used as interoperable public profile identifiers.
        </t>
        <t>
          The registration policy is RFC Required as defined by
          <xref target="RFC8126"/> and constrained by <xref target="RFC8726"/>
          for the Independent Submission Stream.
        </t>
        <t>
          A registration request MUST provide all four registry fields and an
          RFC reference. The referenced RFC MUST define the canonical input
          bytes, deterministic encoding rules, hash and tree calculation,
          authoritative artifact schema, verification procedure, profile
          identifier binding, positive and negative conformance vectors, and
          relevant security considerations. An identifier that does not satisfy
          the syntax above is invalid and MUST NOT be registered.
        </t>
        <t>
          An update request requires authorization from the registered change
          controller and an RFC reference. An update MUST NOT change
          commitment bytes or verification semantics for an existing
          identifier; such a change requires a new identifier. A deprecated
          entry remains recorded with its reference and MUST NOT be reassigned.
        </t>
        <t>
          This registry is created by a document published on the Independent
          Submission Stream. Any issues that arise with management of the
          registry will be resolved by IANA in consultation with the Independent
          Submissions Editor.
        </t>
        <table>
          <name>Initial Commitment Profile Registration</name>
          <thead>
            <tr>
              <th>Identifier</th>
              <th>Description</th>
              <th>Reference</th>
              <th>Change Controller</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>verifiable-telemetry-canonical-cbor-v2</td>
              <td>Deterministic CBOR canonical-record and serial-segment profile with domain-separated SHA-256 tree commitments</td>
              <td>This document</td>
              <td>Independent Stream</td>
            </tr>
          </tbody>
        </table>
        <t>
          This document requests no CoAP Content-Format entry.
        </t>
      </section>
    </section>

    <section numbered="true" toc="include" anchor="applicability">
      <name>Applicability and Deployment Models</name>
      <t>
        This profile standardizes the durable evidence object produced after
        local telemetry admission and before external publication. It is useful
        where the source protocol and application semantics vary, but later
        auditors need a common way to recompute exactly what bytes were
        committed, how they were grouped, and which timestamped artifact binds
        them.
      </t>
      <ul>
        <li>Intermittent environmental or agricultural collectors can admit records locally, seal elapsed-time segments during backhaul outages, and disclose recomputable evidence later.</li>
        <li>Industrial gateways can retain an independently verifiable operational record without requiring the field transport to expose one universal framing or payload schema.</li>
        <li>Multi-vendor collectors can export the same segment and manifest contract to archives, regulators, partners, or a separately specified transparency service.</li>
      </ul>
      <t>
        This profile is not appropriate when an application needs proof of
        sensor truth, source authentication, complete upstream ingestion, or
        the semantics of source-to-record projection; those properties require
        upstream specifications and evidence. It also does not replace SCITT or
        another publication system: such a system can publish a VTL artifact,
        while this document defines how the local artifact is formed and
        verified.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="interop-notes">
      <name>Future Extension Points</name>
      <t>
        The following items are outside the baseline profile defined by this
        document. They identify extension surfaces that would require separate
        specification before they are used as interoperability claims.
      </t>
      <ul>
        <li>A separate upstream admission profile can define transport framing, authentication and decryption, anti-replay behavior, identifier and message-type mappings, payload schemas, source-to-record projection, and conformance vectors up to the canonical-record byte handoff.</li>
        <li>A future specification can register media types for exported evidence bundles or additional artifact families.</li>
        <li>A future SCITT publication profile can define statement content, submission procedure, and verifier processing for published verification manifests or exported evidence bundles.</li>
        <li>A future disclosure profile can standardize a universal Class B withheld-material artifact format.</li>
        <li>A future COSE Receipts profile can register a suitable verifiable-data-structure algorithm and define receipt encodings for VTL disclosure.</li>
        <li>A future registry policy can cover disclosure-class and anchor-status vocabularies if multiple independent specifications need shared allocation.</li>
        <li>A future commitment profile can define a different hash algorithm or tree construction under a distinct <tt>commitment_profile_id</tt>.</li>
      </ul>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
      <reference anchor="RFC2119" target="https://www.rfc-editor.org/rfc/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="Scott Bradner" initials="S." surname="Bradner"/>
          <date year="1997" month="March"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="Benjamin Leiba" initials="B." surname="Leiba"/>
          <date year="2017" month="May"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
      <reference anchor="RFC8949" target="https://www.rfc-editor.org/rfc/rfc8949">
        <front>
          <title>Concise Binary Object Representation (CBOR)</title>
          <author fullname="Carsten Bormann" initials="C." surname="Bormann"/>
          <author fullname="Paul Hoffman" initials="P." surname="Hoffman"/>
          <date year="2020" month="December"/>
        </front>
        <seriesInfo name="STD" value="94"/>
        <seriesInfo name="RFC" value="8949"/>
        <seriesInfo name="DOI" value="10.17487/RFC8949"/>
      </reference>
      <reference anchor="RFC6838" target="https://www.rfc-editor.org/rfc/rfc6838">
        <front>
          <title>Media Type Specifications and Registration Procedures</title>
          <author fullname="Ned Freed" initials="N." surname="Freed"/>
          <author fullname="John Klensin" initials="J." surname="Klensin"/>
          <author fullname="Ted Hansen" initials="T." surname="Hansen"/>
          <date year="2013" month="January"/>
        </front>
        <seriesInfo name="BCP" value="13"/>
        <seriesInfo name="RFC" value="6838"/>
        <seriesInfo name="DOI" value="10.17487/RFC6838"/>
      </reference>
      <reference anchor="RFC8126" target="https://www.rfc-editor.org/rfc/rfc8126">
        <front>
          <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
          <author fullname="Michelle Cotton" initials="M." surname="Cotton"/>
          <author fullname="Benjamin Leiba" initials="B." surname="Leiba"/>
          <author fullname="Thomas Narten" initials="T." surname="Narten"/>
          <date year="2017" month="June"/>
        </front>
        <seriesInfo name="BCP" value="26"/>
        <seriesInfo name="RFC" value="8126"/>
        <seriesInfo name="DOI" value="10.17487/RFC8126"/>
      </reference>
      <reference anchor="RFC8726" target="https://www.rfc-editor.org/rfc/rfc8726">
        <front>
          <title>How Requests for IANA Action Will Be Handled on the Independent Stream</title>
          <author fullname="Adrian Farrel" initials="A." surname="Farrel"/>
          <date year="2020" month="December"/>
        </front>
        <seriesInfo name="RFC" value="8726"/>
        <seriesInfo name="DOI" value="10.17487/RFC8726"/>
      </reference>
      <reference anchor="RFC3161" target="https://www.rfc-editor.org/rfc/rfc3161">
        <front>
          <title>Internet X.509 Public Key Infrastructure Timestamp Protocol (TSP)</title>
          <author fullname="C. Adams"/>
          <author fullname="P. Cain"/>
          <author fullname="D. Pinkas"/>
          <author fullname="R. Zuccherato"/>
          <date year="2001" month="August"/>
        </front>
        <seriesInfo name="RFC" value="3161"/>
        <seriesInfo name="DOI" value="10.17487/RFC3161"/>
      </reference>
      <reference anchor="RFC8610" target="https://www.rfc-editor.org/rfc/rfc8610">
        <front>
          <title>Concise Data Definition Language (CDDL): A Notational Convention to Express CBOR and JSON Data Structures</title>
          <author fullname="Carsten Bormann" initials="C." surname="Bormann"/>
          <author fullname="Paul Hoffman" initials="P." surname="Hoffman"/>
          <date year="2019" month="June"/>
        </front>
        <seriesInfo name="RFC" value="8610"/>
        <seriesInfo name="DOI" value="10.17487/RFC8610"/>
      </reference>
      <reference anchor="RFC9162" target="https://www.rfc-editor.org/rfc/rfc9162">
        <front>
          <title>Certificate Transparency Version 2.0</title>
          <author fullname="B. Laurie"/>
          <author fullname="E. Messeri"/>
          <author fullname="R. Stradling"/>
          <date year="2021" month="December"/>
        </front>
        <seriesInfo name="RFC" value="9162"/>
        <seriesInfo name="DOI" value="10.17487/RFC9162"/>
      </reference>
      <reference anchor="RFC8259" target="https://www.rfc-editor.org/rfc/rfc8259">
        <front>
          <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
          <author fullname="Tim Bray" initials="T." surname="Bray"/>
          <date year="2017" month="December"/>
        </front>
        <seriesInfo name="STD" value="90"/>
        <seriesInfo name="RFC" value="8259"/>
        <seriesInfo name="DOI" value="10.17487/RFC8259"/>
      </reference>
      <reference anchor="RFC6234" target="https://www.rfc-editor.org/rfc/rfc6234">
        <front>
          <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
          <author fullname="D. Eastlake 3rd"/>
          <author fullname="T. Hansen"/>
          <date year="2011" month="May"/>
        </front>
        <seriesInfo name="RFC" value="6234"/>
        <seriesInfo name="DOI" value="10.17487/RFC6234"/>
      </reference>
      </references>

      <references>
        <name>Informative References</name>
      <reference anchor="I-D.ietf-opsawg-rfc5706bis" target="https://datatracker.ietf.org/doc/draft-ietf-opsawg-rfc5706bis/">
        <front>
          <title>Guidelines for Considering Operations and Management in IETF Specifications</title>
          <author fullname="Benoit Claise" initials="B." surname="Claise"/>
          <author fullname="Joe Clarke" initials="J." surname="Clarke"/>
          <author fullname="Adrian Farrel" initials="A." surname="Farrel"/>
          <author fullname="Samier Barguil" initials="S." surname="Barguil"/>
          <author fullname="Carlos Pignataro" initials="C." surname="Pignataro"/>
          <author fullname="Ran Chen" initials="R." surname="Chen"/>
          <date year="2026" month="June" day="26"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-ietf-opsawg-rfc5706bis-05"/>
      </reference>
      <reference anchor="RFC3552" target="https://www.rfc-editor.org/rfc/rfc3552">
        <front>
          <title>Guidelines for Writing RFC Text on Security Considerations</title>
          <author fullname="S. Rescorla"/>
          <author fullname="B. Korver"/>
          <date year="2003" month="July"/>
        </front>
        <seriesInfo name="BCP" value="72"/>
        <seriesInfo name="RFC" value="3552"/>
        <seriesInfo name="DOI" value="10.17487/RFC3552"/>
      </reference>
      <reference anchor="RFC8785" target="https://www.rfc-editor.org/rfc/rfc8785">
        <front>
          <title>JSON Canonicalization Scheme (JCS)</title>
          <author fullname="Anders Rundgren" initials="A." surname="Rundgren"/>
          <author fullname="B. Jordan"/>
          <author fullname="S. Erdtman"/>
          <date year="2020" month="June"/>
        </front>
        <seriesInfo name="RFC" value="8785"/>
        <seriesInfo name="DOI" value="10.17487/RFC8785"/>
      </reference>
      <reference anchor="OTS" target="https://opentimestamps.org/">
        <front>
          <title>OpenTimestamps Protocol and Tooling</title>
          <author>
            <organization>OpenTimestamps Project</organization>
          </author>
          <date year="2016"/>
        </front>
      </reference>
      </references>
    </references>

    <section numbered="true" toc="include" anchor="appendix-a">
      <name>Example Verification Manifest</name>
      <t>
        This appendix shows a representative verification manifest. A
        concrete deployment can carry additional operational fields in the
        defined extension containers; the example below captures the baseline
        verification surface described here.
        Operational summaries can be carried as deployment-specific extensions,
        but they are not substitutes for canonical-record or segment-artifact
        authority and are not required by the disclosure classes.
      </t>
      <sourcecode type="json"><![CDATA[
{
 "version": 2,
 "ledger_id": "b7a1d5e40c6f438e9a75db27c96f31aa",
 "site_id": "an-001",
 "segment_number": "7",
 "commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
 "disclosure_class": "A",
 "artifacts": {
  "segment_cbor": {
   "path": "segments/00000000000000000007.cbor",
   "sha256": "<64 hex chars>"
  },
  "predecessor_segment_cbor": {
   "path": "segments/00000000000000000006.cbor",
   "sha256": "<64 hex chars>"
  },
  "records": [
   {
    "path": "records/device-003-00000006.cbor",
    "sha256": "<64 hex chars>"
   },
   {
    "path": "records/device-003-00000007.cbor",
    "sha256": "<64 hex chars>"
   }
  ],
  "segment_json": {
   "path": "segments/00000000000000000007.json",
   "sha256": "<64 hex chars>"
  },
  "segment_sha256": {
   "path": "segments/00000000000000000007.cbor.sha256",
   "sha256": "<64 hex chars>"
  },
  "tsa_tsr": {
   "path": "segments/00000000000000000007.tsr",
   "sha256": "<64 hex chars>"
  },
  "segment_ots": {
   "path": "segments/00000000000000000007.cbor.ots",
   "sha256": "<64 hex chars>"
  },
  "segment_ots_meta": {
   "path": "segments/00000000000000000007.ots.meta.json",
   "sha256": "<64 hex chars>"
  }
 },
 "anchoring": {
  "tsa": { "status": "complete" },
  "ots": { "status": "complete" },
  "peer": { "status": "skipped" }
 }
}
]]></sourcecode>
      <t>
        A verifier result is a separate object. For example:
      </t>
      <sourcecode type="json"><![CDATA[
{
 "version": 2,
 "artifact_sha256": "<64 hex chars>",
 "commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
 "disclosure_class": "A",
 "verification_scope": "public_recompute",
 "checks_executed": [
  "bundle_disclosure_validation",
  "verification_manifest_validation",
  "segment_artifact_validation",
  "segment_chain_validation",
  "record_level_recompute",
  "batch_metadata_validation",
  "segment_digest_binding",
  "tsa_verification"
 ],
 "checks_skipped": [],
 "channels": {
  "tsa": { "status": "verified" },
  "ots": { "status": "verified", "check": "x-ots-verification" }
 },
 "policy": { "optional_channel_failure": "warn" },
 "record_multiset_root": "<64 hex chars>",
 "overall": "success"
}
]]></sourcecode>
    </section>

    <section numbered="true" toc="include" anchor="appendix-b">
      <name>Conformance Vector Material</name>
      <t>
        The figure below is a reader-oriented sketch of the
        <tt>verifiable-telemetry-canonical-cbor-v2</tt> conformance-vector bundle shape and
        naming only. It is illustrative and is not itself a complete
        machine-readable vector corpus.
      </t>
      <t>
        The exact compact known-answer vector later in this appendix is
        normative for <tt>verifiable-telemetry-canonical-cbor-v2</tt>. The
        surrounding reader-oriented sketches remain illustrative.
      </t>
      <t>
        Wrapped hexadecimal values in this appendix are presentation-only; a
        verifier or implementer should concatenate adjacent lines without
        inserting whitespace.
      </t>
      <t>
        The fixtures below are reader-oriented decoded views, not upstream
        transport or projection fixtures. A machine-readable vector corpus for
        this profile MUST carry the exact canonical-record byte strings as its
        starting inputs together with their expected leaf digests.
      </t>
      <t>
        In these reader-oriented sketches, <tt>kind</tt> is shown as the
        unsigned value carried in the authoritative CBOR array. Its application
        meaning is outside this profile.
      </t>
      <figure>
        <artwork type="ascii-art"><![CDATA[
commitment_profile_id:
  verifiable-telemetry-canonical-cbor-v2

fixture record_a:
  device_id: "0000000000000065"
  fc: 1
  ingest_time: 1772366400
  device_time: null
  kind: 250
  payload.temp_c: 21.5

fixture record_b:
  device_id: "0000000000000066"
  fc: 2
  ingest_time: 1772367000
  device_time: null
  kind: 250
  payload.temp_c: 22.0

fixture record_c:
  device_id: "0000000000000067"
  fc: 3
  ingest_time: 1772367600
  device_time: null
  kind: 250
  payload.temp_c: 22.5

segment_record_v2:
  version: 2
  commitment_profile_id: verifiable-telemetry-canonical-cbor-v2
  ledger_id: b7a1d5e40c6f438e9a75db27c96f31aa
  site_id: an-001
  segment_number: 7
  closure_policy.version: 1
  closure_policy.interval_ms: 86400000
  closure_policy.batch_record_limit: 1024
  closure_policy.record_limit: null
  closure_policy.size_limit_bytes: null
  closure_policy.empty_mode: suppress
  close_reason: interval
  prev_segment_sha256: <SHA-256 of exact segment 6 CBOR>
  batches: <ordered batch objects>
  segment_root: <root over the segment leaf multiset>

class-a-bundle-v2:
  disclosure_class: A
  commitment_profile_id: verifiable-telemetry-canonical-cbor-v2
  required_artifact_1: records/<record-id>.cbor
  required_artifact_2: segments/<segment-number>.cbor
  required_artifact_3: segments/<segment-number>.tsr
  verifier_check_1: bundle_disclosure_validation
  verifier_check_2: segment_artifact_validation
  verifier_check_3: segment_chain_validation
  verifier_check_4: record_level_recompute
  verifier_check_5: batch_metadata_validation
  verifier_check_6: segment_digest_binding
  verifier_check_7: tsa_verification

required_fail_cases:
  - serial reuse, decrease, gap, or wrap
  - wrong predecessor artifact digest or ledger identity
  - record accepted exactly at deadline assigned to old interval
  - timestamp-driven reassignment or reopening of sealed segment
  - in-place closure-policy mutation
  - invalid empty-mode behavior
  - batch identity, number, count, ordering, or root mismatch
  - batch partition does not follow batch_record_limit
  - manifest profile identifier differs from the in-band artifact value
  - proof covers segment_root instead of segment artifact digest
]]></artwork>
      </figure>
      <t>
        The following compact known-answer vector is normative for
        <tt>verifiable-telemetry-canonical-cbor-v2</tt>. Hexadecimal values are
        lowercase and unprefixed. It encodes the epoch segment: the outer
        segment and both embedded batches use <tt>segment_number = 0</tt>, and
        <tt>prev_segment_sha256</tt> is 32 zero octets. The segment uses
        <tt>batch_record_limit = 2</tt>.
      </t>
      <sourcecode type="text"><![CDATA[
record_1 = 87014800000000000000010100f600f6
leaf_1 = b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26
record_2 = 87014800000000000000020201f600f6
leaf_2 = b5227357cf5d0619914971d8dc5218c5a99260bc5d5e1b60cb1083a911a2acaf
record_3 = 87014800000000000000030302f600f6
leaf_3 = 4f82e3e7ee90a111774dd951471a31d4582e0908a0bd5fd63c0080c0231f40cc

sorted_leaves =
  4f82e3e7ee90a111774dd951471a31d4582e0908a0bd5fd63c0080c0231f40cc
  b5227357cf5d0619914971d8dc5218c5a99260bc5d5e1b60cb1083a911a2acaf
  b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26
batch_0_root = 554491e4edf28061622396b83a870db4652211557127c664c6be1c4ad66471ff
batch_1_root = b83bc27f2d8be3a66373af24e6af3eeffff99ff0696ae18c70e379e853796d26
segment_root = bc6502552ed0c515f58d1c632e54db37594042609b59838eb0d5b3d5842aa054

segment_cbor =
  aa676261746368657382a865636f756e740267736974655f696466616e2d303031
  6776657273696f6e02696c65646765725f69647820623761316435653430633666
  34333865396137356462323763393666333161616b6c6561665f68617368657382
  784034663832653365376565393061313131373734646439353134373161333164
  343538326530393038613062643566643633633030383063303233316634306363
  784062353232373335376366356430363139393134393731643864633532313863
  356139393236306263356435653162363063623130383361393131613261636166
  6b6d65726b6c655f726f6f74784035353434393165346564663238303631363232
  333936623833613837306462343635323231313535373132376336363463366265
  3163346164363634373166666c62617463685f6e756d626572006e7365676d65
  6e745f6e756d62657200a865636f756e740167736974655f696466616e2d3030
  316776657273696f6e02696c65646765725f696478206237613164356534306336
  6634333865396137356462323763393666333161616b6c6561665f686173686573
  817840623833626332376632643862653361363633373361663234653661663365
  656666666639396666303639366165313863373065333739653835333739366432
  366b6d65726b6c655f726f6f747840623833626332376632643862653361363633
  373361663234653661663365656666666639396666303639366165313863373065
  333739653835333739366432366c62617463685f6e756d626572016e7365676d
  656e745f6e756d6265720067736974655f696466616e2d303031677665727369
  6f6e02696c65646765725f696478206237613164356534306336663433386539
  6137356462323763393666333161616c636c6f73655f726561736f6e68696e74
  657276616c6c7365676d656e745f726f6f747840626336353032353532656430
  633531356635386431633633326535346462333735393430343236303962353938
  333865623064356233643538343261613035346e636c6f737572655f706f6c69
  6379a66776657273696f6e016a656d7074795f6d6f6465687375707072657373
  6b696e74657276616c5f6d731a05265c006c7265636f72645f6c696d6974f670
  73697a655f6c696d69745f6279746573f67262617463685f7265636f72645f6c
  696d6974026e7365676d656e745f6e756d6265720073707265765f7365676d65
  6e745f73686132353678403030303030303030303030303030303030303030303030
  30303030303030303030303030303030303030303030303030303030303030303030
  3030303030303075636f6d6d69746d656e745f70726f66696c655f69647826766572
  69666961626c652d74656c656d657472792d63616e6f6e6963616c2d63626f722d76
  32
segment_sha256 = ce76302d1fcbf713097c0d70070b6a651bcd97e7855213aaf422b0ff9226708c

three_identical_record_1_root =
  05ddc48e556d67534bf7960a70209696ca9eeb6f18d5595358e7f4804ec87701
four_identical_record_1_root =
  d5d26faa3f54d81d8173700a48d9286179c9d35685d464183a99b1e966f1dfd8
]]></sourcecode>
      <t>
        A published machine-readable vector set can carry exact canonical
        bytes, digests, expected roots, and the applicable
        <tt>commitment_profile_id</tt>. The reader-oriented sketches in this
        appendix are illustrative; the exact compact known-answer vector above
        is normative.
      </t>
    </section>

    <section numbered="true" toc="include" anchor="appendix-c">
      <name>Verification Manifest and Result CDDL</name>
      <t>
        This appendix defines the Concise Data Definition Language
        (CDDL) (<xref target="RFC8610"/>) shape for the verification
        producer manifest and the separate verifier result. It captures the
        verification surface described here and
        provides explicit containers for deployment-specific additions.
        Producer manifests and verifier results MUST be UTF-8 JSON texts under
        <xref target="RFC8259"/> and MUST reject duplicate object member names.
      </t>
      <t>
        Check names are drawn from the standardized vocabulary defined in
        <xref target="verify"/>; deployment-specific extensions MUST use
        separate names beginning with <tt>x-</tt> that do not redefine those
        identifiers.
      </t>
      <t>
        The <tt>relative-path</tt> rule below is intentionally structural. RFC
        8610 regular expressions use the XML Schema dialect and cannot
        portably express all cross-platform path and filesystem-containment
        checks. Implementations MUST apply the semantic path rules in
        <xref target="artifacts"/>, including backslash, drive-prefix, UNC,
        colon, control-character, dot-component, symbolic-link, reparse-point,
        and race-resistant containment checks.
      </t>
      <t>
        <tt>segment_cbor</tt> is the only universally required convenience-key
        entry. Record lists, standalone batch projections, JSON projections,
        digest files, and operational summaries are optional at the schema
        level; disclosure-class rules determine when record or proof material
        is required. A Class C manifest does not require source identifiers,
        upstream transport counters, or a records directory.
      </t>
      <t>
        <tt>segment_number</tt> is a JSON string containing the shortest
        unsigned base-10 representation of a uint64: <tt>0</tt>, or a digit
        from <tt>1</tt> through <tt>9</tt> followed by zero or more digits. Its
        numeric value MUST NOT exceed 18446744073709551615. This avoids loss
        of precision in JSON implementations whose exact integer range ends at
        2^53-1. The lexical rules for <tt>relative-path</tt>,
        <tt>uint64-decimal</tt>, <tt>hex32</tt>, <tt>hex64</tt>, and extension
        check names are normative prose constraints in addition to the
        structural CDDL.
      </t>
      <sourcecode type="cddl"><![CDATA[
verification-manifest-v2 = {
  "version": 2,
  "ledger_id": hex32,
  "site_id": tstr,
  "segment_number": uint64-decimal,
  "commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
  "disclosure_class": disclosure-class,
  "artifacts": artifacts,
  "anchoring": anchoring,
  ? "operational_summary": { * tstr => json-data },
  ? "extensions": { * tstr => json-data },
}

artifacts = {
  "segment_cbor": artifact-ref,
  ? "predecessor_segment_cbor": artifact-ref,
  ? "records": [* artifact-ref],
  ? "batches": [* artifact-ref],
  ? "segment_json": artifact-ref,
  ? "segment_sha256": artifact-ref,
  ? "segment_ots": artifact-ref,
  ? "segment_ots_meta": artifact-ref,
  ? "peer_attest": artifact-ref,
  ? "tsa_info": artifact-ref,
  ? "tsa_tsr": artifact-ref,
  ? "extensions": { * tstr => artifact-ref }
}

artifact-ref = {
  "path": relative-path,
  "sha256": hex64
}

anchoring = {
  ? "tsa": producer-channel-state,
  ? "ots": producer-channel-state,
  ? "peer": producer-channel-state
}

producer-channel-state = {
  "status":
    "verified" / "pending" / "missing" /
    "failed" / "skipped" / "complete"
}

verification-result-v2 = {
  "version": 2,
  "artifact_sha256": hex64,
  "commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
  "disclosure_class": disclosure-class,
  "verification_scope":
    "public_recompute" / "partial_verification" / "anchor_only",
  "checks_executed": [* check-name],
  "checks_skipped": [* skipped-check],
  ? "channels": { * tstr => verifier-channel-result },
  ? "policy": { * tstr => json-data },
  ? "record_multiset_root": hex64,
  "overall": "success" / "partial" / "failure"
}

check-name = standardized-check-name / extension-check-name

standardized-check-name =
  "bundle_disclosure_validation" /
  "verification_manifest_validation" /
  "segment_artifact_validation" /
  "segment_chain_validation" /
  "record_level_recompute" /
  "batch_metadata_validation" /
  "segment_digest_binding" /
  "tsa_verification"

extension-check-name = tstr

skipped-check = {
  "check": check-name,
  "reason": tstr
}

verifier-channel-result = {
  "status":
    "verified" / "pending" / "missing" /
    "failed" / "skipped" / "complete",
  ? "reason": tstr,
  ? "detail": tstr,
  ? "diagnostic": tstr,
  ? "check": check-name
}

disclosure-class = "A" / "B" / "C"
relative-path = tstr
uint64-decimal = tstr
hex32 = tstr
hex64 = tstr
json-data =
  nil / bool / int / float / tstr /
  [* json-data] / { * tstr => json-data }
]]></sourcecode>
    </section>

    <section numbered="true" toc="include" anchor="appendix-d">
      <name>Segment Artifact CDDL</name>
      <t>
        This appendix gives the structural CDDL for v2 segment and embedded
        batch artifacts. The lexical and cross-field requirements in
        <xref target="segment-artifact-schema"/>, the formation rules in
        <xref target="segment-formation"/>, and the chain rules in
        <xref target="segment-chaining"/> are normative in addition to this
        structural shape.
      </t>
      <sourcecode type="cddl"><![CDATA[
segment-record-v2 = {
  "version": 2,
  "commitment_profile_id": "verifiable-telemetry-canonical-cbor-v2",
  "ledger_id": hex32,
  "site_id": tstr,
  "segment_number": uint64,
  "closure_policy": segment-closure-policy-v1,
  "close_reason": close-reason,
  "prev_segment_sha256": hex64,
  "batches": [* segment-batch-v2],
  "segment_root": hex64
}

segment-batch-v2 = {
  "version": 2,
  "ledger_id": hex32,
  "site_id": tstr,
  "segment_number": uint64,
  "batch_number": uint64,
  "merkle_root": hex64,
  "count": positive-uint64,
  "leaf_hashes": [+ hex64]
}

segment-closure-policy-v1 = {
  "version": 1,
  "interval_ms": positive-uint64,
  "batch_record_limit": positive-uint64,
  "record_limit": positive-uint64 / nil,
  "size_limit_bytes": positive-uint64 / nil,
  "empty_mode": "emit" / "suppress"
}

close-reason =
  "interval" /
  "reconfigure" /
  "record_limit" /
  "size_limit" /
  "shutdown" /
  "recovery" /
  "manual"

uint64 = 0..18446744073709551615
positive-uint64 = 1..18446744073709551615
hex32 = tstr
hex64 = tstr
]]></sourcecode>
    </section>

    <section numbered="false" toc="include" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>
        The author thanks the OpenTimestamps project for the public calendar
        infrastructure used during validation.
      </t>
      <t>
        The author thanks Joe Clarke for OPSDIR review feedback that improved
        the operational considerations and deployment guidance.
      </t>
    </section>
  </back>
</rfc>
