<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="info"
     docName="draft-dobson-ai-decision-receipt-00"
     ipr="trust200902"
     submissionType="IETF"
     consensus="false"
     tocInclude="true"
     sortRefs="true"
     symRefs="true"
     version="3"
     xml:lang="en">

  <front>
    <title abbrev="AI-Decision-Receipt">The AI-Decision-Receipt HTTP Response Header Field</title>
    <seriesInfo name="Internet-Draft" value="draft-dobson-ai-decision-receipt-00"/>

    <author fullname="Justin Antony Dobson" initials="J. A." surname="Dobson">
      <organization>Monop Content</organization>
      <address>
        <postal>
          <country>United Kingdom</country>
        </postal>
        <email>justrightdecorators@gmail.com</email>
        <uri>https://sebbi.pro</uri>
      </address>
    </author>

    <date year="2026" month="October" day="26"/>

    <area>Applications and Real-Time</area>
    <workgroup>Individual Submission</workgroup>

    <keyword>AI</keyword>
    <keyword>agents</keyword>
    <keyword>accountability</keyword>
    <keyword>receipt</keyword>
    <keyword>audit</keyword>
    <keyword>structured fields</keyword>

    <abstract>
      <t>
        Automated systems, including AI models and AI agents, increasingly
        make decisions and take actions that affect people, money and data.
        Emerging work on agent identity answers which agent made a request
        and whether it was authorised. It does not give the parties involved
        a portable, independently checkable record of what was decided.
      </t>
      <t>
        This document defines AI-Decision-Receipt, an HTTP response header
        field that carries a compact receipt for a governed automated
        decision: the outcome, a fingerprint of the exact request the
        decision was made on, the position and hash of the record in the
        issuer's tamper-evident log, and a location where anyone can verify
        that record without trusting the issuer. The field uses the
        Structured Field Values for HTTP Dictionary type.
      </t>
    </abstract>
  </front>

  <middle>

    <section anchor="intro">
      <name>Introduction</name>
      <t>
        When an automated system decides something - to allow a payment, to
        refuse an application, to let an agent call a tool - the parties
        affected usually receive no durable evidence of that decision. Logs,
        where they exist, are held by the operator of the system and can be
        edited by that operator. A later dispute between a customer, a
        regulator, an insurer and the operator then depends on whose account
        is believed.
      </t>
      <t>
        Several efforts address the identity of automated clients: HTTP
        Message Signatures <xref target="RFC9421"/> profiles that let a
        website verify which bot or agent sent a request, and OAuth-based
        delegation that records which person or organisation authorised an
        agent. Identity answers "who acted" and "were they allowed to". It
        does not answer "what exactly was decided, on exactly what input,
        and can that be shown later to someone who trusts none of the
        parties".
      </t>
      <t>
        This document defines a small, transport-level receipt for that
        second question. A system that governs or records an automated
        decision (the issuer) returns the AI-Decision-Receipt header field
        with its HTTP response. The receipt binds:
      </t>
      <ul>
        <li>the decision outcome;</li>
        <li>a SHA-256 <xref target="FIPS180-4"/> fingerprint of the exact request body the decision was made on;</li>
        <li>the position and hash of the sealed record of that decision in the issuer's append-only, tamper-evident log; and</li>
        <li>a URI at which the record and its proofs can be checked without credentials.</li>
      </ul>
      <t>
        The receipt is deliberately small and is not itself proof. It is a
        pointer that lets any party fetch the proof and check it with their
        own tools. The design follows the same principle as Certificate
        Transparency <xref target="RFC6962"/>: the issuer commits to a
        record in a log that anyone can audit, so a later change to that
        record cannot be hidden.
      </t>

      <section anchor="requirements">
        <name>Requirements Language</name>
        <t>
          The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
          "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>",
          "<bcp14>SHALL NOT</bcp14>", "<bcp14>SHOULD</bcp14>",
          "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>",
          "<bcp14>NOT RECOMMENDED</bcp14>", "<bcp14>MAY</bcp14>", and
          "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
          described in BCP&nbsp;14 <xref target="RFC2119"/>
          <xref target="RFC8174"/> when, and only when, they appear in all
          capitals, as shown here.
        </t>
      </section>
    </section>

    <section anchor="terms">
      <name>Terminology</name>
      <dl newline="false">
        <dt>Decision:</dt>
        <dd>An outcome produced by an automated system about a request, for
        example to allow, hold for human review, or refuse an action.</dd>
        <dt>Issuer:</dt>
        <dd>The party that records the decision and emits the receipt. The
        issuer may be the system that made the decision, or a governance
        layer (for example a gateway) that sits in front of it.</dd>
        <dt>Log:</dt>
        <dd>The issuer's append-only sequence of sealed records, in which
        each record's hash commits to the hash of the record before it, so
        that altering, inserting or removing any record changes every later
        hash.</dd>
        <dt>Seal:</dt>
        <dd>The hash that identifies one record in the log.</dd>
        <dt>Relying party:</dt>
        <dd>Anyone who receives a receipt and wishes to check it: the client,
        the person affected by the decision, an auditor, a regulator, an
        insurer or a court.</dd>
      </dl>
    </section>

    <section anchor="field">
      <name>The AI-Decision-Receipt Header Field</name>
      <t>
        AI-Decision-Receipt is a Dictionary Structured Field
        (<xref target="RFC9651" sectionFormat="of" section="3.2"/>). It is a
        response header field. It <bcp14>MUST NOT</bcp14> be sent as a
        trailer field, because a relying party needs it to be bound to the
        response it accompanies. Its members are defined below.
      </t>

      <section anchor="members">
        <name>Members</name>
        <dl>
          <dt>v</dt>
          <dd>An Integer giving the version of this format. This document
          defines version 1. <bcp14>REQUIRED</bcp14>.</dd>

          <dt>issuer</dt>
          <dd>A String containing the host name of the issuer, for example
          "sebbi.pro". Relying parties use it to decide whether they recognise
          the issuer and to check that the verify URI belongs to it.
          <bcp14>REQUIRED</bcp14>.</dd>

          <dt>decision</dt>
          <dd>A Token giving the outcome. This document defines three values:
          ALLOW (the action may proceed), CHALLENGE (the action requires
          review by a person before it proceeds) and BLOCK (the action must
          not proceed). Issuers <bcp14>MAY</bcp14> define further values;
          such values <bcp14>MUST</bcp14> consist of upper-case letters and
          "_" only. A relying party that does not recognise a value
          <bcp14>MUST</bcp14> treat it as CHALLENGE. <bcp14>REQUIRED</bcp14>.</dd>

          <dt>score</dt>
          <dd>A Decimal between 0 and 1 giving the issuer's risk score for the
          decision, where higher means riskier. A receiver
          <bcp14>MUST</bcp14> also accept an Integer (0 or 1). The meaning of
          intermediate values is defined by the issuer. <bcp14>OPTIONAL</bcp14>.</dd>

          <dt>block</dt>
          <dd>An Integer giving the position of the sealed record in the
          issuer's log. <bcp14>REQUIRED</bcp14> when the decision was
          sealed.</dd>

          <dt>seal</dt>
          <dd>A String containing the lower-case hexadecimal SHA-256 hash that
          identifies the sealed record in the log. <bcp14>REQUIRED</bcp14>
          when block is present.</dd>

          <dt>req</dt>
          <dd>A String containing the lower-case hexadecimal SHA-256 hash of
          the exact request body on which the decision was made, as the issuer
          received it. <bcp14>RECOMMENDED</bcp14>.</dd>

          <dt>call</dt>
          <dd>A String containing the issuer's identifier for this request,
          for correlation in support and dispute processes.
          <bcp14>OPTIONAL</bcp14>.</dd>

          <dt>agent</dt>
          <dd>A String identifying the authenticated automated client on
          whose request the decision was made, when the issuer authenticated
          it - for example the key identifier of a verified HTTP Message
          Signature <xref target="RFC9421"/>. See <xref target="identity"/>.
          <bcp14>OPTIONAL</bcp14>.</dd>

          <dt>verify</dt>
          <dd>A String containing an absolute "https" URI
          <xref target="RFC3986"/> at which the sealed record and the proofs
          described in <xref target="issuer"/> can be retrieved.
          <bcp14>REQUIRED</bcp14> when block is present.</dd>
        </dl>
        <t>
          Receivers <bcp14>MUST</bcp14> ignore members they do not recognise,
          so that later versions can add members without breaking existing
          receivers. Parameters on members are not defined by this document
          and <bcp14>MUST</bcp14> be ignored.
        </t>
      </section>

      <section anchor="example">
        <name>Example</name>
        <t>A response from an issuer that sealed an ALLOW decision
        (line breaks added and hash values shortened for readability; real
        seal and req values are 64 hexadecimal characters):</t>
        <sourcecode type="http-message"><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json
AI-Decision-Receipt: v=1, issuer="sebbi.pro", decision=ALLOW,
  score=0.12, block=1042,
  seal="9f2c4be0c6a1...f5a4b3c2d",
  req="5d41402abc4b...3c2b1a0f9e",
  call="GC-7Q2M9X4KDP",
  verify="https://sebbi.pro/forever?block=1042"
Access-Control-Expose-Headers: AI-Decision-Receipt
]]></sourcecode>
      </section>

      <section anchor="browsers">
        <name>Use from Web Browsers</name>
        <t>
          Issuers that serve cross-origin requests <bcp14>SHOULD</bcp14>
          include AI-Decision-Receipt in Access-Control-Expose-Headers, so that
          web applications can read the receipt.
        </t>
      </section>
    </section>

    <section anchor="issuer">
      <name>Issuer Requirements</name>
      <t>An issuer that emits a receipt containing block, seal and verify:</t>
      <ol>
        <li><bcp14>MUST</bcp14> have appended the sealed record to its log
        before sending the response that carries the receipt.</li>
        <li><bcp14>MUST</bcp14> maintain the log so that each record's hash
        commits to the hash of the record before it, and <bcp14>MUST
        NOT</bcp14> alter or remove a record once sealed.</li>
        <li><bcp14>MUST</bcp14> make the record and its proofs available at
        the verify URI to any party, without authentication, for as long as
        it emits receipts that refer to it. Where the record contains
        personal or confidential data, the issuer <bcp14>MAY</bcp14> serve
        only the hashes needed for verification (see
        <xref target="privacy"/>).</li>
        <li><bcp14>SHOULD</bcp14> regularly commit the latest hash of its
        log to at least one system it does not control, such that the
        commitment cannot later be changed by the issuer - for example a
        public timestamping service such as <xref target="OPENTIMESTAMPS"/>,
        a public blockchain, or independent witnesses that countersign the
        log. This lets a relying party establish that a record existed no
        later than a given time.</li>
        <li><bcp14>SHOULD</bcp14> publish the method used to compute record
        hashes in enough detail that a relying party can recompute them
        independently.</li>
      </ol>
    </section>

    <section anchor="verify">
      <name>Verifying a Receipt</name>
      <t>A relying party verifies a receipt as follows:</t>
      <ol>
        <li>Check that v is a version it understands and that the host of the
        verify URI matches issuer, or is otherwise recognised as acting for
        the issuer.</li>
        <li>If req is present and the relying party holds the request body,
        compute its SHA-256 hash and check that it equals req.</li>
        <li>Retrieve the record from the verify URI and check that the hash
        it carries for position block equals seal.</li>
        <li>Recompute the record's hash from its published contents using the
        issuer's published method, and check that it equals seal; and check
        that the record commits to the hash of the record before it.</li>
        <li>Where the issuer anchors its log externally, check that an anchor
        covers this record or a later one, using the anchoring system's own
        tools rather than the issuer's.</li>
      </ol>
      <t>
        A receipt that passes these checks shows that the issuer recorded the
        stated decision about the stated request, at or before the anchored
        time, and has not since changed that record without detection. It
        does not show that the decision was correct, lawful or fair; it
        makes the decision available to be examined.
      </t>
    </section>

    <section anchor="identity">
      <name>Relationship to Agent Identity</name>
      <t>
        Agent identity mechanisms and this receipt are complementary.
        Identity establishes who sent a request and under whose authority;
        the receipt establishes what was decided about it and lets anyone
        check that record later. When an issuer has authenticated the
        client - for example by verifying an HTTP Message Signature
        <xref target="RFC9421"/> - it <bcp14>SHOULD</bcp14> place the
        verified key identifier in the agent member and include it in the
        sealed record, so that the identity of the agent and the decision
        about its request are bound in the same tamper-evident entry.
      </t>
      <t>
        An issuer <bcp14>MUST NOT</bcp14> populate agent from unauthenticated
        information such as the User-Agent header field.
      </t>
    </section>

    <section anchor="impl">
      <name>Implementation Status</name>
      <t>
        This section records the status of known implementations of the
        protocol defined by this specification at the time of posting of
        this Internet-Draft, and is based on a proposal described in
        <xref target="RFC7942"/>. It is to be removed before publication as
        an RFC.
      </t>
      <dl>
        <dt>sebbi.pro</dt>
        <dd>
          <t>Organisation: Monop Content, United Kingdom.</t>
          <t>Description: emits AI-Decision-Receipt version 1 on every
          response from its AI gateway (which sits in front of OpenAI and
          Anthropic model APIs) and on every response from its decision API.
          Records are sealed in a SHA-256 hash chain that is anchored hourly
          in Bitcoin through OpenTimestamps and observed by independent
          witness chains. Records can be checked in a web browser or with a
          standalone script that makes no network calls to the issuer.</t>
          <t>Specification and checker:
          https://sebbi.pro/standard/ai-decision-receipt</t>
          <t>Level of maturity: in production.</t>
          <t>Coverage: all members defined in this document except agent.</t>
          <t>Contact: the author of this document.</t>
        </dd>
      </dl>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t>
        A receipt is an assertion by the issuer until it has been verified as
        described in <xref target="verify"/>. Relying parties
        <bcp14>MUST NOT</bcp14> treat the presence of the field as evidence
        that a decision was recorded.
      </t>
      <t>
        The header field is not itself signed. An intermediary that can modify
        the response can alter or remove it. Integrity of the field in transit
        depends on the transport (for example TLS). Where a receipt must be
        attributable to the issuer independently of transport, the issuer
        <bcp14>MAY</bcp14> sign the response, including this field, with HTTP
        Message Signatures <xref target="RFC9421"/>. Regardless of signing, a
        forged receipt fails verification against the issuer's log.
      </t>
      <t>
        An issuer controls its own log. Without external anchoring or
        witnessing, an issuer could rebuild its log from an earlier point.
        The anchoring requirement in <xref target="issuer"/> exists to make
        such rewriting detectable; relying parties that need strong
        assurance <bcp14>SHOULD</bcp14> check anchors themselves.
      </t>
      <t>
        A receipt can be replayed alongside a different response. Relying
        parties <bcp14>SHOULD</bcp14> use req, and where present call and
        agent, to check that a receipt belongs to the exchange it accompanies.
      </t>
      <t>
        Verify URIs are retrieved by relying parties. Relying parties
        <bcp14>SHOULD</bcp14> only follow verify URIs whose host matches the
        issuer or is otherwise trusted for that issuer, to avoid being
        directed to arbitrary hosts.
      </t>
    </section>

    <section anchor="privacy">
      <name>Privacy Considerations</name>
      <t>
        The req member is a hash, not the request itself. A hash of a short or
        predictable request body can be reversed by guessing. Issuers
        <bcp14>SHOULD NOT</bcp14> publish request bodies at the verify URI,
        and <bcp14>SHOULD</bcp14> consider whether published hashes of
        low-entropy requests could reveal personal data; where they could,
        the issuer <bcp14>MAY</bcp14> include a secret random value, returned
        only to the client, in the hashed material.
      </t>
      <t>
        The verify URI is public. Records published there
        <bcp14>MUST NOT</bcp14> contain personal data unless the issuer has a
        lawful basis to publish it; publishing only hashes is sufficient for
        verification.
      </t>
      <t>
        The agent member can link requests made by the same agent. Issuers
        <bcp14>SHOULD</bcp14> include it only when the client has
        authenticated as that agent.
      </t>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>
        IANA is requested to register the following entry in the "Hypertext
        Transfer Protocol (HTTP) Field Name Registry" defined in
        <xref target="RFC9110" sectionFormat="of" section="16.3.1"/>:
      </t>
      <dl newline="false">
        <dt>Field Name:</dt>
        <dd>AI-Decision-Receipt</dd>
        <dt>Status:</dt>
        <dd>provisional</dd>
        <dt>Structured Type:</dt>
        <dd>Dictionary</dd>
        <dt>Reference:</dt>
        <dd>This document</dd>
        <dt>Comments:</dt>
        <dd>none</dd>
      </dl>
    </section>

  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3986.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9110.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9651.xml"/>
        <reference anchor="FIPS180-4" target="https://doi.org/10.6028/NIST.FIPS.180-4">
          <front>
            <title>Secure Hash Standard (SHS)</title>
            <author>
              <organization>National Institute of Standards and Technology</organization>
            </author>
            <date year="2015" month="August"/>
          </front>
          <seriesInfo name="FIPS PUB" value="180-4"/>
          <seriesInfo name="DOI" value="10.6028/NIST.FIPS.180-4"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6962.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7942.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9421.xml"/>
        <reference anchor="OPENTIMESTAMPS" target="https://opentimestamps.org/">
          <front>
            <title>OpenTimestamps: Scalable, Trust-Minimized, Distributed Timestamping with Bitcoin</title>
            <author>
              <organization>OpenTimestamps</organization>
            </author>
            <date/>
          </front>
        </reference>
      </references>
    </references>

    <section anchor="ack" numbered="false">
      <name>Acknowledgements</name>
      <t>
        The design draws on the transparency-log approach of Certificate
        Transparency and on the Structured Field Values work of the HTTP
        Working Group.
      </t>
    </section>
  </back>
</rfc>
