Skip to main content

The Vaara Receipt: A Recomputable Receipt Format for Decisions About Autonomous Actions
draft-sirkkavaara-vaara-receipt-13

Document Type Active Internet-Draft (individual)
Author Henri Sirkkavaara
Last updated 2026-10-10
RFC stream (None)
Intended RFC status Informational
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-sirkkavaara-vaara-receipt-13
Independent Submission                                    H. Sirkkavaara
Internet-Draft                                                     Vaara
Intended status: Informational                           11 October 2026
Expires: 14 April 2027

  The Vaara Receipt: A Recomputable Receipt Format for Decisions About
                           Autonomous Actions
                   draft-sirkkavaara-vaara-receipt-13

Abstract

   This document specifies vaara.receipt/v1, a signed and independently
   recomputable record that binds a decision about an autonomous action
   to the evidence the decision was made on, and optionally to one or
   more external timestamp anchors.  The format is canonicalized with
   the JSON Canonicalization Scheme (JCS) so that a third party can
   recompute its digests, and, for a receipt signed with a public-key
   algorithm, verify its signature, without access to the issuer.  A
   decision and the execution receipt that answers it form one
   recomputable pair through the envelope's back link.

   The receipt's trust is root-agnostic: the same record is verifiable
   with or without a hardware trusted execution environment and is re-
   expressible as an IETF RATS Entity Attestation Result.  Downstream
   specifications (a payment rail, a compliance regime, a framework
   integration) define profiles that pin to a version of this document
   and add only their own evidence schema; they do not redefine the
   envelope.  The format described here is deployed, and its receipts
   are independently recomputable from public conformance vectors that
   ship with standalone checkers importing no issuer code.  The minimal
   profile is the engine decision: one receipt per decision an engine
   records on its own audit trail, bound to the trail record it decided,
   with no external rail.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

Sirkkavaara               Expires 14 April 2027                 [Page 1]
Internet-Draft                Vaara Receipt                 October 2026

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 14 April 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   3
     1.1.  Terminology . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Canonicalization, Digests, Numbers, and Times . . . . . . . .   4
   3.  The Receipt Envelope  . . . . . . . . . . . . . . . . . . . .   5
     3.1.  Algorithms and Signature Encoding . . . . . . . . . . . .   6
     3.2.  Signed Payload  . . . . . . . . . . . . . . . . . . . . .   7
     3.3.  Back Link . . . . . . . . . . . . . . . . . . . . . . . .   7
     3.4.  Issuer Block  . . . . . . . . . . . . . . . . . . . . . .   9
     3.5.  Post-Quantum Signature and Crypto Posture . . . . . . . .  10
     3.6.  Existence Proof . . . . . . . . . . . . . . . . . . . . .  11
     3.7.  Execution Receipt . . . . . . . . . . . . . . . . . . . .  11
     3.8.  Worked Examples . . . . . . . . . . . . . . . . . . . . .  13
   4.  Decision and Evidence Binding (decisionDerived) . . . . . . .  16
   5.  Timestamp Anchors (timestampAnchors)  . . . . . . . . . . . .  19
   6.  Profiles  . . . . . . . . . . . . . . . . . . . . . . . . . .  22
     6.1.  Registry  . . . . . . . . . . . . . . . . . . . . . . . .  22
     6.2.  Related Suite: Governance Decision Records  . . . . . . .  24
     6.3.  Profile Example: x402 Settlement Binding  . . . . . . . .  24
     6.4.  Profile Example: Authorization Decision . . . . . . . . .  25
     6.5.  Profile Example: AP2 Checkout Binding . . . . . . . . . .  28
     6.6.  Profile Example: TAP Request Binding  . . . . . . . . . .  29
     6.7.  Profile: Generic External Execution Evidence  . . . . . .  29
     6.8.  Profile: Engine Decision  . . . . . . . . . . . . . . . .  30
       6.8.1.  Cage Block  . . . . . . . . . . . . . . . . . . . . .  32
   7.  Conformance . . . . . . . . . . . . . . . . . . . . . . . . .  34
   8.  Implementation Status . . . . . . . . . . . . . . . . . . . .  35
   9.  Versioning  . . . . . . . . . . . . . . . . . . . . . . . . .  36
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  37

Sirkkavaara               Expires 14 April 2027                 [Page 2]
Internet-Draft                Vaara Receipt                 October 2026

   11. Privacy Considerations  . . . . . . . . . . . . . . . . . . .  39
   12. Regulatory Applicability  . . . . . . . . . . . . . . . . . .  39
   13. Related Work  . . . . . . . . . . . . . . . . . . . . . . . .  41
   14. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  43
   15. Normative References  . . . . . . . . . . . . . . . . . . . .  43
   16. Informative References  . . . . . . . . . . . . . . . . . . .  44
   Appendix A.  Envelope Schema (CDDL) . . . . . . . . . . . . . . .  48
   Appendix B.  Cage Drivers and Bases in Use  . . . . . . . . . . .  52
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  54

1.  Introduction

   A Vaara receipt is a signed, independently recomputable record that
   binds a decision about an autonomous action to the evidence it was
   made on, and optionally to one or more external timestamp anchors.
   Any system that emits or consumes Vaara receipts conforms to this
   document.  Downstream specifications define profiles that pin to a
   version of this document and add only their own evidence schema; they
   do not redefine the envelope.  An action here is any operation an
   autonomous or semi-autonomous system performs; an AI agent tool call
   is one case, and the format does not depend on the actor being an AI
   agent.  The property this provides is accountable autonomy: an
   autonomous system may act, and an outside party can still recompute
   what it was permitted to do and what it did, without trusting the
   operator.

   The receipt's trust is root-agnostic.  The same record is verifiable
   with or without a hardware TEE and re-expressible as an IETF RATS
   ([RFC9334]) Entity Attestation Result (an AR4SI vector,
   [I-D.ietf-rats-ear]), whether rooted in a TPM 2.0 host, an AMD SEV-
   SNP confidential VM, or software alone.  The signature and the
   optional external time anchor carry the evidence, not a single trust
   root.

   This document packages a format that already ships and is
   independently recomputable from public conformance vectors.  The
   executable conformance fixtures live under tests/vectors/ in the
   source repository ([VAARA-REPO]), each directory with a checker
   (_check_independent.py) that imports no issuer code: only the
   standard library and, as its profile needs, libraries for signatures,
   JCS, ASN.1, or ML-DSA.

Sirkkavaara               Expires 14 April 2027                 [Page 3]
Internet-Draft                Vaara Receipt                 October 2026

   The floor of the format is the engine decision profile (Section 6.8):
   one receipt per decision an engine records on its hash-chained audit
   trail, bound to that trail record, with no payment rail, settlement
   artifact, or external evidence record to join.  It is the smallest
   conforming receipt, it is what a default install of the reference
   implementation emits for every decision, and it is the entry point a
   producer reaches for first.

1.1.  Terminology

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in BCP
   14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

2.  Canonicalization, Digests, Numbers, and Times

   Every digest of a JSON value in this document, and every signed
   payload, is computed over the JSON Canonicalization Scheme (JCS,
   [RFC8785]).  The canonicalization label for the
   evidenceRef.canonicalization member (Section 4) is "jcs-rfc8785".
   The values "JCS" and "jcs-json-v1" are accepted aliases for the same
   algorithm; producers SHOULD emit "jcs-rfc8785", and consumers MUST
   accept all three.

   A digest is written "sha256:" followed by the 64 lowercase
   hexadecimal characters of a SHA-256 ([FIPS180-4]) value.  Unless the
   definition of a member says otherwise, the hashed bytes are the JCS
   encoding of the referenced JSON value.  Where a member is a digest
   over bytes that are not a JSON value (a UTF-8 string, a configuration
   file, a joined preimage), its definition names those bytes.

   No signed block and no evidence record defined in this document
   carries a non-integer number.  Quantities that are not integers, such
   as risk scores and thresholds, are carried as decimal strings (for
   example "0.12").  A producer MUST NOT emit a non-integer JSON number
   in any of them, because two JCS implementations are only guaranteed
   to agree on integers within the range JCS defines.

   Times are date-time strings as defined in [RFC3339], in UTC with the
   "Z" designator.  Fractional seconds MAY be present.  A consumer MUST
   NOT reorder or compare receipts by these strings without parsing
   them, because two producers can write the same instant with a
   different number of fractional digits.

Sirkkavaara               Expires 14 April 2027                 [Page 4]
Internet-Draft                Vaara Receipt                 October 2026

3.  The Receipt Envelope

   A receipt is a JSON object.  It is either a decision receipt, which
   records a decision about an action, or an execution receipt, which
   records what followed.  Both kinds share the envelope below and
   differ in their derived block and their asserted block.

   +==================+=======+===========+==========+================+
   | Member           |Type   | Kind      | Presence | Meaning        |
   +==================+=======+===========+==========+================+
   | version          |integer| both      | REQUIRED | 1 for this     |
   |                  |       |           |          | document.      |
   +------------------+-------+-----------+----------+----------------+
   | alg              |string | both      | REQUIRED | "ES256",       |
   |                  |       |           |          | "RS256", or    |
   |                  |       |           |          | "HS256".  See  |
   |                  |       |           |          | Section 3.1.   |
   +------------------+-------+-----------+----------+----------------+
   | backLink         |object | both      | REQUIRED | The            |
   |                  |       |           |          | predecessor    |
   |                  |       |           |          | this receipt   |
   |                  |       |           |          | answers.  See  |
   |                  |       |           |          | Section 3.3.   |
   +------------------+-------+-----------+----------+----------------+
   | decisionDerived  |object | decision  | REQUIRED | The decision   |
   |                  |       |           |          | and its basis. |
   |                  |       |           |          | See Section 4. |
   +------------------+-------+-----------+----------+----------------+
   | issuerAsserted   |object | decision  | REQUIRED | The issuer     |
   |                  |       |           |          | block.  See    |
   |                  |       |           |          | Section 3.4.   |
   +------------------+-------+-----------+----------+----------------+
   | outcomeDerived   |object | execution | REQUIRED | The outcome.   |
   |                  |       |           |          | See            |
   |                  |       |           |          | Section 3.7.   |
   +------------------+-------+-----------+----------+----------------+
   | receiptAsserted  |object | execution | REQUIRED | The issuer     |
   |                  |       |           |          | block.  See    |
   |                  |       |           |          | Section 3.4.   |
   +------------------+-------+-----------+----------+----------------+
   | signature        |string | both      | REQUIRED | The signature  |
   |                  |       |           |          | over the       |
   |                  |       |           |          | signed payload |
   |                  |       |           |          | (Section 3.2). |
   |                  |       |           |          | See            |
   |                  |       |           |          | Section 3.1.   |
   +------------------+-------+-----------+----------+----------------+
   | timestampAnchors |array  | decision  | OPTIONAL | External time  |

Sirkkavaara               Expires 14 April 2027                 [Page 5]
Internet-Draft                Vaara Receipt                 October 2026

   |                  |       |           |          | attestations.  |
   |                  |       |           |          | See Section 5. |
   +------------------+-------+-----------+----------+----------------+
   | pqSignature      |object | execution | OPTIONAL | A post-quantum |
   |                  |       |           |          | signature      |
   |                  |       |           |          | beside the     |
   |                  |       |           |          | classical one. |
   |                  |       |           |          | See            |
   |                  |       |           |          | Section 3.5.   |
   +------------------+-------+-----------+----------+----------------+
   | existenceProof   |object | execution | OPTIONAL | A timestamp    |
   |                  |       |           |          | over the whole |
   |                  |       |           |          | signed         |
   |                  |       |           |          | receipt.  See  |
   |                  |       |           |          | Section 3.6.   |
   +------------------+-------+-----------+----------+----------------+

                    Table 1: Receipt envelope members

   A decision receipt carries decisionDerived and issuerAsserted and
   neither outcomeDerived nor receiptAsserted; an execution receipt
   carries the reverse.  The schema is closed.  A consumer MUST reject a
   receipt that carries a member not listed for its kind in Table 1, and
   MUST reject any member not defined by this document inside backLink,
   decisionDerived, evidenceRef, issuerAsserted, receiptAsserted,
   outcomeDerived, completeness, cryptoPosture, pqSignature, or
   existenceProof.  A consumer that rebuilds a signed block from the
   members it understands would otherwise leave out signed bytes, and
   could report a receipt as verified over content it never checked.
   Evidence records are defined by profiles (Section 6), and their own
   rules govern members they do not define.

   Appendix A gives the envelope in CDDL ([RFC8610]).  The CDDL and the
   prose are both normative.  Rules the CDDL cannot express, such as
   runningCount equal to seq + 1, the issuer block alg equal to the
   envelope alg, and the absence of sigSuite from a decision receipt,
   are stated in the prose only.

3.1.  Algorithms and Signature Encoding

   alg names the algorithm of signature.  ES256 is ECDSA using P-256 and
   SHA-256, and the signature is the 64-byte r||s pair as defined for
   "ES256" in [RFC7518].  RS256 is RSASSA-PKCS1-v1_5 using SHA-256, and
   HS256 is HMAC using SHA-256, both as defined in [RFC7518]. signature
   is the lowercase hexadecimal encoding of the raw signature or MAC
   bytes.  No other alg value is defined in this version, and a consumer
   MUST reject a receipt that names one.

Sirkkavaara               Expires 14 April 2027                 [Page 6]
Internet-Draft                Vaara Receipt                 October 2026

   HS256 is symmetric.  An HS256 receipt is verifiable only by a holder
   of the shared secret, so it is not recomputable by an arbitrary third
   party.  Producers that intend receipts for parties outside their own
   trust domain SHOULD use ES256 or RS256.

   The asserted block repeats the algorithm in its own alg member,
   inside the signed bytes.  The two MUST be equal.  A consumer MUST
   reject a receipt whose envelope alg and asserted-block alg differ,
   before trying any key.

3.2.  Signed Payload

   The signature is computed over the JCS encoding of the object
   containing exactly these members, with their receipt values:

   <CODE BEGINS>
   decision receipt:
     ("version", "alg", "backLink", "decisionDerived", "issuerAsserted")
   execution receipt:
     ("version", "alg", "backLink", "outcomeDerived", "receiptAsserted")
   <CODE ENDS>

   "signature", "timestampAnchors", "pqSignature", and "existenceProof"
   are not part of the signed payload.  Each is either the signature
   itself or evidence attached after signing, so attaching one does not
   invalidate the signature.  A consumer MUST verify the signature by
   reconstructing the payload for the receipt's kind from the members as
   received, canonicalizing it, and checking it under alg with the
   verification key (the public key for ES256 and RS256, the shared
   secret for HS256).

3.3.  Back Link

   backLink binds a receipt to the object it answers.

Sirkkavaara               Expires 14 April 2027                 [Page 7]
Internet-Draft                Vaara Receipt                 October 2026

   +====================+==========+==================================+
   | Member             | Presence | Meaning                          |
   +====================+==========+==================================+
   | attestationDigest  | REQUIRED | A digest (Section 2) of the      |
   |                    |          | predecessor, computed over its   |
   |                    |          | complete JSON form including its |
   |                    |          | own signature.                   |
   +--------------------+----------+----------------------------------+
   | attestationNonce   | REQUIRED | A non-empty string: the          |
   |                    |          | predecessor's nonce, or the      |
   |                    |          | identifier the profile names in  |
   |                    |          | its place.                       |
   +--------------------+----------+----------------------------------+
   | fallbackProjection | OPTIONAL | Present only when no predecessor |
   |                    |          | attestation exists and           |
   |                    |          | attestationDigest is computed    |
   |                    |          | over a named projection of the   |
   |                    |          | originating request instead.     |
   |                    |          | The value names the projection   |
   |                    |          | and its version.                 |
   +--------------------+----------+----------------------------------+

                        Table 2: backLink members

   For a decision receipt the predecessor is the attestation of the
   request the decision governs, unless the receipt's profile names a
   different predecessor; the engine decision profile (Section 6.8)
   names the previous record on the issuer's audit trail.  For an
   execution receipt the predecessor is the same request attestation its
   decision receipt names, so a decision and its execution receipt carry
   the same backLink.  A consumer confirms the binding by recomputing
   attestationDigest from the predecessor and comparing
   attestationNonce, with no access to the issuer.  A profile that
   permits fallbackProjection MUST define each projection value it uses.
   A consumer MUST reject a fallbackProjection value it does not
   implement.

   This document defines one value,
   "tools_call_params_plus_meta_authorization_binding_v1", for a Model
   Context Protocol tools/call request.  The projection is the object
   {"projection": the value, "name": params.name, "arguments":
   params.arguments, "authorizationBinding":
   params._meta.authorization_binding}, and attestationDigest is its
   digest.  authorization_binding is REQUIRED and is an object with a
   non-empty string nonce, chosen by the server for the call; name and
   arguments are REQUIRED.  No other member of _meta enters the
   projection, so a gateway and a provider that see the same call with
   different _meta members compute the same digest.  Where the

Sirkkavaara               Expires 14 April 2027                 [Page 8]
Internet-Draft                Vaara Receipt                 October 2026

   projection cannot be built, the binding fails and a consumer MUST NOT
   widen the projection to recover it.  See tests/vectors/
   fallback_projection_v0/ and tests/vectors/decision_pairing_v0/.

3.4.  Issuer Block

   issuerAsserted (in a decision receipt) and receiptAsserted (in an
   execution receipt) have the same members.  Both are inside the signed
   payload.

   +===============+========+==========+==============================+
   | Member        | Type   | Presence | Meaning                      |
   +===============+========+==========+==============================+
   | iss           | string | REQUIRED | The issuer.                  |
   +---------------+--------+----------+------------------------------+
   | sub           | string | REQUIRED | The subject: the agent or    |
   |               |        |          | principal the action was     |
   |               |        |          | taken by or for.             |
   +---------------+--------+----------+------------------------------+
   | iat           | string | REQUIRED | Issuance time, an [RFC3339]  |
   |               |        |          | date-time in UTC.  This is a |
   |               |        |          | string, not a JSON Web Token |
   |               |        |          | NumericDate.                 |
   +---------------+--------+----------+------------------------------+
   | nonce         | string | REQUIRED | Unique per receipt.          |
   |               |        |          | Producers SHOULD draw at     |
   |               |        |          | least 128 bits from a        |
   |               |        |          | cryptographic random source. |
   +---------------+--------+----------+------------------------------+
   | alg           | string | REQUIRED | Equal to the envelope alg    |
   |               |        |          | (Section 3.1).               |
   +---------------+--------+----------+------------------------------+
   | secretVersion | string | REQUIRED | Names the verification key.  |
   |               |        |          | A consumer resolves the key  |
   |               |        |          | from iss and secretVersion   |
   |               |        |          | out of band; this document   |
   |               |        |          | defines no resolution        |
   |               |        |          | protocol.                    |
   +---------------+--------+----------+------------------------------+
   | aud           | string | OPTIONAL | The relying party the        |
   |               |        |          | receipt was issued for.      |
   +---------------+--------+----------+------------------------------+
   | taskId        | string | OPTIONAL | The long-running task the    |
   |               |        |          | action belongs to.           |
   +---------------+--------+----------+------------------------------+
   | completeness  | object | OPTIONAL | The per-boundary sequence of |
   |               |        |          | this receipt, in the issuer  |
   |               |        |          | block.  The same block,      |

Sirkkavaara               Expires 14 April 2027                 [Page 9]
Internet-Draft                Vaara Receipt                 October 2026

   |               |        |          | carried in the evidence      |
   |               |        |          | record, is the completeness  |
   |               |        |          | layer of Section 6.4.        |
   +---------------+--------+----------+------------------------------+
   | sigSuite      | string | OPTIONAL | The hybrid signature suite   |
   |               |        |          | the issuer committed to      |
   |               |        |          | (Section 3.5).  Execution    |
   |               |        |          | receipts only.               |
   +---------------+--------+----------+------------------------------+
   | cryptoPosture | object | OPTIONAL | The algorithms protecting    |
   |               |        |          | the receipt and their post-  |
   |               |        |          | quantum level (Section 3.5). |
   +---------------+--------+----------+------------------------------+

                      Table 3: Issuer block members

   aud and taskId, when present, are non-empty strings.  A consumer
   asked to check either against an expected value reports three
   outcomes: bound (present and equal), conflict (present and
   different), or unsupported (absent).  An absent aud or taskId states
   that the issuer bound none.  It does not state that the receipt was
   issued for any relying party or task.

   completeness, when present, carries exactly three members, all
   REQUIRED: boundaryId (a non-empty string), seq (an integer, 0 or
   greater), and runningCount (an integer equal to seq + 1).  A consumer
   MUST reject a completeness object that is partial or breaks these
   rules.  The boundary of an execution receipt is the boundary of its
   decision receipts with "#execution" appended, so a refused decision,
   which has no execution receipt, does not read as a gap.

3.5.  Post-Quantum Signature and Crypto Posture

   There is no post-quantum alg value in this version.  An execution
   receipt MAY carry a post-quantum signature beside the classical one.
   The issuer commits to it inside the signed payload with sigSuite,
   whose defined values are "ES256+ML-DSA-65" and "RS256+ML-DSA-65".
   The classical part of the value MUST equal alg. pqSignature then
   carries three non-empty strings: alg ("ML-DSA-65", [FIPS204]), keyid
   (names the ML-DSA verification key), and sig (the lowercase
   hexadecimal ML-DSA-65 signature over the same signed payload bytes
   the classical signature covers).

Sirkkavaara               Expires 14 April 2027                [Page 10]
Internet-Draft                Vaara Receipt                 October 2026

   A consumer MUST reject a receipt whose sigSuite has any other value.
   A consumer that verifies ML-DSA MUST reject a receipt whose sigSuite
   names a hybrid suite and whose pqSignature is absent or does not
   verify: that is a stripped signature, and the committed sigSuite is
   what makes the stripping detectable.  A pqSignature on a receipt
   without sigSuite commits nothing, and a consumer MUST NOT treat it as
   post-quantum protection.  A decision receipt MUST NOT carry sigSuite.

   cryptoPosture records which algorithms protect the receipt, in the
   shape of CycloneDX cryptographic properties.  It has three REQUIRED
   members: assetType ("algorithm"), algorithms (a non-empty array of
   objects, each with exactly algorithm, primitive, and
   nistQuantumSecurityLevel), and nistQuantumSecurityLevel (an integer
   from 0 to 5, the highest level in algorithms).  The levels are 0 for
   HS256 (primitive "mac"), ES256, and RS256 (primitive "signature"),
   and 3 for ML-DSA-65 (primitive "signature").  A consumer checks
   cryptoPosture by recomputing it from alg and sigSuite.  A posture
   that does not match the recomputation, or that claims an ML-DSA leg
   without a sigSuite that commits it, is a claim the receipt does not
   back, and a consumer MUST NOT rely on it.

3.6.  Existence Proof

   An execution receipt MAY carry existenceProof, an RFC 3161
   ([RFC3161]) timestamp over the whole signed receipt.  It has exactly
   four members, all non-empty strings: backend ("rfc3161-eidas-
   qualified" in this version), hashAlgorithm ("sha256"), recordDigest
   (a digest of the receipt with existenceProof removed, signature
   included), and token (the base64 DER TimeStampToken whose message
   imprint is that digest).  A consumer recomputes recordDigest from the
   receipt and requires the token's imprint to equal it.  It is outside
   the signed payload; its integrity rests on the token, which covers
   the signed receipt including its signature.  The attested time is
   qualified only when the consumer pins the token signer's issuing
   authority from a trusted list it holds; the backend value alone
   proves nothing.

3.7.  Execution Receipt

   An execution receipt records the outcome of the action a decision
   governed.  Its conformance vectors are tests/vectors/
   execution_receipt_v0/, with a standalone checker that imports no
   issuer code.

Sirkkavaara               Expires 14 April 2027                [Page 11]
Internet-Draft                Vaara Receipt                 October 2026

     +==================+==========+================================+
     | Member           | Presence | Meaning                        |
     +==================+==========+================================+
     | status           | REQUIRED | "executed" (the action ran),   |
     |                  |          | "refused" (it did not run), or |
     |                  |          | "errored" (it was attempted    |
     |                  |          | and failed).  A consumer MUST  |
     |                  |          | reject any other value.        |
     +------------------+----------+--------------------------------+
     | completedAt      | REQUIRED | Time the outcome was recorded  |
     |                  |          | (Section 2).                   |
     +------------------+----------+--------------------------------+
     | resultCommitment | OPTIONAL | A commitment to the result, or |
     |                  |          | to the error for "errored".    |
     |                  |          | Absent for "refused".          |
     +------------------+----------+--------------------------------+
     | decisionDigest   | OPTIONAL | A digest of the decision       |
     |                  |          | receipt this outcome answers,  |
     |                  |          | over its signed members and    |
     |                  |          | its signature, without         |
     |                  |          | timestampAnchors.              |
     +------------------+----------+--------------------------------+

                     Table 4: outcomeDerived members

   resultCommitment takes one of two forms.  The projection form is
   {projection, projectionDigest}: projection is a string holding the
   JCS encoding of a JSON value, and projectionDigest is "sha256:" over
   the UTF-8 bytes of that string.  The value is either the result
   itself or the object {"digest": "sha256:..."} over the JCS encoding
   of the result, so a result is committed by value or by digest while
   the raw result stays private.  The reference form is {ref, digest,
   canonicalization}: ref locates the result, digest is a digest of it,
   and canonicalization is "jcs".  A consumer that holds the result
   recomputes the commitment.

   The backLink pair (Section 3.3) binds the execution receipt to the
   call it answers. decisionDigest binds it to the content of one
   decision, so an outcome cannot be reattached to a different decision
   about the same call.  Because status is inside the signed payload, an
   executed receipt replayed with its status changed to "refused" does
   not verify: the signed envelope, not any single sub-check, binds the
   outcome.  See tests/vectors/execution_receipt_v0/normative/ and
   tests/vectors/decision_pairing_v0/.

Sirkkavaara               Expires 14 April 2027                [Page 12]
Internet-Draft                Vaara Receipt                 October 2026

3.8.  Worked Examples

   Two receipts from the conformance vectors, as the library wrote them.
   Both verify with the standalone checkers of their suites.  Lines
   longer than the page are folded with the single-backslash strategy of
   [RFC8792]; the unfolded bytes are the vector files.

   A decision receipt, the floor of the format (Section 6.8), from
   tests/vectors/trail_decision_v0/valid/0-allow.json.  The evidence
   record it binds follows it; evidenceRef.digest is the SHA-256 of that
   record's JCS encoding, and the back link names the previous trail
   record's hash, here the hash of the empty string because this is the
   first record of its trail.

Sirkkavaara               Expires 14 April 2027                [Page 13]
Internet-Draft                Vaara Receipt                 October 2026

   <CODE BEGINS>
   ========== NOTE: '\' line wrapping per RFC 8792 ==========

   {
     "alg": "ES256",
     "backLink": {
       "attestationDigest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427a\
     e41e4649b934ca495991b7852b855",
       "attestationNonce": "dc8b561b-01e2-4e8e-9af2-b8b0fcb9a2ff"
     },
     "decisionDerived": {
       "decidedAt": "2026-09-25T00:17:48.320Z",
       "decision": "allow",
       "evidenceRef": {
         "canonicalization": "jcs-rfc8785",
         "digest": "sha256:7663868c3f5830dba2be46d514c65451404b8cf93d75\
     69efff1493eb3c380a4e",
         "ref": "vaara:trail/dc8b561b-01e2-4e8e-9af2-b8b0fcb9a2ff",
         "schema": "vaara.trail-decision/v0"
       },
       "policyId": "policy:vaara-engine/1",
       "reason": "allow: risk=0.12 (threshold allow<0.55 deny>0.85)",
       "riskScore": "0.12"
     },
     "issuerAsserted": {
       "alg": "ES256",
       "iat": "2026-09-25T00:17:48Z",
       "iss": "vaara:engine",
       "nonce": "RBKpasu2API112jCGYcLZ0M7",
       "secretVersion": "es256:dfa441deb94a9c1c",
       "sub": "vector-agent"
     },
     "signature": "7ebfd51b88d876a46fea986beb497ef0e122e84f3356c5244dd0\
     a2a893a8aa7eaee95ec0c84d12a41929ea15403be85b0e9b1211ae4e6acb6dcb96\
     c4bafc42ad",
     "version": 1
   }
   <CODE ENDS>

   The evidence record behind evidenceRef:

Sirkkavaara               Expires 14 April 2027                [Page 14]
Internet-Draft                Vaara Receipt                 October 2026

   <CODE BEGINS>
   ========== NOTE: '\' line wrapping per RFC 8792 ==========

   {
     "actionId": "vector-action-0",
     "agentId": "vector-agent",
     "decidedAt": "2026-09-25T00:17:48.320Z",
     "decision": "allow",
     "eventType": "decision_made",
     "previousHash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e464\
     9b934ca495991b7852b855",
     "reason": "allow: risk=0.12 (threshold allow<0.55 deny>0.85)",
     "recordHash": "sha256:b0b163a567a30a5396583055f4a943484958c3ad082d\
     2d656b2b30ebf6105af4",
     "recordId": "dc8b561b-01e2-4e8e-9af2-b8b0fcb9a2ff",
     "riskScore": "0.12",
     "schema": "vaara.trail-decision/v0",
     "tenantId": "",
     "toolName": "read_file"
   }
   <CODE ENDS>

   An execution receipt (Section 3.7) with an executed status and a
   projection result commitment, from
   tests/vectors/execution_receipt_v0/normative/
   es256_executed_projection/receipt.json.  Its back link carries the
   attestation digest and nonce of the decision receipt it follows, so
   the outcome cannot be reattached to another decision.

Sirkkavaara               Expires 14 April 2027                [Page 15]
Internet-Draft                Vaara Receipt                 October 2026

   <CODE BEGINS>
   ========== NOTE: '\' line wrapping per RFC 8792 ==========

   {
     "alg": "ES256",
     "backLink": {
       "attestationDigest": "sha256:79acdd4bb3c22a688b1c3321b9a26cafb5c\
     b58c990a963874066d04b8497f70b",
       "attestationNonce": "fixed-attestation-nonce-000"
     },
     "outcomeDerived": {
       "completedAt": "2026-05-29T10:00:00Z",
       "resultCommitment": {
         "projection": "{\"deleted\":true,\"path\":\"/archive/2024-Q3.m\
     d\"}",
         "projectionDigest": "sha256:c9a4caed49b3efaa7908a29a550b8d33ff\
     bb088c52d519242477223a83214198"
       },
       "status": "executed"
     },
     "receiptAsserted": {
       "alg": "ES256",
       "iat": "2026-05-29T10:00:00Z",
       "iss": "issuer://test",
       "nonce": "fixed-receipt-nonce-0001",
       "secretVersion": "v1",
       "sub": "agent:archiver"
     },
     "signature": "867c0439a289d77b75d489b07c42292095c947869365f1c92d98\
     2440338bddf0bb0bf91212cf9b1e681b076315862b5458f5167e98f0fca3a03c42\
     3b2a825f44",
     "version": 1
   }
   <CODE ENDS>

4.  Decision and Evidence Binding (decisionDerived)

   +=================+==========+======================================+
   | Member          | Presence | Meaning                              |
   +=================+==========+======================================+
   | decision        | REQUIRED | "allow", "block", or                 |
   |                 |          | "escalate".  A consumer MUST         |
   |                 |          | reject any other value.              |
   +-----------------+----------+--------------------------------------+
   | decidedAt       | REQUIRED | Time of the decision                 |
   |                 |          | (Section 2).                         |
   +-----------------+----------+--------------------------------------+
   | reason          | OPTIONAL | The issuer's reason, a string.       |

Sirkkavaara               Expires 14 April 2027                [Page 16]
Internet-Draft                Vaara Receipt                 October 2026

   +-----------------+----------+--------------------------------------+
   | policyId        | OPTIONAL | Names the policy the decision        |
   |                 |          | was made under.                      |
   +-----------------+----------+--------------------------------------+
   | riskScore,      | OPTIONAL | Decimal strings (Section 2):         |
   | thresholdAllow, |          | the score the decision rested        |
   | thresholdBlock  |          | on and the thresholds it was         |
   |                 |          | compared with.                       |
   +-----------------+----------+--------------------------------------+
   | clientTurnId    | OPTIONAL | A turn identifier the client         |
   |                 |          | supplied.  It records that the       |
   |                 |          | client claimed it, not that          |
   |                 |          | the issuer vouches for it.           |
   +-----------------+----------+--------------------------------------+
   | evidenceRef     | OPTIONAL | Binds the decision to an             |
   |                 |          | evidence record.  Every              |
   |                 |          | profile in Section 6 requires        |
   |                 |          | it.                                  |
   +-----------------+----------+--------------------------------------+
   | rationale       | OPTIONAL | The rule that decided and why,       |
   |                 |          | in words.                            |
   +-----------------+----------+--------------------------------------+
   | binding         | OPTIONAL | Digests binding the decision         |
   |                 |          | to its policy, intent, and           |
   |                 |          | inputs.                              |
   +-----------------+----------+--------------------------------------+
   | decisionProof   | OPTIONAL | A zero-knowledge proof over          |
   |                 |          | binding.                             |
   +-----------------+----------+--------------------------------------+

                      Table 5: decisionDerived members

   "allow" means the action was permitted. "block" means it was refused.
   "escalate" means it was referred to a person or another authority and
   was not permitted at the time of the decision; a later decision, with
   its own receipt, settles it.  These are the only values.  Profiles
   below name verdicts that a verifier computes, such as "deny" or
   "revise"; those are outputs of a checker, not values of decision.

   rationale has the members rule, reason, and declaredIntent (strings,
   REQUIRED) and intentSatisfied (a boolean, OPTIONAL). binding has four
   REQUIRED digests: policyDigest over the JCS encoding of the policy,
   intentDigest over the UTF-8 bytes of the declared intent,
   inputsDigest over the JCS encoding of the evaluation inputs, and
   bindingDigest over the UTF-8 bytes of policyDigest, intentDigest,
   inputsDigest, and decision joined in that order by the single byte
   0x1F. decisionProof is a proof that the committed values reach the
   stated decision, opened against bindingDigest; its format is not

Sirkkavaara               Expires 14 April 2027                [Page 17]
Internet-Draft                Vaara Receipt                 October 2026

   defined by this document.  A consumer that does not verify
   decisionProof MUST NOT read it as evidence of anything, and the
   signature covers it either way.

       +==================+==========+=============================+
       | Member           | Presence | Meaning                     |
       +==================+==========+=============================+
       | canonicalization | REQUIRED | A label from Section 2.     |
       +------------------+----------+-----------------------------+
       | digest           | REQUIRED | A digest of the evidence    |
       |                  |          | record.                     |
       +------------------+----------+-----------------------------+
       | schema           | REQUIRED | The schema identifier of    |
       |                  |          | the evidence record,        |
       |                  |          | defined by its profile.     |
       +------------------+----------+-----------------------------+
       | ref              | OPTIONAL | An advisory locator for the |
       |                  |          | evidence record, defined by |
       |                  |          | the profile.  Not an        |
       |                  |          | identifier; see below.      |
       +------------------+----------+-----------------------------+

                        Table 6: evidenceRef members

   The binding is recomputable: given the receipt and the evidence
   record, a third party confirms that the digest of the evidence record
   equals evidenceRef.digest with no access to the issuer.

   The digest is the binding; ref is advisory.  A profile MAY assign the
   same ref to more than one evidence record, and profiles in use do:
   where a single action settles to several parties, each party's record
   is a separate evidence record carried under one shared ref.  Those
   records differ under digest because their contents differ.

   A consumer therefore MUST NOT resolve an evidence record by ref
   alone, and MUST confirm that the digest of the evidence record equals
   evidenceRef.digest before treating the record as the one the receipt
   decided over.  Resolving by ref alone admits a record that shares the
   locator but is not the record the issuer signed over, and no check in
   this document fails when that happens.

Sirkkavaara               Expires 14 April 2027                [Page 18]
Internet-Draft                Vaara Receipt                 October 2026

5.  Timestamp Anchors (timestampAnchors)

   A timestamp anchor is evidence from outside the issuer that a
   decision receipt existed no later than a stated time.  Anchors are
   optional and are attached to decision receipts; an execution receipt
   carries its time evidence in existenceProof (Section 3.6).  Every
   anchor binds anchoredDigest, the digest of the receipt's signed
   payload (Section 3.2), so an anchor commits to the exact signed
   receipt and does not depend on any other anchor.

   <CODE BEGINS>
   {
     "method": "rfc3161",
     "anchoredDigest": "sha256:...",
     "token": "<base64 DER RFC 3161 TimeStampToken>",
     "authority": "<optional human-readable authority name>"
   }
   <CODE ENDS>

   method is REQUIRED and selects the members that follow.
   anchoredDigest is REQUIRED for every method. authority is OPTIONAL
   and informative.

Sirkkavaara               Expires 14 April 2027                [Page 19]
Internet-Draft                Vaara Receipt                 October 2026

    +=================+=============================+=================+
    | method          | What it is                  | Further members |
    +=================+=============================+=================+
    | rfc3161         | An RFC 3161 ([RFC3161])     | token           |
    |                 | timestamp token whose       |                 |
    |                 | message imprint is          |                 |
    |                 | anchoredDigest, from any    |                 |
    |                 | time-stamping authority,    |                 |
    |                 | including one the producer  |                 |
    |                 | runs.                       |                 |
    +-----------------+-----------------------------+-----------------+
    | rfc3161-eidas-  | As rfc3161, from a          | token           |
    | qualified       | qualified time-stamping     |                 |
    |                 | authority under eIDAS       |                 |
    |                 | ([eIDAS]).  The             |                 |
    |                 | qualification adds legal    |                 |
    |                 | weight and nothing else.    |                 |
    +-----------------+-----------------------------+-----------------+
    | rfc3161-blinded | As rfc3161, with the        | token,          |
    |                 | authority shown a salted    | anchorSalt      |
    |                 | digest instead of           |                 |
    |                 | anchoredDigest.             |                 |
    +-----------------+-----------------------------+-----------------+
    | rfc3161-eidas-  | As rfc3161-eidas-qualified, | token,          |
    | qualified-      | blinded the same way.       | anchorSalt      |
    | blinded         |                             |                 |
    +-----------------+-----------------------------+-----------------+
    | scitt           | Inclusion of anchoredDigest | logId,          |
    |                 | as a leaf of an append-only | leafIndex,      |
    |                 | Merkle log hashed as in     | treeSize,       |
    |                 | [RFC6962].  The identifier  | inclusionProof, |
    |                 | is kept for receipts that   | rootHash        |
    |                 | already carry it; this      |                 |
    |                 | method is not registration  |                 |
    |                 | with a SCITT Transparency   |                 |
    |                 | Service and its entry is    |                 |
    |                 | not a COSE receipt.         |                 |
    +-----------------+-----------------------------+-----------------+

                     Table 7: Timestamp anchor methods

Sirkkavaara               Expires 14 April 2027                [Page 20]
Internet-Draft                Vaara Receipt                 October 2026

   For every method a consumer MUST first recompute anchoredDigest from
   the receipt and reject the anchor if it differs.  For the rfc3161
   methods token is the base64 DER TimeStampToken, and a consumer
   requires its message imprint to equal anchoredDigest, or the blinded
   imprint below.  The method name is not proof of who signed the token:
   a consumer treats the attested time as independent of the issuer only
   when it checks the token signer against a certificate or trusted list
   it holds, and as qualified only when that list is a qualified trust
   list.

   A blinded method keeps the authority's request log from being matched
   against published receipts.  The producer draws a fresh 32-byte salt
   from a cryptographic random source, sends the authority the imprint
   SHA-256("vaara/anchor-blind/v1" || salt || D), where D is the 32 raw
   bytes of anchoredDigest and the label is ASCII, and carries the salt
   as anchorSalt (64 lowercase hexadecimal characters).  A producer MUST
   NOT reuse a salt.  A consumer MUST recompute the imprint, MUST reject
   a blinded anchor whose anchorSalt is absent or malformed, and MUST
   reject an unblinded method that carries anchorSalt, so that a blinded
   anchor is never read as a plain one.  Blinding does not hide the
   anchor from anyone holding the receipt, since the salt travels with
   it, and it does not hide the timing or volume of requests from the
   authority.

   For the scitt method logId is the base64 SHA-256 of the log's name,
   leafIndex and treeSize are integers, inclusionProof is an array of
   base64 sibling hashes, and rootHash is the base64 root at the time of
   append.  A consumer recomputes the root from the leaf (the 32 raw
   bytes of anchoredDigest) and inclusionProof. rootHash is the log
   operator's own claim.  The anchor witnesses the receipt only when the
   consumer checks rootHash against a tree head it holds independently
   of the receipt, directly at the same tree size or through a
   consistency proof ([RFC9162]) to a later head.

   The method registry is maintained by this document.  A consumer MUST
   NOT treat an anchor whose method it does not implement as verified,
   and MUST NOT reject the receipt because of it: the receipt's
   integrity rests on its signature, and an anchor is additional
   evidence.

   Registration with a SCITT Transparency Service ([RFC9943])
   complements an anchor and is not one.  A receipt's bytes can be the
   attached payload of a SCITT Signed Statement.  The service's receipt
   commits to that Signed Statement as registered, not to
   anchoredDigest, so it travels beside the receipt and is not carried
   in timestampAnchors.  A consumer verifies it against the statement
   bytes and the service's published keys, with no call to the service.

Sirkkavaara               Expires 14 April 2027                [Page 21]
Internet-Draft                Vaara Receipt                 October 2026

   A receipt MAY carry several anchors of different methods.  The
   producer's own time evidence (rfc3161 from its own authority, or
   scitt) and the legal anchor (rfc3161-eidas-qualified) are independent
   and can be added separately.

6.  Profiles

   A profile is a downstream specification that uses this envelope
   unchanged and defines only its own evidence record (the schema and
   contents behind evidenceRef), plus any join keys it needs.  A profile
   MUST state the vaara.receipt/vN version it pins to and SHOULD ship
   recomputable vectors.

   There is one binding mechanism, not one per plane.  Each named
   profile (Section 6.3, Section 6.4, Section 6.5, Section 6.6) names an
   external artifact by content address and binds it through this
   envelope unchanged; they differ only in which artifact is hashed and
   the evidenceRef.ref label.  Section 6.7 states that mechanism in
   schema-agnostic form: a single binding that does not depend on what
   is connected to it.  The named profiles are instances of it, kept
   because a given ecosystem pins to a label it recognizes as its own.

6.1.  Registry

   The profiles below pin to vaara.receipt/v1.  Vector paths are
   relative to the source repository ([VAARA-REPO]).

Sirkkavaara               Expires 14 April 2027                [Page 22]
Internet-Draft                Vaara Receipt                 October 2026

    +=============+=============================+=====================+
    |Profile      | Evidence schema             |Vectors              |
    +=============+=============================+=====================+
    |x402         | x402.settlement.*/v0        |tests/vectors/       |
    |settlement   |                             |x402_settlement_v0/  |
    |binding      |                             |                     |
    +-------------+-----------------------------+---------------------+
    |authorization| vaara.authorization/v0      |tests/vectors/       |
    |decision     |                             |authorization_v0/,   |
    |             |                             |tests/vectors/       |
    |             |                             |contiguity_v0/,      |
    |             |                             |tests/vectors/       |
    |             |                             |class_gate_v0/       |
    +-------------+-----------------------------+---------------------+
    |AP2 checkout | vaara.authorization/v0      |tests/vectors/ap2_v0/|
    |binding      | (names AP2 PEF frame_id)    |                     |
    +-------------+-----------------------------+---------------------+
    |TAP request  | tap.request/v0              |tests/vectors/tap_v0/|
    |binding      |                             |                     |
    +-------------+-----------------------------+---------------------+
    |generic      | vaara.authorization/v0      |tests/vectors/       |
    |external     | (names an                   |external_evidence_v0/|
    |execution    | external_execution_evidence |                     |
    |evidence     | slot)                       |                     |
    +-------------+-----------------------------+---------------------+
    |engine       | vaara.trail-decision/v0     |tests/vectors/       |
    |decision (the|                             |trail_decision_v0/,  |
    |floor)       |                             |tests/vectors/       |
    |             |                             |cage_v0/             |
    +-------------+-----------------------------+---------------------+

                         Table 8: Profile registry

   Three further suites in the same repository are related to this
   format and are not profiles of it, because the artifact each one
   verifies is not a vaara.receipt/v1 envelope: governance_decision_v0
   (Section 6.2), credential_binding_v0 (the signed HS256 grant a
   credential broker issues, the artifact the authorization profile's
   grantFingerprint names), and atlas_threat_v0 (a flat HMAC record
   exercised against MITRE ATLAS agent threat patterns).  Each ships a
   standalone checker, and none defines an evidence schema for
   evidenceRef.

Sirkkavaara               Expires 14 April 2027                [Page 23]
Internet-Draft                Vaara Receipt                 October 2026

6.2.  Related Suite: Governance Decision Records

   This section is informative. tests/vectors/governance_decision_v0/
   holds signed governance decision and outcome records in the contract
   shape proposed for the CrewAI framework (schemas
   crewai.governance.decision/v1 and crewai.governance.outcome/v1), each
   record wrapped as {"record", "signature"} with an ES256 signature
   over the JCS encoding of the record.  They are not vaara.receipt/v1
   envelopes and define no evidence schema for evidenceRef; earlier
   revisions of this document described them as the floor of this
   format, which they were not.

   What the suite does pin is the part a third party recomputes with a
   JCS library and a signature library alone: an intent_ref derived from
   the schema, agent, action type, normalized scope and an intent digest
   over the call parameters, so a re-presented authorization recomputes
   to the same identity on a retry; a target-state digest and a decision
   context hash binding the policy set and the continuation; four fail-
   closed verdicts (intent mismatch, target-state drift, continuation
   mismatch, duplicate outcome); and a per-run completeness sequence
   with a terminal seal, the same layering as Section 6.4.  The member
   names of these preimages are those of the records themselves, in
   snake case, and the checker is tests/vectors/
   governance_decision_v0/_check_independent.py; a second checker with
   no dependencies at all, _check_zerodep.py, reaches the same verdicts.

   The case cases/unicode_scope.json carries a normalized scope with
   non-ASCII characters.  Under RFC 8785 these are emitted as their raw
   UTF-8 bytes; a producer that escapes them to \uXXXX form
   canonicalizes different bytes and fails the vector, which is the
   cheapest way to catch a canonicalizer that is sorted JSON but not
   JCS.  That property holds for every digest in this document.

6.3.  Profile Example: x402 Settlement Binding

   This profile binds an x402 payment settlement to a Vaara receipt
   across an action lifecycle, on a generic rail and on the Sui exact-
   payment rail.  It adds:

   *  A settlement record (schema = x402.settlement.<rail>/v0) whose JCS
      digest is the receipt's evidenceRef.digest.

   *  A join key actionRef = sha256(JCS({agentId, actionType, scope,
      timestampMs, seq, terminal})), carried on the settlement, so an
      in-progress receipt (terminal: false) cannot be presented where
      the terminal one is required.

Sirkkavaara               Expires 14 April 2027                [Page 24]
Internet-Draft                Vaara Receipt                 October 2026

   A third party recomputes three per-step verdicts (action-ref
   recomputes, settlement binding resolves, signature verifies) and one
   lifecycle verdict, with only the settlement and the receipt in hand.
   See _check_independent.py in the vectors directory.

6.4.  Profile Example: Authorization Decision

   This profile turns an enforcement decision into a receipt.  A
   credential broker authorizes a tool call against a signed,
   attestation-bound grant with typed capability scopes; the gateway's
   verdict, allow or deny, is minted as a receipt instead of being
   discarded.  The decision maps onto the envelope verdict vocabulary:
   an allowed call is "allow", a refused call is "block" carrying the
   machine reason (capability_exceeded, binding_unknown,
   missing_credential, ...) as decisionDerived.reason.  It adds:

   *  An authorization record (schema = vaara.authorization/v0) whose
      JCS digest is the receipt's evidenceRef.digest.  It binds
      toolName, tenantId, the grant by content address (grantFingerprint
      = sha256(JCS(grant)) over the grant with its signature member
      removed, the bytes the grant's signature covers; an ECDSA
      signature has two valid encodings for one signing act, so a digest
      over the signature would give one grant two identities), the
      runtime argument commitment (argsCommitment = sha256(JCS(args))),
      the evaluated capabilities, and the verdict / reason.

   *  The raw arguments never enter the record; only their commitment
      does, so the receipt is publishable while the arguments stay
      private.  An auditor holding the arguments out of band recomputes
      the commitment and re-runs the verdict.

   *  An optional coverage block names the observation boundary the
      decision was made under, inside the record and therefore under the
      signature.  It binds the boundary (the chokepoint identity), the
      serverFingerprint (the exact capability surface in scope,
      manifest:sha256(JCS(tools)) or the command hash), and a scope
      literal stating that only calls routed through the chokepoint are
      observed.  A tool reached on an out-of-band path is out of
      coverage.  The block is absent when no boundary is asserted,
      leaving the record byte-identical to a coverage-free decision.

Sirkkavaara               Expires 14 April 2027                [Page 25]
Internet-Draft                Vaara Receipt                 October 2026

   *  An optional completeness block scopes a sequence to that boundary,
      inside the record and therefore under the signature.  It binds the
      boundaryId (the same boundary the coverage block names), a
      monotonic seq starting at 0 with no gaps by construction, and a
      runningCount equal to the total receipts issued under the boundary
      up to and including this one (runningCount = seq + 1).  The block
      is absent when no sequence is asserted, leaving the record byte-
      identical to a completeness-free decision.

   *  An optional sealing record finalizes the boundary: a terminal
      completeness block ({boundaryId, sealed: true, total: N}) that
      pins the boundary's final count independently of the per-record
      sequence.  It is additive and emitted once the boundary is closed;
      a boundary that is never sealed verifies exactly as before, with
      the seal absent and the stream byte-identical.  The seal may also
      carry maxClass, the highest action class the boundary authorized;
      it bounds a gap's worst case and is itself optional.

   A verdict is only as meaningful as what the issuer could see. "allow"
   over an unbounded surface and "allow" over a stated one are identical
   bytes with opposite meaning, so an absent refusal reads as fact only
   against a declared scope: "not refused within this boundary", never
   "not observed".  The coverage block carries that boundary in the
   trace itself, so it is recomputable evidence rather than a separate
   trust root.  The verdict stays a thin read over it.  The chokepoint
   remains an observer of what passes through it, not a claim about what
   does not.

   The deny case is the point.  A refused call leaves a signed, content-
   addressed, portable proof of the non-action: a third party recomputes
   the verdict from the grant and the arguments and confirms the
   refusal, trusting only the issuer's public key.  A third party
   recomputes five verdicts per case (grant fingerprint, argument
   commitment, capability verdict, evidence binding, signature) with
   only the grant, the arguments, the evidence, and the receipt in hand.
   See _check_independent.py.

   Coverage states the boundary; completeness makes a gap inside it
   provable.  With the per-boundary seq contiguous by construction and
   the runningCount signed into each record, a dropped receipt is a
   missing sequence number that any holder detects from the receipts
   alone: the highest running count names how many exist, so a short set
   is self-evidently incomplete and the absent seq is named.  This needs
   no issuer access and no external witness.  The tests/vectors/
   contiguity_v0/ vectors and the "vaara verify-contiguity" surface
   carry that check.

Sirkkavaara               Expires 14 April 2027                [Page 26]
Internet-Draft                Vaara Receipt                 October 2026

   The per-record running count alone cannot tell a pure tail truncation
   (holding 0..k with nothing after) from a complete stream, since the
   latest held count is then k + 1 and reads as whole.  The optional
   sealing record closes that gap: when a boundary is finalized, the
   holder expects max(seq + 1, runningCount, total) records, so a
   dropped tail shows as the missing range up to the sealed total.  A
   boundary that is never sealed verifies exactly as before.  One
   residual remains, and it is irreducible from the held set alone: a
   suffix drop that also suppresses the sealing record leaves nothing to
   detect.  Closing that is the job of an rfc3161 anchor over the
   running count (Section 5), which attests that at time T, N receipts
   existed under the boundary.  The layering is seq for order, the hash
   chain for tamper-evidence, the sealing record for a truncated tail,
   and the timestamp anchor for the seal-suppressed residual.

   A gap proves that a record is absent but not what it would have
   authorized.  When worst-case-governs is the reading, the seal's
   optional maxClass bounds it: it names the highest action class the
   boundary authorized, so a missing record could have authorized an
   action of at most that class.  The verifier surfaces this as
   worstCaseClass, computed from the held set and the seal alone, with
   no issuer.  The field is optional; absent it, a gap reports only that
   a record is missing.

   Beyond bounding a gap at audit time, the sealed maxClass is
   consumable at enforcement time.  A chain recipient gating its own
   next unattended action holds a policy set of action classes it will
   proceed under and permits if and only if the sealed worst-case class
   is a member of that set, failing closed when no class is sealed.
   This is a membership test, not an ordering: this document computes no
   ordering over class labels, so the recipient asks "is the sealed
   class one I permit", never "is it at or below a ceiling".  Because
   the seal bounds a gap's worst case at maxClass, a permitted class
   permits even when the boundary has a gap: the recipient consumes the
   committed bound and does not re-derive the chain or query a log.  The
   bound is trustworthy under the honest issuer whose seal commits
   before any tail is trimmed; a seal that under-states the class is a
   reconciliation question against the issuer's log, not one this held-
   set-alone gate answers.

   maxClass lives in the unsigned evidence block, so a recipient MUST
   NOT consume it raw.  It rides under signature only through the
   binding: the seal's signed decisionDerived.evidenceRef.digest is
   "sha256:" + JCS(evidence), so recomputing that digest proves the
   class is the class that was signed.  Before gating, a recipient MUST
   verify each receipt's signature and that its evidence recomputes to
   the signed digest; a seal whose binding fails is not trusted,
   contributes no class, and the gate fails closed.  Without this, an

Sirkkavaara               Expires 14 April 2027                [Page 27]
Internet-Draft                Vaara Receipt                 October 2026

   agent loosens the gate by relabeling an irreversible action's class
   into a permitted one while the record signature, which never covered
   the evidence, still verifies.  The conformance vectors are in
   tests/vectors/class_gate_v0/; the deny_relabeled case carries exactly
   this attack and the independent checker rejects it.

6.5.  Profile Example: AP2 Checkout Binding

   This profile binds an AP2 checkout to the post-checkout agent actions
   a credential broker authorizes, so the actions taken after a payment
   settles carry the same recomputable, gap-evident record as the
   authorization decisions in Section 6.4.  It reuses the
   vaara.authorization/v0 evidence record unchanged and adds a join to
   the AP2 Payment Evidence Frame (PEF, AP2 PR #274):

   *  The AP2 checkout emits a PEF whose frame_id = sha256(JCS(frame)),
      with frame_id and signature excluded from the preimage, and whose
      receipt_hash = sha256(JCS(receipt)) content-addresses the wrapped
      Checkout Receipt.  Canonicalization is
      urn:x402:canonicalisation:jcs-rfc8785-v1 (JCS / RFC 8785), the
      same as this envelope, so the address joins with no re-
      canonicalization.

   *  Each post-checkout authorization receipt names the checkout it
      followed by content address: decisionDerived.evidenceRef.ref =
      ap2:checkout/<frame_id>, under the receipt signature.  The AP2
      task scope is the coverage.boundary (Section 6.4), and the
      completeness block sequences the actions under it.

   The identity of the checkout is the PEF frame_id, a content address
   the payment side already computes; the completeness of the actions
   taken under it is the vaara.authorization/v0 contiguity stream.  A
   per-action hash says an action was recorded; the running count says
   none inside the AP2 task boundary was dropped.  A third party
   recomputes the frame address, confirms every receipt names that
   checkout, resolves each evidence binding, verifies each signature,
   and re-runs the gap check, with only the PEF and the held receipts in
   hand.  See tests/vectors/ap2_v0/_check_independent.py.  AP2 can pin
   from the point the Checkout Receipt ends rather than define a new
   post-settlement primitive.

Sirkkavaara               Expires 14 April 2027                [Page 28]
Internet-Draft                Vaara Receipt                 October 2026

6.6.  Profile Example: TAP Request Binding

   This profile binds a Visa Trusted Agent Protocol (TAP) request to the
   action a trusted agent takes under it, across the action lifecycle,
   so the post-authorization record is the same recomputable evidence as
   any other decision receipt.  It adds a TAP request evidence record
   (schema = tap.request/v0) whose JCS digest is the receipt's
   evidenceRef.digest, and the join key actionRef = sha256(JCS({agentId,
   actionType, scope, timestampMs, seq, terminal})) carried on the
   request:

   *  The trusted agent presents the TAP request to the relying party.
      The decision receipt names it by content address:
      decisionDerived.evidenceRef.digest = sha256(JCS(request)),
      decisionDerived.evidenceRef.ref = tap:request/<actionRef>, both
      under the receipt signature.  Canonicalization is JCS / RFC 8785,
      the same as this envelope, so the address joins with no re-
      canonicalization.

   *  The lifecycle lives in the join key.  Because the action tuple
      covers terminal, the in-progress (terminal: false) request has a
      different actionRef than the final (terminal: true) one, and the
      in-progress receipt does not resolve against the terminal request.
      A mid-action receipt cannot be presented where the final one is
      required.

   The verdict is recomputable offline.  A third party recomputes the
   action ref, resolves the request binding, and verifies the signature
   with only the TAP request, the held receipts, and the issuer's public
   key, with the TAP service offline and no live verifier endpoint to
   trust.  See tests/vectors/tap_v0/_check_independent.py.  TAP can pin
   to vaara.receipt/v1 for the post-authorization record rather than
   define a new primitive.

6.7.  Profile: Generic External Execution Evidence

   This is the schema-agnostic binding the named profiles above are
   instances of.  It takes any external execution-evidence artifact,
   content-addresses it, and binds it through this envelope unchanged,
   with no field names that depend on what produced it.  A verifier
   carrying an external_execution_evidence slot (linked_call_id /
   evidence_hash / evidence_type, written linkedCallId, evidenceHash and
   evidenceType in the vectors) resolves that slot against a
   vaara.receipt/v1 authorization receipt as the recomputable producer:

Sirkkavaara               Expires 14 April 2027                [Page 29]
Internet-Draft                Vaara Receipt                 October 2026

   *  evidence_hash = sha256(JCS(evidence_record)), equal to the
      receipt's decisionDerived.evidenceRef.digest, so the slot and the
      receipt name the same recomputable artifact (JCS / RFC 8785, no
      re-canonicalization).

   *  linked_call_id is the call the receipt names:
      decisionDerived.evidenceRef.ref = mcp:call/<linked_call_id>, under
      the receipt signature.

   *  evidence_type is the receipt's evidence schema
      (vaara.authorization/v0).

   The trace is the coverage.boundary, and each receipt carries a signed
   completeness block (seq + runningCount), so the held set proves not
   only that each named call's evidence resolves but that none inside
   the boundary was dropped.  A slot's evidence_hash alone proves a
   given record exists; the completeness block turns a silent drop into
   a named gap.  The dropped vector withholds one record, slot and
   receipt both, and the signed running count still proves it existed.

   A third party recomputes every verdict offline with only the held
   slots, the receipts, and the issuer's public key, with no live
   verifier endpoint to trust.  See tests/vectors/
   external_evidence_v0/_check_independent.py.  Any plane that emits
   execution evidence pins here by naming its artifact through this
   slot, rather than defining a new primitive or a profile of its own.

6.8.  Profile: Engine Decision

   An engine that keeps a hash-chained audit trail writes one decision
   receipt per decision it records on that trail.  The evidence record
   is the decision as the trail holds it, under schema vaara.trail-
   decision/v0.  It carries no tool arguments, so a receipt can leave
   the machine without them.

Sirkkavaara               Expires 14 April 2027                [Page 30]
Internet-Draft                Vaara Receipt                 October 2026

   +====================+=============================================+
   | Field              | Meaning                                     |
   +====================+=============================================+
   | schema             | "vaara.trail-decision/v0".                  |
   +--------------------+---------------------------------------------+
   | recordId, actionId | The trail record and the action it decided. |
   +--------------------+---------------------------------------------+
   | eventType          | "decision_made" or "action_blocked".        |
   +--------------------+---------------------------------------------+
   | agentId, toolName, | As recorded. tenantId is "" when unset.     |
   | tenantId           |                                             |
   +--------------------+---------------------------------------------+
   | decision, reason   | The trail's verdict ("allow", "escalate" or |
   |                    | "deny") and its reason.                     |
   +--------------------+---------------------------------------------+
   | riskScore          | Decimal string.                             |
   +--------------------+---------------------------------------------+
   | decidedAt          | ISO 8601 UTC with milliseconds.             |
   +--------------------+---------------------------------------------+
   | recordHash         | "sha256:" and the trail record's own hash.  |
   +--------------------+---------------------------------------------+
   | previousHash       | "sha256:" and the hash of the record before |
   |                    | it.  An empty genesis link is written as    |
   |                    | the SHA-256 of the empty string.            |
   +--------------------+---------------------------------------------+
   | decisionDetail     | The refinement behind the verdict, present  |
   |                    | only when the trail record carries one.     |
   +--------------------+---------------------------------------------+
   | approver,          | The disposition: present together, only     |
   | humanDisposed      | when the trail record carries an approver.  |
   |                    | See below.                                  |
   +--------------------+---------------------------------------------+
   | cage               | OPTIONAL.  The cage block (Section 6.8.1).  |
   +--------------------+---------------------------------------------+

            Table 9: vaara.trail-decision/v0 evidence members

   The envelope writes the trail's "deny" as "block".
   backLink.attestationDigest is previousHash, backLink.attestationNonce
   is recordId, and evidenceRef.ref is "vaara:trail/" followed by
   recordId.  A verifier checks the signature and the evidence digest as
   in Section 3.2 and Section 4.  With the trail in hand it also looks
   up recordId and confirms that the stored record hash matches
   recordHash; a receipt whose record is missing from the trail, or
   whose hash differs, fails.  See tests/vectors/
   trail_decision_v0/_check_independent.py.

Sirkkavaara               Expires 14 April 2027                [Page 31]
Internet-Draft                Vaara Receipt                 October 2026

   approver and humanDisposed name what kind of party disposed of the
   decision, inside the evidence record and therefore under the
   signature.  approver is exactly "human" or "policy", and
   humanDisposed is a boolean that is true only when a human acted on
   this decision.  A producer MUST NOT emit humanDisposed true with an
   approver other than "human".  The converse is permitted: approver
   "human" with humanDisposed false records a human who reviewed while
   the disposition stayed automatic, which only narrows the claim.  Both
   members are absent when no disposition was asserted, leaving the
   record byte-identical to a disposition-free decision.

   The disposition exists because one verdict word covers dispositions a
   relying party has to separate.  A decision admitted because a human
   approved it, and a decision admitted because an earlier human
   approval was replayed against a matching argument commitment, both
   carry the verdict "allow".  The second was disposed of by the
   deployment, against an argument commitment some human approved at
   another time and on another action.  Where that difference reaches a
   consumer only as free text, a consumer that must branch on human
   involvement cannot do it from the signed members.  The approver
   vocabulary is closed at two values: a value an implementation may
   invent is a value a relying party cannot branch on.

   A consumer MUST NOT infer human involvement from absent disposition
   members.  Absence states that no disposition was asserted, and
   records written before these members existed carry none.  See
   tests/vectors/decision_disposition_v0/ for the live-approval,
   replayed-approval and policy-claiming-human cases.

6.8.1.  Cage Block

   The cage block states which cage, if any, the process that made the
   decision ran in, and whether the issuer confirmed at decision time
   that the confinement held on that process.  A cage here is any
   isolation layer an agent is started in: a mandatory access control
   profile, a system call filter, a user-space kernel, or a virtual
   machine.  The block is a member of the evidence record, so
   evidenceRef.digest and the signature bind it like any other member.

Sirkkavaara               Expires 14 April 2027                [Page 32]
Internet-Draft                Vaara Receipt                 October 2026

    +==============+=========+==========+=============================+
    | Field        | Type    | Required | Meaning                     |
    +==============+=========+==========+=============================+
    | driver       | string  | MUST     | The name of the cage's      |
    |              |         |          | driver, never empty, or     |
    |              |         |          | "none" when no cage was     |
    |              |         |          | declared to the deciding    |
    |              |         |          | process.                    |
    +--------------+---------+----------+-----------------------------+
    | confirmed    | boolean | MUST     | Whether the confinement was |
    |              |         |          | confirmed at decision time, |
    |              |         |          | as defined below.           |
    +--------------+---------+----------+-----------------------------+
    | basis        | string  | MUST     | What the confirmation rests |
    |              |         | unless   | on: "declared" when only    |
    |              |         | driver   | the launcher's declaration  |
    |              |         | is       | stands, otherwise the name  |
    |              |         | "none"   | of the fact that was read.  |
    +--------------+---------+----------+-----------------------------+
    | configDigest | string  | MAY      | "sha256:" and 64 lowercase  |
    |              |         |          | hexadecimal characters over |
    |              |         |          | the cage's effective        |
    |              |         |          | configuration.              |
    +--------------+---------+----------+-----------------------------+
    | upstream     | string  | MAY      | Informative.  The cage's    |
    |              |         |          | own name and version.       |
    +--------------+---------+----------+-----------------------------+
    | name         | string  | MAY      | Informative.  The name of   |
    |              |         |          | this launch inside the      |
    |              |         |          | cage.                       |
    +--------------+---------+----------+-----------------------------+

                        Table 10: Cage block members

   A block with driver "none" MUST carry confirmed false and MUST NOT
   carry any other member.  A block with any other driver MUST carry
   basis.

   confirmed true means exactly this: at decision time the issuer read,
   on the deciding process or on the platform under it, the fact that
   basis names, and the fact held. confirmed true MUST be accompanied by
   a basis other than "none" or "declared".  It does not mean that the
   cage enforced the configuration configDigest names, that the cage is
   free of defects, or that any party other than the issuer observed the
   fact. confirmed false with basis "declared" means that a launcher
   declared the cage and the issuer did not confirm it.

Sirkkavaara               Expires 14 April 2027                [Page 33]
Internet-Draft                Vaara Receipt                 October 2026

   The block names the deciding process, not the agent the decision was
   about.  One launch can therefore produce blocks that differ by the
   surface the decision was made on: a decision made inside the caged
   tree names the cage and confirms it; a decision made by a process
   outside the tree about that tree (a file-system guard, an egress
   proxy) names that process's own confinement, which may be "none" or
   the declared block unconfirmed.  Each is true of the process that
   signed it.  A consumer collecting one launch's receipts groups them
   by subject and name, not by the block.

   Each driver defines which bytes its configDigest covers.  A consumer
   uses configDigest as a comparator: two receipts with the same driver
   and configDigest ran under the same declared configuration.  A
   consumer that holds the configuration and the driver's rule MAY
   recompute the digest; one that does not treats it as an opaque value.
   A configDigest that does not match the stated form makes the block
   non-conforming.

   The values of driver and basis form open sets.  Their names carry no
   normative meaning beyond the rules above; Appendix B lists the values
   in use at the time of writing.  A consumer MUST ignore cage block
   members it does not recognize.  An evidence record without a cage
   block makes no claim about confinement, and a consumer MUST NOT read
   its absence as either confined or unconfined.

   The conformance vectors are tests/vectors/cage_v0/: a run outside any
   cage, a cage declared and not confirmed, and a confirmed cage,
   written by a reference engine; a block changed after signing, which
   fails the evidence digest; and three blocks that are signed and
   digest-consistent but break a rule of the block (confirmed on basis
   "declared", confirmed with driver "none", and a malformed
   configDigest).  The standalone checker tests/vectors/
   cage_v0/_check_independent.py gives each file a signature, evidence,
   and cage verdict and imports no issuer code.

7.  Conformance

   An implementation conforms to vaara.receipt/v1 if, for every receipt
   it emits:

   1.  The receipt keeps the rules of Section 3 and Section 4: one kind,
       no undefined members, an alg defined in Section 3.1 and repeated
       unchanged in the issuer block, a decision or status value defined
       there, and a well-formed completeness block where one is present.

   2.  The Section 3.2 signature verifies against the stated alg and
       key.

Sirkkavaara               Expires 14 April 2027                [Page 34]
Internet-Draft                Vaara Receipt                 October 2026

   3.  evidenceRef.digest equals sha256(JCS(evidence_record)) for the
       referenced record, under one of the Section 2 canonicalization
       labels.

   4.  Any timestampAnchors[].anchoredDigest equals the digest of the
       signed payload of the same receipt, and any
       existenceProof.recordDigest equals the digest of the receipt with
       existenceProof removed.

   5.  For an execution receipt (Section 3.7),
       backLink.attestationDigest equals "sha256:" of the JCS-canonical
       predecessor and backLink.attestationNonce equals the
       predecessor's issuerAsserted.nonce; and when status is
       "executed", resultCommitment.projectionDigest equals "sha256:" of
       the projection bytes.

   6.  Any cage block in an evidence record (Section 6.8.1) keeps the
       rules of that section.

   The committed vectors plus _check_independent.py are the reference
   conformance suite; running the x402 profile checker and having it
   exit 0 is a passing run for that profile.

   The same vectors serve as recomputable test evidence for the
   reversibility classification and enforcement controls in OWASP AISVS
   1.0 ([AISVS2026]), specifically C9.2.3 (trusted reversibility
   classification), C9.2.4 (runtime enforcement of reversibility), and
   C9.2.10 (highest-impact class enforcement across multi-step chains).

8.  Implementation Status

   This section records the status of known implementations at the time
   of writing, per [RFC7942].  It is informational and may be removed
   before publication.  The format is not specific to any single agent
   runtime; it records decisions about autonomous actions in general, of
   which AI agent tool calls are one case.

   A reference implementation ships the format at three layers, all in
   the source repository ([VAARA-REPO]):

   *  A library that emits and verifies receipts, including the floor
      profile (Section 6.8): a default install signs one receipt per
      decision it records.

Sirkkavaara               Expires 14 April 2027                [Page 35]
Internet-Draft                Vaara Receipt                 October 2026

   *  The public conformance vectors under tests/vectors/ with per-
      profile standalone checkers (_check_independent.py) that import no
      issuer code, so a second party recomputes every digest, signature,
      back link, and completeness verdict from the bytes alone.
      Independent reimplementations have reproduced these vectors.

   *  A desktop application for macOS that reads the engine's audit
      trails, shows each allow, escalate, or deny decision as it is
      recorded, routes the machine's agent clients through the
      governance proxy, and verifies decision receipts with its own JCS,
      SHA-256, and P-256 code written in Swift.  That verifier runs
      against the same conformance vectors as the library in continuous
      integration, so the two cannot drift apart unnoticed.

   A default install of the library signs a receipt for every decision.
   The signing dependencies are part of the base package, not an
   optional extra.

   The implementation also takes a receipt to roots outside its own
   signature.  It registers a receipt with an IETF SCITT Transparency
   Service ([RFC9943]) over the reference APIs ([I-D.ietf-scitt-scrapi])
   and verifies the service's receipt with no network access
   (Section 5).  A continuous-integration job registers a decision
   receipt with a SCITT ledger built from its public source, stops the
   ledger, and verifies the result offline.  For an AMD SEV-SNP host, it
   checks an attestation report's signing key offline against AMD's root
   key: the root certifies the intermediate key, the intermediate
   certifies the VCEK or VLEK ([AMD-VCEK]), the VCEK's chip identifier
   and TCB match the report ([AMD-SNP-ABI]), and the report signature
   verifies under it.  The check passes on a report from production
   hardware.  It does not consult AMD's certificate revocation list.
   The in-guest report emitter follows the kernel interface and has not
   yet been run inside a guest by the implementation.

   The library, vectors, and checkers are exercised on every release.
   The application is built from source on the installing machine by its
   package formula and is not distributed as a notarized build.

9.  Versioning

   The envelope version is the integer "version" member and the
   vaara.receipt/vN schema identifier.  A change to the signed-payload
   member set, the canonicalization, or the signature construction bumps
   N.

   A new OPTIONAL member of a block defined in Section 3 or Section 4 is
   added only by a revision of this document and does not bump N.
   Because those blocks are closed (Section 3), a consumer built to an

Sirkkavaara               Expires 14 April 2027                [Page 36]
Internet-Draft                Vaara Receipt                 October 2026

   earlier revision rejects a receipt that carries the new member.  That
   is intended: it fails closed rather than verifying bytes it does not
   understand.  A producer that needs receipts accepted by such
   consumers omits the new member.  New anchor methods and new profiles
   do not change how the envelope is parsed.

10.  Security Considerations

   The integrity of a receipt rests on the Section 3.2 signature over
   the JCS-canonical signed payload, not on any timestamp anchor or
   trust root.  A consumer MUST verify that signature, under the
   algorithm "alg" names and with the key the issuer block names through
   iss and secretVersion, before relying on any field.  Because the
   signed payload excludes "signature" and "timestampAnchors", anchors
   added after signing cannot alter the signed content; a consumer MUST
   recompute each anchoredDigest from the signed payload rather than
   trusting the anchor's stated value.

   Verifying that signature establishes that the key the issuer block
   names produced the signed payload and that the payload has not
   changed since.  It says nothing about the state of that key now.
   Offline verification is a computation over the parameters the
   consumer holds, while revocation is a property of the present, and
   this document defines no revocation mechanism and places no freshness
   requirement on key material.  A consumer MUST NOT treat a signature
   that verifies as evidence that the signing key is still valid.  Where
   a decision depends on revocation state, the key resolution path and
   the staleness a deployment accepts are operational parameters of that
   deployment and MUST be stated by it; the receipt does not carry them.

   Recomputability depends entirely on canonicalization.  A producer and
   a consumer that disagree on JCS output for the same JSON value will
   compute different digests; implementations MUST use a conformant JCS
   ([RFC8785]) implementation and MUST treat any of the three accepted
   labels as the same algorithm.

   The argument commitment in the authorization profile (Section 6.4)
   lets a receipt be published while the raw arguments stay private, but
   a low-entropy argument set is open to a dictionary attack against the
   commitment.  Producers SHOULD ensure the committed object carries
   sufficient entropy (for example a per-call nonce) where argument
   confidentiality matters.

   An absent refusal is evidence only within a declared coverage
   boundary (Section 6.4).  A reader MUST NOT read a missing receipt as
   "the action did not happen"; without a coverage block it means only
   "not observed", and with one it means "not refused within this
   boundary".  The completeness block makes a dropped receipt inside the

Sirkkavaara               Expires 14 April 2027                [Page 37]
Internet-Draft                Vaara Receipt                 October 2026

   boundary detectable, but a pure tail truncation is not detectable by
   sequence contiguity alone and requires a timestamp anchor over the
   running count to close.

   A decision receipt records what was decided.  It does not record what
   followed.  A decision receipt carrying the verdict "allow", with no
   execution receipt bound to it by backLink, establishes that the
   action was permitted and establishes nothing about whether it ran.  A
   consumer MUST NOT read a decision receipt as evidence that the action
   took effect: the executed status lives in the execution receipt's
   outcomeDerived and is signed there (Section 3.7).  Only the pair
   establishes that an action was permitted and then took effect, which
   is why backLink is a required member.

   A recipient that consumes a sealed maxClass to gate its own next
   action (Section 6.4) MUST bind the class to the signature before
   acting on it. maxClass sits in the unsigned evidence block and is
   covered by the signature only through the seal's
   decisionDerived.evidenceRef.digest = "sha256:" + JCS(evidence).  A
   recipient MUST verify each receipt's signature and that its evidence
   recomputes to that signed digest; a seal whose binding fails
   contributes no class and the gate fails closed.  A recipient that
   reads maxClass raw, without recomputing the binding, can be made to
   permit an irreversible action whose class an agent relabeled into a
   permitted one while the record signature, which never covered the
   evidence, still verifies.  The gate is also a membership test over
   class labels, not an ordering; this document defines no ordering over
   classes, and a recipient MUST NOT infer one.

   The cage block (Section 6.8.1) is an assertion by the issuer, bound
   by the issuer's signature. confirmed true is not an attestation by
   the cage, the kernel, or the hardware: a compromised issuer can sign
   a block that claims confinement it did not have, and a process can be
   confined in ways the issuer cannot see.  A consumer that needs
   confinement established independently of the issuer needs evidence
   from outside it, such as a hardware attestation of the platform.
   Bases differ in strength. "hypervisor_present" shows that a virtual
   machine is underneath and not which one or how it is configured, and
   a mandatory access control label shows that a profile is attached and
   not what the profile allows.  configDigest names the declared
   configuration; it does not show that the declared configuration is
   the one in force.

Sirkkavaara               Expires 14 April 2027                [Page 38]
Internet-Draft                Vaara Receipt                 October 2026

11.  Privacy Considerations

   A receipt is built to be handed to parties outside the issuer, so
   whatever it carries in clear travels with it.  The signed blocks
   carry identifiers (iss, sub, aud, taskId), times, a decision, and an
   optional free-text reason.  Evidence records defined by profiles
   carry more: the engine decision profile (Section 6.8) carries the
   agent identifier, the tool name, the tenant, and the reason.  A
   producer SHOULD treat sub, agent and tenant identifiers, and reason
   text as potentially personal data where the subject or the operator
   is a natural person, and SHOULD keep personal data out of reason.

   The format keeps the action's inputs and results out of the receipt
   by design.  Arguments and results enter only as commitments
   (Section 3.7, Section 6.4), and the evidence record is bound by
   digest, so a receipt can be shared while the evidence stays with the
   operator.  A commitment over a small or predictable value can be
   reversed by guessing; the dictionary-attack paragraph in Section 10
   applies to every commitment in this document, not only to arguments.

   Receipts are durable and have no expiry.  A receipt that has left the
   issuer cannot be withdrawn, and its signature keeps verifying.
   Producers subject to erasure obligations should keep erasable data in
   evidence records held by the operator, where deleting the record
   leaves the receipt verifiable and the evidence unrecoverable from it.
   Timestamp anchors disclose to the time-stamping authority that a
   receipt existed at a time; the blinded methods (Section 5) keep the
   authority's log from being matched to published receipts.

12.  Regulatory Applicability

   This section is informative.  It states which element of the receipt
   carries what a named legal or standards text asks for, and which
   public conformance suite in [VAARA-REPO] exercises that element.  It
   does not assert that a deployment holding receipts complies with any
   text.  Compliance is a property of the deployment and of its legal
   reading; the receipt is evidence a reader can recompute.  Every suite
   named below ships a checker that imports no issuer code (Section 7).

   The mapping covers Union law first because that is where the format
   is deployed.  Other regimes with an equivalent logging obligation map
   onto the same rows and are not enumerated.

   [AIACT] Art. 12(1): Automatic recording of events over the
   lifetime of a high-risk system.
      The decision record and the execution receipt that answers it
      (Section 3, Section 3.7), one pair per action.  Suites:
      execution_receipt_v0, decision_pairing_v0.

Sirkkavaara               Expires 14 April 2027                [Page 39]
Internet-Draft                Vaara Receipt                 October 2026

   [AIACT] Art. 12(1), read with Art. 19 and Art. 26(6): Records that
   stay verifiable across a retention period measured in years, held
   by the provider and by the deployer.
      Signature over canonical bytes (Section 2) with the signing key
      identified in the envelope, so a record verifies after the issuer
      rotates keys; the regulator package export.  Suites:
      key_rotation_v0, article12_fold_v0.

   [AIACT] Art. 12(1): A record of events, which a reader can only
   rely on if it can tell a missing record from an event that did not
   occur.
      Gap-evident contiguity over a declared coverage boundary,
      checkable from the held receipts and the issuer's public key
      alone.  Suites: contiguity_v0.

   [AIACT] Art. 14: Human oversight, including the ability to
   intervene and override.
      The disposition of a decision: who produced the allow, deny or
      escalate, so that a record cannot overstate human involvement.
      Suites: decision_disposition_v0.

   [AIACT] Art. 13: Operation transparent enough for deployers to
   interpret output.
      The one-page audit summary rendered from a record set: verdict,
      counts, findings, with pinned bytes.  Suites: audit_summary_v0,
      record_set_v0.

   [eIDAS] Art. 41 and 42: A qualified electronic time stamp enjoys a
   presumption of accuracy of the date and time it indicates.
      An RFC 3161 token from a qualified trust service over the record's
      canonical bytes: the rfc3161-eidas-qualified anchor on a decision
      receipt (Section 5) and existenceProof on an execution receipt
      (Section 3.6).  Suites: qualified_time_v0, which exercises
      existenceProof.

   [GDPR] Art. 5(1)(c): Data minimisation.
      Evidence enters the receipt by content digest, never by value
      (Section 4); the record proves what was decided on without
      carrying it.  Suites: evidence_ref_v0.

   [GDPR] Chapter V: Transfers of personal data to third countries.
      A signed data-locality record binding one action's transfer facts
      to the decision that ran, optionally with a region attestation
      from a party other than the issuer.  Suites: data_locality_v0.

Sirkkavaara               Expires 14 April 2027                [Page 40]
Internet-Draft                Vaara Receipt                 October 2026

   [DORA-RTS] Art. 12: Logging that is protected against unauthorised
   alteration and whose clocks are synchronised.
      Hash chain and signature over canonical bytes; the external time
      anchor as the clock the issuer does not control.  Suites:
      transparency_consistency_v0, qualified_time_v0.

   [PLD] Art. 9: Disclosure of relevant evidence at the claimant's
   request, in an accessible and understandable form.
      A receipt recomputable by the claimant's expert from the bytes,
      with no access to the producer's systems.  Suites:
      record_conformance_v0, article12_fold_v0.

   [ISO42001] Annex A, event logging control: Recording of AI system
   event logs.
      The same decision and receipt pair; the summary page is the
      management-system artefact.  Suites: execution_receipt_v0,
      audit_summary_v0.

   Two limits apply to every row.  First, a receipt records what its
   issuer observed at signing time; the revocation and key-status limits
   in Section 10 hold regardless of which obligation the record is read
   against, and a suite (revocation_freshness_v0) pins what a clean
   answer may claim.  Second, the rows name obligations on the operator
   of a system, and the receipt is the operator's evidence; the format
   places no obligation on a verifier beyond recomputation.

13.  Related Work

   Several independent research efforts published in 2026 converge on
   the same core observation this document implements: that governing
   agent behavior requires binding decisions to individual actions
   rather than to sessions or agents, using content-addressed,
   independently verifiable records.

   Salfeld [Salfeld2026] introduces a zero-trust execution framework
   grounded in signed execution receipts with DSSE and Ed25519,
   demonstrating the pattern on a proof-of-concept infrastructure (zta-
   hub).  He and Yu [He2026SEB] propose a Sovereign Execution Broker
   that interposes on tool calls with per-action attestation in cloud
   environments.  He and Yu [He2026SAB] extend this to a Sovereign
   Assurance Boundary covering multi-tenant and Kubernetes deployments.
   Uchibeke [Uchibeke2026] examines pre-execution attestation and the
   case for binding authorization evidence before a tool call is
   dispatched.

Sirkkavaara               Expires 14 April 2027                [Page 41]
Internet-Draft                Vaara Receipt                 October 2026

   All four adopt per-action signed records with content-addressed
   evidence.  This document adds a held-set completeness mechanism
   (Section 6.4) and publishes conformance vectors with checkers that
   import no issuer code.

   A parallel line of work in the IETF community addresses signed
   receipts for agent actions taken over the Model Context Protocol
   (MCP).  [ACTA-RECEIPTS] defines a base signed-receipt format for
   machine-to-machine access-control decisions, canonicalized with JCS
   ([RFC8785]) and verified against an issuer key resolved out of band;
   it records a decision after it is made.  [ASQAV-COMPLIANCE] layers a
   regulatory compliance profile on that base format, mapping fields to
   obligations under the EU AI Act and DORA and tightening optional
   fields to required ones for audit use.  [AGENTROA] places an
   enforcement proxy outside the agent process that authorizes an action
   before it runs, binds the MCP tool call by a hash of its canonical
   arguments, and can register the authorization with a SCITT
   transparency service ([RFC9943]).  [VCP] profiles the same SCITT
   substrate for audit trails in algorithmic trading, a different
   domain.

   [AGENT-ACTION-RECEIPTS] specifies a newline-delimited log of per-
   action receipts, and uses one construction this document does not.
   Its chain link is the SHA-256 of the previous record's transmitted
   octets, including that record's signature and any member the verifier
   does not recognize, where the linkage here and in the formats above
   digests a re-canonicalization.  Digesting the transmitted octets
   makes chain verification independent of agreement about
   canonicalization and covers extension members a re-canonicalized
   digest excludes.  Its signed byte sequence is a fixed member order
   rather than JCS, and its stated interoperability constraints exclude
   non-ASCII member names and non-integer numbers from the signed set.

   This document shares the per-action, content-addressed, recomputable
   approach of these efforts.  Three of its properties are worth naming
   next to them.  First, the held-set completeness mechanism of
   Section 6.4: a monotonic sequence with a running count and an
   optional sealing record lets a third party prove a receipt is missing
   from a set, and a sealed worst-case class lets a chain recipient gate
   its own next action on the held set alone, with no issuer access.
   Second, one profile-neutral envelope carries authorization,
   settlement, checkout, and external-execution evidence through the
   same binding (Section 6).  Third, the envelope's backLink binds a
   decision to its predecessor attestation, so a pre-execution
   authorization and its post-execution record form one recomputable
   pair rather than a single post-hoc entry; [AGENTROA] records the
   authorization decision and states that it carries no paired post-
   execution receipt.

Sirkkavaara               Expires 14 April 2027                [Page 42]
Internet-Draft                Vaara Receipt                 October 2026

   A receipt is re-expressible as a RATS Entity Attestation Result
   ([I-D.ietf-rats-ear]), and its timestamp anchors admit an eIDAS-
   qualified timestamp (Section 5) as a swappable method for legal
   weight.  This work references the formats above rather than profiling
   any of them, because the held-set completeness mechanism and the
   profile-neutral envelope are properties of the format that a field-
   level profile could not add.

   [AUDIT-ARCH] describes an architecture for auditing AI agent
   delegation and interactions.  It specifies roles, four classes of
   audit record and a set of candidate work items, and deliberately no
   wire format; its illustrative field names are stated to be
   placeholders.  The envelope specified here is a candidate for its
   Action Record class: it is produced at the boundary where an action
   took effect, it carries a stable reference to the evidence a decision
   was derived from (Section 4), and it is re-expressible as a RATS
   Entity Attestation Result.  This document defines no equivalent of
   that architecture's Authorization Transition record, which carries a
   change in permission state and is replayable to reconstruct the
   authorization in force at an instant.  The envelope's backLink binds
   a decision to its predecessor attestation, while the architecture's
   correlation identifier ties a record to the interaction that
   motivated it.  Those are different edges, so a deployment using both
   would carry both.

14.  IANA Considerations

   This document has no IANA actions.  The timestamp anchor method
   registry (Section 5) and the profile registry (Section 6.1) are
   maintained by the specification, not by IANA, in this version.

15.  Normative References

   [FIPS180-4]
              National Institute of Standards and Technology, "Secure
              Hash Standard (SHS)", FIPS PUB 180-4, August 2015,
              <https://nvlpubs.nist.gov/nistpubs/FIPS/
              NIST.FIPS.180-4.pdf>.

   [FIPS204]  National Institute of Standards and Technology, "Module-
              Lattice-Based Digital Signature Standard", FIPS PUB 204,
              August 2024, <https://nvlpubs.nist.gov/nistpubs/FIPS/
              NIST.FIPS.204.pdf>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/info/rfc2119>.

Sirkkavaara               Expires 14 April 2027                [Page 43]
Internet-Draft                Vaara Receipt                 October 2026

   [RFC3161]  Adams, C., Cain, P., Pinkas, D., and R. Zuccherato,
              "Internet X.509 Public Key Infrastructure Time-Stamp
              Protocol (TSP)", RFC 3161, DOI 10.17487/RFC3161, August
              2001, <https://www.rfc-editor.org/info/rfc3161>.

   [RFC3339]  Klyne, G. and C. Newman, "Date and Time on the Internet:
              Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
              <https://www.rfc-editor.org/info/rfc3339>.

   [RFC6962]  Laurie, B., Langley, A., and E. Kasper, "Certificate
              Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
              <https://www.rfc-editor.org/info/rfc6962>.

   [RFC7518]  Jones, M., "JSON Web Algorithms (JWA)", RFC 7518,
              DOI 10.17487/RFC7518, May 2015,
              <https://www.rfc-editor.org/info/rfc7518>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/info/rfc8174>.

   [RFC8610]  Birkholz, H., Vigano, C., and C. Bormann, "Concise Data
              Definition Language (CDDL): A Notational Convention to
              Express Concise Binary Object Representation (CBOR) and
              JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
              June 2019, <https://www.rfc-editor.org/info/rfc8610>.

   [RFC8785]  Rundgren, A., Jordan, B., and S. Erdtman, "JSON
              Canonicalization Scheme (JCS)", RFC 8785,
              DOI 10.17487/RFC8785, June 2020,
              <https://www.rfc-editor.org/info/rfc8785>.

16.  Informative References

   [ACTA-RECEIPTS]
              Farley, T., "Signed Decision Receipts for Machine-to-
              Machine Access Control", Work in Progress, Internet-Draft,
              draft-farley-acta-signed-receipts, June 2026,
              <https://datatracker.ietf.org/doc/draft-farley-acta-
              signed-receipts/>.

   [AGENT-ACTION-RECEIPTS]
              Sahu, N., "Signed, Hash-Chained Action Receipts for AI
              Agents", Work in Progress, Internet-Draft, draft-sahu-
              agent-action-receipts, August 2026,
              <https://datatracker.ietf.org/doc/draft-sahu-agent-action-
              receipts/>.

Sirkkavaara               Expires 14 April 2027                [Page 44]
Internet-Draft                Vaara Receipt                 October 2026

   [AGENTROA] Michalak, J., "Agent Route Origin Authorization
              (AgentROA): A Cryptographic Policy Enforcement Framework
              for AI Agent Actions", Work in Progress, Internet-Draft,
              draft-nivalto-agentroa-route-authorization, April 2026,
              <https://datatracker.ietf.org/doc/draft-nivalto-agentroa-
              route-authorization/>.

   [AIACT]    European Parliament and Council, "Regulation (EU)
              2024/1689 laying down harmonised rules on artificial
              intelligence (Artificial Intelligence Act)", June 2024,
              <https://eur-lex.europa.eu/eli/reg/2024/1689/oj>.

   [AISVS2026]
              OWASP Foundation, "OWASP AI Security Verification Standard
              (AISVS) 1.0, Chapter 9: Orchestration and Agentic Action",
              June 2026, <https://github.com/OWASP/AISVS/blob/main/1.0/
              en/0x10-C09-Orchestration-and-Agentic-Action.md>.

   [AMD-SNP-ABI]
              Advanced Micro Devices, "SEV Secure Nested Paging Firmware
              ABI Specification", AMD Publication 56860, Revision 1.58,
              May 2025, <https://docs.amd.com/v/u/en-US/56860>.

   [AMD-VCEK] Advanced Micro Devices, "Versioned Chip Endorsement Key
              (VCEK) Certificate and KDS Interface Specification", AMD
              Publication 57230, <https://docs.amd.com/v/u/en-US/57230>.

   [ASQAV-COMPLIANCE]
              Marques, J., "Compliance Profile of Signed Action Receipts
              for AI Agents", Work in Progress, Internet-Draft, draft-
              marques-asqav-compliance-receipts, July 2026,
              <https://datatracker.ietf.org/doc/draft-marques-asqav-
              compliance-receipts/>.

   [AUDIT-ARCH]
              Kuehlewind, M. and H. Birkholz, "An Architecture for
              Auditing AI Agent Delegation and Interactions", Work in
              Progress, Internet-Draft, draft-kuehlewind-audit-
              architecture, May 2026, <https://datatracker.ietf.org/doc/
              draft-kuehlewind-audit-architecture/>.

   [DORA-RTS] European Commission, "Commission Delegated Regulation (EU)
              2024/1774 supplementing Regulation (EU) 2022/2554 with
              regard to regulatory technical standards specifying ICT
              risk management tools, methods, processes, and policies",
              March 2024,
              <https://eur-lex.europa.eu/eli/reg_del/2024/1774/oj>.

Sirkkavaara               Expires 14 April 2027                [Page 45]
Internet-Draft                Vaara Receipt                 October 2026

   [eIDAS]    European Parliament and Council, "Regulation (EU) No
              910/2014 on electronic identification and trust services
              for electronic transactions in the internal market
              (eIDAS)", July 2014, <https://eur-lex.europa.eu/legal-
              content/EN/TXT/?uri=CELEX:32014R0910>.

   [GDPR]     European Parliament and Council, "Regulation (EU) 2016/679
              on the protection of natural persons with regard to the
              processing of personal data (General Data Protection
              Regulation)", April 2016,
              <https://eur-lex.europa.eu/eli/reg/2016/679/oj>.

   [He2026SAB]
              He, J., "Sovereign Assurance Boundary: Certificate-Bound
              Admission for Agentic Infrastructure", arXiv 2606.11632,
              June 2026, <https://arxiv.org/abs/2606.11632>.

   [He2026SEB]
              He, J., "Sovereign Execution Broker: Enforcing
              Certificate-Bound Authority in Agentic Control Planes",
              arXiv 2606.20520, June 2026,
              <https://arxiv.org/abs/2606.20520>.

   [I-D.ietf-rats-ear]
              Fossati, T. and S. Frost, "Attestation Results for Secure
              Interactions", Work in Progress, Internet-Draft, draft-
              ietf-rats-ear, 2026,
              <https://datatracker.ietf.org/doc/draft-ietf-rats-ear/>.

   [I-D.ietf-scitt-scrapi]
              Birkholz, H., Geater, J., and A. Delignat-Lavaud, "Supply
              Chain Integrity, Transparency, and Trust (SCITT) Reference
              APIs", Work in Progress, Internet-Draft, draft-ietf-scitt-
              scrapi-11, 26 June 2026,
              <https://datatracker.ietf.org/doc/draft-ietf-scitt-
              scrapi/>.

   [ISO42001] ISO/IEC, "ISO/IEC 42001:2023, Information technology,
              Artificial intelligence, Management system", December
              2023, <https://www.iso.org/standard/42001>.

   [PLD]      European Parliament and Council, "Directive (EU) 2024/2853
              on liability for defective products", October 2024,
              <https://eur-lex.europa.eu/eli/dir/2024/2853/oj>.

Sirkkavaara               Expires 14 April 2027                [Page 46]
Internet-Draft                Vaara Receipt                 October 2026

   [RFC7942]  Sheffer, Y. and A. Farrel, "Improving Awareness of Running
              Code: The Implementation Status Section", BCP 205,
              RFC 7942, DOI 10.17487/RFC7942, July 2016,
              <https://www.rfc-editor.org/info/rfc7942>.

   [RFC8792]  Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
              "Handling Long Lines in Content of Internet-Drafts and
              RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
              <https://www.rfc-editor.org/info/rfc8792>.

   [RFC9162]  Laurie, B., Messeri, E., and R. Stradling, "Certificate
              Transparency Version 2.0", RFC 9162, DOI 10.17487/RFC9162,
              December 2021, <https://www.rfc-editor.org/info/rfc9162>.

   [RFC9334]  Birkholz, H., Thaler, D., Richardson, M., Smith, N., and
              W. Pan, "Remote ATtestation procedureS (RATS)
              Architecture", RFC 9334, DOI 10.17487/RFC9334, January
              2023, <https://www.rfc-editor.org/info/rfc9334>.

   [RFC9943]  Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande,
              Y., and S. Lasker, "An Architecture for Trustworthy and
              Transparent Digital Supply Chains", RFC 9943,
              DOI 10.17487/RFC9943, June 2026,
              <https://www.rfc-editor.org/info/rfc9943>.

   [Salfeld2026]
              Salfeld-Nebgen, J., "Governing Actions, Not Agents:
              Institutional Attestation as a Governance Model for
              Autonomous AI Systems", arXiv 2606.26298, June 2026,
              <https://arxiv.org/abs/2606.26298>.

   [Uchibeke2026]
              Uchibeke, U., "Before the Tool Call: Deterministic Pre-
              Action Authorization for Autonomous AI Agents",
              arXiv 2603.20953, March 2026,
              <https://arxiv.org/abs/2603.20953>.

   [VAARA-REPO]
              Vaara, "Vaara Receipt Specification (vaara.receipt/v1) and
              conformance vectors", 2026,
              <https://github.com/vaaraio/vaara/
              tree/35e3d6c5ae21f322a230e63c4f104adb3d3b0494>.

   [VCP]      Kamimura, T., "A SCITT Profile for Verifiable Audit Trails
              in Algorithmic Trading: The VeritasChain Protocol (VCP)",
              Work in Progress, Internet-Draft, draft-kamimura-scitt-
              vcp, January 2026, <https://datatracker.ietf.org/doc/
              draft-kamimura-scitt-vcp/>.

Sirkkavaara               Expires 14 April 2027                [Page 47]
Internet-Draft                Vaara Receipt                 October 2026

Appendix A.  Envelope Schema (CDDL)

   This appendix is normative.  It describes the JSON encoding of a
   receipt (Section 3) in CDDL.  Maps are closed: a member not named
   here is not allowed, which is the rule of Section 3.  A reference
   implementation validates every positive receipt in its published
   conformance vectors against this schema.

   <CODE BEGINS>
   ; vaara.receipt/v1 envelope, JSON encoding.
   ; Maps are closed: a member not named here is not allowed.
   ; Rules CDDL cannot state are in the prose: runningCount is
   ; seq + 1, the issuer block alg equals the envelope alg, and
   ; the classical part of sigSuite equals alg.

   receipt = decision-receipt / execution-receipt

   decision-receipt = {
     version: 1,
     alg: alg,
     backLink: back-link,
     decisionDerived: decision-derived,
     issuerAsserted: decision-issuer-block,
     signature: hex,
     ? timestampAnchors: [* anchor],
   }

   execution-receipt = {
     version: 1,
     alg: alg,
     backLink: back-link,
     outcomeDerived: outcome-derived,
     receiptAsserted: issuer-block,
     signature: hex,
     ? pqSignature: pq-signature,
     ? existenceProof: existence-proof,
   }

   alg = "ES256" / "RS256" / "HS256"
   hex = tstr .regexp "[0-9a-f]+"
   digest = tstr .regexp "sha256:[0-9a-f]{64}"
   nonempty = tstr .regexp ".+"
   date-time = tstr .regexp "[0-9-]{10}T[0-9:]{8}([.][0-9]+)?Z"
   decimal = tstr .regexp "-?[0-9]+([.][0-9]+)?"

   back-link = {
     attestationDigest: digest,
     attestationNonce: nonempty,

Sirkkavaara               Expires 14 April 2027                [Page 48]
Internet-Draft                Vaara Receipt                 October 2026

     ? fallbackProjection: nonempty,
   }

   issuer-block = {
     issuer-members,
     ? sigSuite: "ES256+ML-DSA-65" / "RS256+ML-DSA-65",
   }

   ; A decision receipt has no pqSignature, so its issuer block
   ; names no sigSuite (SPEC.md 2.5).
   decision-issuer-block = {
     issuer-members,
   }

   issuer-members = (
     iss: tstr,
     sub: tstr,
     iat: date-time,
     nonce: tstr,
     alg: alg,
     secretVersion: tstr,
     ? aud: nonempty,
     ? taskId: nonempty,
     ? completeness: completeness,
     ? cryptoPosture: crypto-posture,
   )

   completeness = {
     boundaryId: nonempty,
     seq: uint,
     runningCount: uint,
   }

   crypto-posture = {
     assetType: "algorithm",
     nistQuantumSecurityLevel: 0..5,
     algorithms: [+ crypto-algorithm],
   }

   crypto-algorithm = {
     algorithm: nonempty,
     primitive: nonempty,
     nistQuantumSecurityLevel: 0..5,
   }

   decision-derived = {
     decision: "allow" / "block" / "escalate",
     decidedAt: date-time,

Sirkkavaara               Expires 14 April 2027                [Page 49]
Internet-Draft                Vaara Receipt                 October 2026

     ? reason: tstr,
     ? policyId: tstr,
     ? riskScore: decimal,
     ? thresholdAllow: decimal,
     ? thresholdBlock: decimal,
     ? clientTurnId: tstr,
     ? evidenceRef: evidence-ref,
     ? rationale: rationale,
     ? binding: binding,
     ? decisionProof: { * tstr => any },
   }

   evidence-ref = {
     canonicalization: "jcs-rfc8785" / "JCS" / "jcs-json-v1",
     digest: digest,
     schema: nonempty,
     ? ref: nonempty,
   }

   rationale = {
     rule: tstr,
     reason: tstr,
     declaredIntent: tstr,
     ? intentSatisfied: bool,
   }

   binding = {
     policyDigest: digest,
     intentDigest: digest,
     inputsDigest: digest,
     bindingDigest: digest,
   }

   outcome-derived = {
     status: "executed" / "refused" / "errored",
     completedAt: date-time,
     ? resultCommitment: projection-commitment / reference-commitment,
     ? decisionDigest: digest,
   }

   projection-commitment = {
     projection: tstr,
     projectionDigest: digest,
   }

   reference-commitment = {
     ref: tstr,
     digest: digest,

Sirkkavaara               Expires 14 April 2027                [Page 50]
Internet-Draft                Vaara Receipt                 October 2026

     canonicalization: "jcs",
   }

   pq-signature = {
     alg: "ML-DSA-65",
     keyid: nonempty,
     sig: hex,
   }

   existence-proof = {
     backend: "rfc3161-eidas-qualified",
     hashAlgorithm: "sha256",
     recordDigest: digest,
     token: nonempty,
   }

   anchor = rfc3161-anchor / blinded-anchor / log-anchor / other-anchor

   rfc3161-anchor = {
     method: "rfc3161" / "rfc3161-eidas-qualified",
     anchoredDigest: digest,
     token: nonempty,
     ? authority: tstr,
   }

   blinded-anchor = {
     method: "rfc3161-blinded" / "rfc3161-eidas-qualified-blinded",
     anchoredDigest: digest,
     token: nonempty,
     anchorSalt: tstr .regexp "[0-9a-f]{64}",
     ? authority: tstr,
   }

   log-anchor = {
     method: "scitt",
     anchoredDigest: digest,
     logId: nonempty,
     leafIndex: uint,
     treeSize: uint,
     inclusionProof: [* tstr],
     rootHash: nonempty,
     ? authority: tstr,
   }

   ; A method this document does not define: carried, never
   ; treated as verified. CDDL cannot say "any method name but
   ; the three above", so this alternative also admits a
   ; registered name with members missing; the prose rule that

Sirkkavaara               Expires 14 April 2027                [Page 51]
Internet-Draft                Vaara Receipt                 October 2026

   ; a registered method keeps its own shape is checked by the
   ; verifier, not by this schema.
   other-anchor = {
     method: tstr,
     anchoredDigest: digest,
     * tstr => any,
   }
   <CODE ENDS>

Appendix B.  Cage Drivers and Bases in Use

   This appendix is informative.  It lists the driver and basis values a
   reference implementation emits at the time of writing.  No value here
   is normative, and either list can grow without a revision of this
   document.

Sirkkavaara               Expires 14 April 2027                [Page 52]
Internet-Draft                Vaara Receipt                 October 2026

    +=================+==========================+====================+
    | driver          | What it starts the agent | basis when         |
    |                 | in                       | confirmed          |
    +=================+==========================+====================+
    | vaara-cage      | An AppArmor profile with | apparmor_label     |
    |                 | a cgroup and a file      |                    |
    |                 | access guard             |                    |
    +-----------------+--------------------------+--------------------+
    | openshell       | NVIDIA OpenShell         | seccomp_filter     |
    +-----------------+--------------------------+--------------------+
    | codex           | The OpenAI Codex sandbox | seccomp_filter     |
    |                 | (bubblewrap, Landlock    |                    |
    |                 | and seccomp on Linux)    |                    |
    +-----------------+--------------------------+--------------------+
    | sandbox-runtime | Anthropic sandbox-       | bwrap_init         |
    |                 | runtime (bubblewrap on   |                    |
    |                 | Linux)                   |                    |
    +-----------------+--------------------------+--------------------+
    | nono            | nono (Landlock with a    | seccomp_filter,    |
    |                 | seccomp baseline)        | no_new_privs       |
    +-----------------+--------------------------+--------------------+
    | gvisor          | gVisor (a user-space     | gvisor_kernel_log  |
    |                 | kernel)                  |                    |
    +-----------------+--------------------------+--------------------+
    | agent-sandbox   | Kubernetes SIG agent-    | gvisor_kernel_log, |
    |                 | sandbox (gVisor or Kata) | hypervisor_present |
    +-----------------+--------------------------+--------------------+
    | kata            | Kata Containers (one     | hypervisor_present |
    |                 | lightweight VM per       |                    |
    |                 | container)               |                    |
    +-----------------+--------------------------+--------------------+
    | firecracker     | Firecracker (a microVM)  | hypervisor_present |
    +-----------------+--------------------------+--------------------+
    | microsandbox    | microsandbox (libkrun    | hypervisor_present |
    |                 | microVM)                 |                    |
    +-----------------+--------------------------+--------------------+
    | e2b             | E2B, self-hosted         | hypervisor_present |
    |                 | (Firecracker microVM)    |                    |
    +-----------------+--------------------------+--------------------+
    | apple-container | Apple container (one     | hypervisor_present |
    |                 | lightweight VM per       |                    |
    |                 | container)               |                    |
    +-----------------+--------------------------+--------------------+

         Table 11: Driver values and the basis each can confirm on

Sirkkavaara               Expires 14 April 2027                [Page 53]
Internet-Draft                Vaara Receipt                 October 2026

    +====================+============================================+
    | basis              | The fact that was read                     |
    +====================+============================================+
    | none               | Nothing; no cage was declared.             |
    +--------------------+--------------------------------------------+
    | declared           | Nothing beyond the launcher's declaration. |
    +--------------------+--------------------------------------------+
    | apparmor_label     | The process carries the cage's AppArmor    |
    |                    | label.                                     |
    +--------------------+--------------------------------------------+
    | seccomp_filter     | A seccomp filter is attached and           |
    |                    | no_new_privs is set.                       |
    +--------------------+--------------------------------------------+
    | no_new_privs       | no_new_privs is set, which Landlock        |
    |                    | requires.                                  |
    +--------------------+--------------------------------------------+
    | bwrap_init         | Process 1 of the process's PID namespace   |
    |                    | is bubblewrap.                             |
    +--------------------+--------------------------------------------+
    | gvisor_kernel_log  | The kernel log is the one gVisor writes.   |
    +--------------------+--------------------------------------------+
    | hypervisor_present | The CPU reports a hypervisor underneath.   |
    +--------------------+--------------------------------------------+

                           Table 12: Basis values

Author's Address

   Henri Sirkkavaara
   Vaara
   Email: hello@vaara.io
   URI:   https://github.com/vaaraio/vaara

Sirkkavaara               Expires 14 April 2027                [Page 54]