<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.43 (Ruby 4.0.5) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-mih-zhang-agent-disclosure-bundle-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.34.1 -->
  <front>
    <title abbrev="AAC Evidence Bundle">AAC Evidence Bundle</title>
    <seriesInfo name="Internet-Draft" value="draft-mih-zhang-agent-disclosure-bundle-00"/>
    <author initials="S." surname="Mih" fullname="Steven Mih">
      <organization>Action State Group, Inc.</organization>
      <address>
        <email>spec@actionstate.ai</email>
      </address>
    </author>
    <author initials="Y." surname="Zhang" fullname="Yiqun Zhang">
      <organization>Independent</organization>
      <address>
        <email>zhangyiqun-spec@gmail.com</email>
      </address>
    </author>
    <date year="2026" month="September" day="26"/>
    <area>Security</area>
    <workgroup>SCITT</workgroup>
    <keyword>SCITT</keyword>
    <keyword>evidence</keyword>
    <keyword>AI agent</keyword>
    <keyword>transparency</keyword>
    <keyword>audit</keyword>
    <abstract>
      <?line 53?>

<t>This document defines the AAC Evidence Bundle, a portable presentation and
verification container for an Agent Action Capsule and the records that make
its evidentiary claim intelligible. A permalink carries a bundle in its URL
fragment, an offline HTML report carries a bundle in its shell, and a hosted
report serves a bundle at its URL. The bundle does not alter any enclosed
Capsule. It declares its citation closure and any missing cited records,
carries verified disclosure preimages as a bundle-level overlay, separates
three different completeness claims, and permits independently specified
extension blocks and neutral third-party countersignatures.</t>
    </abstract>
  </front>
  <middle>
    <?line 65?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>A Capsule proves the identity and claimed content of one action. An audit
report normally needs more: the report Capsule, its chain of judgments or
adjudications, the turns cited by those records, selected disclosed preimages,
and the log evidence that supports a claim about coverage. Passing these
items as unrelated files produces a presentation that a verifier cannot
describe precisely.</t>
      <t>The AAC Evidence Bundle is that unit of evidence. It is deliberately a
presentation-layer object: the Capsules in <tt>records</tt> retain their original
bytes, identities, signatures, and registrations. The same bundle can be
encoded in a URL fragment, embedded in an offline HTML shell, or obtained
from a hosted report URL. These are transports for one object, not distinct
evidence formats.</t>
    </section>
    <section anchor="conventions">
      <name>Conventions and Definitions</name>
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP 14
<xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals,
as shown here.</t>
      <dl>
        <dt>Bundle:</dt>
        <dd>
          <t>An AAC Evidence Bundle as defined in <xref target="bundle-object"/>.</t>
        </dd>
        <dt>Root Capsule:</dt>
        <dd>
          <t>The Capsule identified by the Bundle's <tt>root</tt> member. The Bundle's evidence
claim is made from this Capsule outward through its declared closure.</t>
        </dd>
        <dt>JSON-DIGEST:</dt>
        <dd>
          <t>The lowercase-hex SHA-256 digest of <tt>UTF8(JCS(value))</tt>, using <xref target="RFC8785"/>
over the whole recursively canonicalized JSON value with no member filtering,
as defined by <xref target="I-D.mih-scitt-agent-action-capsule"/>.</t>
        </dd>
        <dt>WITHHELD:</dt>
        <dd>
          <t>The disclosure state of an eligible member absent from the Bundle-level
disclosure overlay. It is neither an empty value nor a verification failure.</t>
        </dd>
      </dl>
      <t>The terms "Capsule", "capsule_id", <tt>chain.parent_capsule_id</tt>, <tt>references</tt>,
<tt>seq</tt>, <tt>leaf_index</tt>, and <tt>log_coordinates</tt> are as defined in
<xref target="I-D.mih-scitt-agent-action-capsule"/>.</t>
    </section>
    <section anchor="bundle-object">
      <name>Evidence Bundle Object</name>
      <t>A Bundle is a JSON <xref target="RFC8259"/> object with this shape. Ellipses denote values
defined by this document or a registered extension; they do not authorize
untyped replacement formats.</t>
      <artwork><![CDATA[
{
  "bundle_version": "2",
  "bundle_kind": "evidence-bundle/v2",
  "root": "<capsule_id>",
  "records": [ ... ],
  "completeness": {
    "closure_depth": 2,
    "records_mode": "complete|declared_incomplete",
    "payloads_mode": "all|selected",
    "suppressed_fields": [ ... ],
    "missing": [ "<cited capsule digest>", ... ]
  },
  "disclosures": {
    "<capsule_id>": { "<member>": "<revealed preimage>" }
  },
  "disclosure_record": "<capsule_id>",
  "completeness_certificate": { ... },
  "checkpoint": { ... },
  "verification": { ... },
  "extensions": { "<registered kind>": { ... } },
  "countersignatures": [ ... ]
}
]]></artwork>
      <t><tt>bundle_version</tt> and <tt>bundle_kind</tt> are REQUIRED and MUST be respectively
<tt>"2"</tt> and <tt>"evidence-bundle/v2"</tt>. <tt>root</tt>, <tt>records</tt>, and <tt>completeness</tt> are
REQUIRED. <tt>root</tt> is the lowercase-hex <tt>capsule_id</tt> of one record in <tt>records</tt>.
Every <tt>records</tt> element MUST be an unmodified Capsule object conforming to
<xref target="I-D.mih-scitt-agent-action-capsule"/>; duplicate <tt>capsule_id</tt> values are
not permitted. All other members shown are OPTIONAL unless a claim in this
document requires them. A receiver MUST reject an object with an unknown
<tt>bundle_version</tt> or <tt>bundle_kind</tt> as an AAC Evidence Bundle, rather than
silently applying version-2 verification rules.</t>
      <t><tt>payloads_mode</tt> states whether the producer included all payload material it
chose to carry (<tt>all</tt>) or only a selected subset (<tt>selected</tt>).
<tt>suppressed_fields</tt> names fields intentionally not carried by the Bundle; it
does not turn an absent disclosure into an empty value or a failure.</t>
    </section>
    <section anchor="closure">
      <name>Citation Closure</name>
      <t>Citation closure is declared, not assumed. Starting at <tt>root</tt>, a producer
MUST traverse <tt>chain.parent_capsule_id</tt> and every <tt>references[].digest</tt>
transitively through <tt>completeness.closure_depth</tt> edges. The default depth is
2 when the member is absent: report to judgments or adjudications, then to
turns. A producer using a different depth MUST state that non-negative JSON
integer explicitly.</t>
      <t>For each target reached within that depth, the Bundle MUST either supply the
cited Capsule in <tt>records</tt> with a matching identity or list its digest once in
<tt>completeness.missing</tt>. A target MUST NOT be silently dropped. <tt>records_mode</tt>
MUST be <tt>complete</tt> exactly when <tt>missing</tt> is absent or empty, and MUST be
<tt>declared_incomplete</tt> exactly when it is non-empty. A verifier MUST report
the latter as declared incomplete, not as complete and not as an unexplained
failure. A supplied record whose computed <tt>capsule_id</tt> does not match the
chain target or reference digest is not supplied evidence for that target.</t>
      <t>The closure declaration says nothing about records beyond its stated depth.
A verifier MUST report the depth it applied and MUST NOT infer unbounded
ancestry or citation completeness from the presence of a short chain.</t>
    </section>
    <section anchor="disclosures">
      <name>Bundle-Level Disclosures</name>
      <t><tt>disclosures</tt> is a Bundle-level overlay keyed first by the enclosed Capsule's
<tt>capsule_id</tt>, then by the disclosure member name:</t>
      <artwork><![CDATA[
"disclosures": {
  "<capsule_id>": {
    "agent_input": { ... },
    "agent_output": { ... }
  }
}
]]></artwork>
      <t>It has the same eligibility and DE-3 digest rule as the per-Capsule
Disclosure Envelope in
<xref target="I-D.mih-agent-disclosure-envelope"/>. The member name
selects that draft's registered committed-digest path in the specified
Capsule. For every disclosed member, a verifier MUST compute
<tt>JSON-DIGEST(revealed preimage)</tt> and compare it to the committed digest at
that registered path in that <tt>records</tt> element. A match is REVEALED; a
mismatch is a failed verification of that disclosed content. A member absent
from this overlay is WITHHELD, never blank and never failed.</t>
      <t>The overlay is carried once per Bundle rather than by wrapping each Capsule
in <tt>{capsule, disclosures}</tt>. It MUST NOT alter an enclosed Capsule or its
<tt>capsule_id</tt>. An overlay key not naming a supplied record, or a member not
eligible under the Disclosure Envelope registry, is a disclosure finding and
MUST NOT be treated as a successful revelation. <tt>disclosure_record</tt>, when
present, identifies the Capsule that records the act of sealing or issuing
these disclosures; it is evidence about that act and does not replace the
DE-3 check.</t>
    </section>
    <section anchor="completeness">
      <name>Completeness Claims and Log Membership</name>
      <t><tt>completeness_certificate</tt> and <tt>checkpoint</tt>, when supplied, support three
separate claims. A verifier MUST report each claim independently.</t>
      <ol spacing="normal" type="1"><li>
          <t><strong>Graph closure</strong>: every citation reached under <xref target="closure"/> is supplied
with matching identity or explicitly listed in <tt>completeness.missing</tt>.</t>
        </li>
        <li>
          <t><strong>Interval coverage</strong>: the claimed sequence interval is anchored to a
checkpointed range root. Without a verified witness receipt or checkpoint
signature, this is only relative to a producer-asserted checkpoint.</t>
        </li>
        <li>
          <t><strong>Per-record membership</strong>: every supplied record is bound to its claimed
log position under that range root.</t>
        </li>
      </ol>
      <t>The certificate MUST state its <tt>log_id</tt>, range root, first and last <tt>seq</tt>,
and the proof material that binds that range root to <tt>checkpoint</tt>. A signed
range proof that binds only the first and last record proves endpoint
inclusion only: an interior record can be deleted or replaced while such a
proof still passes. A verifier MUST NOT report whole-range completeness from
endpoint inclusion alone. A verifier MUST verify an included, verifiable
witness receipt or checkpoint signature over the checkpoint before reporting
interval coverage or per-record membership as independently verified.
Otherwise it MUST explicitly label those claims <tt>checkpoint_unverified</tt> and
describe them as relative to a producer-asserted checkpoint.
The portable checkpoint signature member is <tt>checkpoint.cose</tt>, an unpadded
base64url CLL COSE checkpoint. A verifier that implements this member MUST
verify it and require its log identifier, MMR size, and root to equal the
certificate and checkpoint values before removing the qualifier.</t>
      <t>For the third claim, every supplied record MUST either carry a membership entry
within the declared interval or be explicitly listed in <tt>completeness.missing</tt>.
A membership entry or record whose <tt>seq</tt> is outside the interval MUST be
rejected. Each membership entry MUST carry <tt>log_coordinates</tt> stating its
claimed position and an inclusion proof to the certificate's range root. The
base profile's terms apply exactly:
<tt>seq</tt> is the 1-based log position and <tt>leaf_index = seq - 1</tt> is the zero-based
MMR index. <tt>log_coordinates</tt> states which index is used. The verifier MUST
verify every inclusion proof at its stated <tt>leaf_index</tt>, require the proof's
<tt>leaf_index</tt> to equal that coordinate and its <tt>size</tt> to equal
<tt>checkpoint.mmr_size</tt>, and bind the record to
the range root; it MUST NOT substitute an endpoint proof for a missing
per-record proof. A record without a valid proof may remain usable for graph
closure but does not satisfy per-record membership.</t>
    </section>
    <section anchor="extensions">
      <name>Typed Extensions</name>
      <t><tt>extensions</tt>, when present, is an object keyed by a registered Evidence Bundle
extension kind. The member name declares the kind and its value is that kind's
block. The extension kind registry is Specification Required. A registered
specification defines its block shape and any semantic checks. For example, a
company-side row model such as <tt>report/v1</tt> is permitted only as such an
extension; this neutral core does not define, parse, or own its rows.</t>
      <t>Extensions are included in the bundle digest (<xref target="bundle-digest"/>). A verifier
that does not implement a registered extension kind MUST preserve its
integrity status as digest-covered, report the block as uninterpreted, and
MUST NOT apply that block's semantics. An unknown kind MUST NOT alter the
core Capsule, closure, disclosure, or membership checks.</t>
    </section>
    <section anchor="bundle-digest">
      <name>Bundle Digest and Countersignatures</name>
      <t>The bundle digest is <tt>SHA-256(UTF8(JCS(canonical bundle form)))</tt>, rendered as
64 lowercase hexadecimal characters. The canonical bundle form is the Bundle
with <tt>countersignatures</tt> omitted. <tt>countersignatures</tt> is excluded so that
independent parties can add signatures without changing the digest they sign;
every other present Bundle member, including <tt>extensions</tt>, participates.</t>
      <t><tt>countersignatures</tt>, when present, is an array of objects. Each object MUST
carry <tt>type</tt> and the type's signature encoding. A countersignature is made by
a party other than the producer and signs the bundle digest. This document
does not define who populates the slot or what a valid countersignature means
for a relying party.</t>
      <t>The initial registered type is <tt>cose-sign1</tt>. Its object is
<tt>{type: "cose-sign1", signature: "&lt;base64url tagged COSE_Sign1&gt;"}</tt>. This is a
reserved neutral slot. Population and countersignature verification, including
COSE signature and payload verification, are future scope. A current verifier
MUST surface each entry as <tt>unverified</tt>; it MUST NOT present pass-through data
as a verified countersignature.</t>
    </section>
    <section anchor="fragment-codec">
      <name>Fragment Codec</name>
      <t>The common permalink codec is exact. To encode a Bundle in a URL fragment, a
producer MUST serialize the whole Bundle with JCS, including recursive
<tt>sort_keys</tt> object-member ordering, UTF-8 encode the resulting JSON text, and
encode those bytes with RFC 4648 base64url <xref target="RFC4648"/> Section 5 without
padding. The resulting unescaped ASCII string is the fragment value after
<tt>#</tt>. A decoder MUST base64url-decode the unpadded fragment, UTF-8 decode it,
parse it as JSON, and then apply the Bundle checks in this document.</t>
      <t>The <tt>/v/&lt;id&gt;</tt> route carries a Bundle of one using this same codec; <tt>/bundle</tt>
uses no different decoder. The path is a locator only. URL fragments are not
sent in HTTP requests, so a hosted service receives a Bundle only when it is
otherwise uploaded or embedded in the returned report.</t>
    </section>
    <section anchor="verification">
      <name>Verification</name>
      <t><tt>verification</tt>, when present, is producer self-report. It MAY record tool
versions, performed checks, or findings, but it is not proof and MUST NOT
replace independent verification of Capsules, disclosures, closure,
certificates, checkpoints, or countersignatures. A verifier MUST label it as
producer self-report.</t>
      <t>A conforming verifier MUST at minimum compute the Bundle digest, verify each
enclosed Capsule under the base profile, apply <xref target="closure"/> and <xref target="disclosures"/>,
and report graph closure, interval coverage, and per-record membership as
separate results. It MUST distinguish WITHHELD, REVEALED-match,
REVEALED-mismatch, declared incomplete, and absent or invalid membership
proofs.</t>
    </section>
    <section anchor="security">
      <name>Security Considerations</name>
      <t>The Bundle does not make omitted evidence disappear. Its explicit missing
declaration is necessary to prevent a short report from being represented as a
complete closure. Range endpoints are not a substitute for per-record
membership: endpoint-only proofs leave interior substitution and deletion
undetected. Disclosures are not signatures and are untrusted until their DE-3
digest comparison succeeds. Fragments can be copied or changed by a party
hosting a link, so every received Bundle requires independent verification.
Unknown extension kinds are integrity-covered but semantically untrusted.</t>
    </section>
    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>IANA is requested to create the "AAC Evidence Bundle Parameters" registry
group with these Specification Required registries, using <xref target="RFC8174"/> and
<xref target="RFC2119"/> terminology and the designated-expert criteria of <xref target="RFC8126"/>:</t>
      <ol spacing="normal" type="1"><li>
          <t>"Evidence Bundle kind", initial value <tt>evidence-bundle/v2</tt>.</t>
        </li>
        <li>
          <t>"Evidence Bundle extension kind", with no initial value. A registered
specification defines each block; private <tt>x-</tt> prefixed kinds are not
registered.</t>
        </li>
        <li>
          <t>"Evidence Bundle countersignature type", initial value <tt>cose-sign1</tt>.</t>
        </li>
      </ol>
      <t>Until IANA registry creation, the interim registry of record is <tt>REGISTRY.md</tt>
in the source repository of <xref target="I-D.mih-scitt-agent-action-capsule"/>. It records
the same values and policy.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-normative-references">
      <name>Normative References</name>
      <reference anchor="RFC2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author fullname="S. Bradner" initials="S." surname="Bradner"/>
          <date month="March" year="1997"/>
          <abstract>
            <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>
      <reference anchor="RFC8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <date month="May" year="2017"/>
          <abstract>
            <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>
      <reference anchor="RFC8126">
        <front>
          <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
          <author fullname="M. Cotton" initials="M." surname="Cotton"/>
          <author fullname="B. Leiba" initials="B." surname="Leiba"/>
          <author fullname="T. Narten" initials="T." surname="Narten"/>
          <date month="June" year="2017"/>
          <abstract>
            <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
            <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
            <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
          </abstract>
        </front>
        <seriesInfo name="BCP" value="26"/>
        <seriesInfo name="RFC" value="8126"/>
        <seriesInfo name="DOI" value="10.17487/RFC8126"/>
      </reference>
      <reference anchor="RFC8259">
        <front>
          <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
          <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
          <date month="December" year="2017"/>
          <abstract>
            <t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t>
            <t>This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t>
          </abstract>
        </front>
        <seriesInfo name="STD" value="90"/>
        <seriesInfo name="RFC" value="8259"/>
        <seriesInfo name="DOI" value="10.17487/RFC8259"/>
      </reference>
      <reference anchor="RFC8785">
        <front>
          <title>JSON Canonicalization Scheme (JCS)</title>
          <author fullname="A. Rundgren" initials="A." surname="Rundgren"/>
          <author fullname="B. Jordan" initials="B." surname="Jordan"/>
          <author fullname="S. Erdtman" initials="S." surname="Erdtman"/>
          <date month="June" year="2020"/>
          <abstract>
            <t>Cryptographic operations like hashing and signing need the data to be expressed in an invariant format so that the operations are reliably repeatable. One way to address this is to create a canonical representation of the data. Canonicalization also permits data to be exchanged in its original form on the "wire" while cryptographic operations performed on the canonicalized counterpart of the data in the producer and consumer endpoints generate consistent results.</t>
            <t>This document describes the JSON Canonicalization Scheme (JCS). This specification defines how to create a canonical representation of JSON data by building on the strict serialization methods for JSON primitives defined by ECMAScript, constraining JSON data to the Internet JSON (I-JSON) subset, and by using deterministic property sorting.</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="8785"/>
        <seriesInfo name="DOI" value="10.17487/RFC8785"/>
      </reference>
      <reference anchor="RFC4648">
        <front>
          <title>The Base16, Base32, and Base64 Data Encodings</title>
          <author fullname="S. Josefsson" initials="S." surname="Josefsson"/>
          <date month="October" year="2006"/>
          <abstract>
            <t>This document describes the commonly used base 64, base 32, and base 16 encoding schemes. It also discusses the use of line-feeds in encoded data, use of padding in encoded data, use of non-alphabet characters in encoded data, use of different encoding alphabets, and canonical encodings. [STANDARDS-TRACK]</t>
          </abstract>
        </front>
        <seriesInfo name="RFC" value="4648"/>
        <seriesInfo name="DOI" value="10.17487/RFC4648"/>
      </reference>
      <reference anchor="I-D.mih-scitt-agent-action-capsule">
        <front>
          <title>An Agent Action Capsule Profile for SCITT</title>
          <author initials="S." surname="Mih" fullname="Steven Mih">
            <organization>Action State Group, Inc.</organization>
          </author>
          <date>n.d.</date>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-mih-scitt-agent-action-capsule-05"/>
      </reference>
      <reference anchor="I-D.mih-agent-disclosure-envelope">
        <front>
          <title>Disclosure Envelope Profile for Agent Action Capsules</title>
          <author initials="S." surname="Mih" fullname="Steven Mih">
            <organization>Action State Group, Inc.</organization>
          </author>
          <date>n.d.</date>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-mih-agent-disclosure-envelope-00"/>
      </reference>
    </references>
    <?line 348?>

<section numbered="false" anchor="change-log">
      <name>Change Log</name>
      <t>Since -00 (this document): initial publication.</t>
    </section>
    <section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>The author thanks the SCITT working group and the Action State Group
architecture review for the evidence-bundle starting shape.</t>
    </section>
  </back>

</rfc>
