<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="std"
     docName="draft-flores-aidp-provenance-00"
     ipr="trust200902"
     submissionType="IETF"
     consensus="true"
     obsoletes=""
     updates=""
     xml:lang="en"
     tocInclude="true"
     tocDepth="3"
     symRefs="true"
     sortRefs="true"
     version="3">

  <front>
    <title abbrev="AIDP Provenance Seal and Register">The AIDP Provenance Seal and Serving Register</title>
    <seriesInfo name="Internet-Draft" value="draft-flores-aidp-provenance-00"/>

    <author fullname="Justin Philip Flores" initials="J. P." surname="Flores">
      <address>
        <email>justinflores@pm.me</email>
      </address>
    </author>

    <date year="2026" month="August" day="3"/>

    <area>Security</area>
    <workgroup>Individual Submission</workgroup>

    <keyword>provenance</keyword>
    <keyword>inference</keyword>
    <keyword>attribution</keyword>
    <keyword>signature</keyword>

    <abstract>
      <t>
        A response served by an inference provider carries no verifiable statement of what
        produced it. A recipient cannot determine which model generated a given output, nor
        whether the endpoint that served it was authorized by the party whose name is on it.
        Attribution today rests on the serving party's own account of events, offered after
        the fact and at its own discretion.
      </t>
      <t>
        This document specifies two mechanisms that together make that determination
        decidable by a recipient. The Provenance Seal is a detached signature by which a
        provider binds a model identifier, its own identity, and a timestamp to the exact
        bytes of a served response. The Serving Register is a signed document listing, for
        each provider, the endpoints authorized to serve its models, the public keys that
        validate its seals, and whether the provider declares that it seals every response.
        A DNS record under the provider's own domain binds that domain to its register entry
        and to its declared sealing policy, so that a suppressed seal is detectable rather
        than merely absent.
      </t>
      <t>
        The design follows electronic mail authentication: the seal is patterned on DKIM,
        the register on SPF, and the declared sealing policy on the published policy record
        of DMARC.
      </t>
    </abstract>
  </front>

  <middle>

    <section anchor="introduction">
      <name>Introduction</name>
      <t>
        Inference responses arrive as unattributed text. A recipient holding a response has
        no mechanism for establishing which model produced it, whether the model named in
        the response metadata is the model that ran, or whether the host that answered was
        one the named provider had authorized to answer on its behalf. Every element of that
        chain is asserted by the serving party and verified by no one.
      </t>
      <t>
        The consequences are ordinary rather than exotic. A router may substitute a cheaper
        model for the one a caller selected and bill for the one selected. Weights obtained
        outside a provider's distribution may be served under that provider's name. A
        response may be altered between the serving host and the recipient. When an incident
        occurs and the parties disagree about what happened, no party holds evidence, and
        the account that prevails is the account of whoever controlled the pipeline.
      </t>
      <t>
        Electronic mail faced the structurally identical problem and solved it with three
        composable pieces: a signature binding a message to a signing domain, a published
        list of hosts authorized to send for a domain, and a published policy stating what a
        receiver should do when the first two are absent or fail. This document adapts that
        pattern.
      </t>

      <section anchor="scope">
        <name>Scope</name>
        <t>
          This document specifies the wire artifacts and the verification procedure: the
          Provenance Seal, the Serving Register, the DNS binding between them, and the
          ordered checks a verifier performs. It does not specify what a recipient does with
          a verification result. Deferring delivery, annotating output, accumulating
          findings over time, and refusing further exchange are policy behaviors outside the
          scope of this document.
        </t>
        <t>
          The mechanisms here are transport-agnostic in principle. <xref target="transport"/>
          defines a binding for HTTP, which is where inference APIs are deployed today.
        </t>
      </section>

      <section anchor="non-goals">
        <name>Non-Goals</name>
        <t>
          A valid Provenance Seal establishes that a party holding a registered private key
          asserted that a named model produced exactly these bytes at approximately this
          time. It establishes nothing else. In particular, a seal is not evidence that the
          named model actually performed the computation. A provider that signs a false
          model identifier produces a cryptographically valid seal carrying a false claim.
        </t>
        <t>
          What the seal changes is the character of that falsehood. An unsigned false claim
          is deniable; a signed one is a durable, attributable artifact held by the party
          who was deceived. This document specifies the mechanism that makes such a claim
          non-repudiable. It offers no mechanism for detecting it, and readers should not
          treat seal validity as a statement about model behavior, output quality, or
          safety.
        </t>
      </section>
    </section>

    <section anchor="conventions">
      <name>Conventions and Definitions</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>

      <dl newline="false" spacing="normal">
        <dt>Provider:</dt>
        <dd>
          The party that performs inference serving and whose identity a seal asserts. A
          provider holds one or more seal signing keys and one register entry.
        </dd>
        <dt>Verifier:</dt>
        <dd>
          The party that receives a response and evaluates its seal. Typically the client
          software acting for the end user.
        </dd>
        <dt>Serving endpoint:</dt>
        <dd>
          A network location, expressed as an absolute URI, at which a provider's models are
          served.
        </dd>
        <dt>Register entry:</dt>
        <dd>
          The record in the Serving Register describing one provider: its authorized serving
          endpoints, its seal public keys, the model identifiers it is registered to serve,
          and its declared sealing policy.
        </dd>
        <dt>Selector:</dt>
        <dd>
          A short label identifying one seal key within a register entry, permitting a
          provider to hold several keys concurrently and to rotate them independently.
        </dd>
        <dt>Registrar:</dt>
        <dd>
          The party that publishes and signs a Serving Register document.
        </dd>
      </dl>
    </section>

    <section anchor="seal">
      <name>The Provenance Seal</name>

      <section anchor="seal-fields">
        <name>Fields</name>
        <t>
          A Provenance Seal consists of the following fields. All are
          <bcp14>REQUIRED</bcp14>.
        </t>
        <dl newline="false" spacing="normal">
          <dt>register-entry:</dt>
          <dd>The identifier of the provider's register entry.</dd>
          <dt>selector:</dt>
          <dd>The selector identifying the signing key within that entry.</dd>
          <dt>model:</dt>
          <dd>The model identifier the provider asserts produced the response.</dd>
          <dt>provider:</dt>
          <dd>The provider identity as it appears in the register entry.</dd>
          <dt>signed-at:</dt>
          <dd>The time of signing, as an Internet date/time string <xref target="RFC3339"/>.</dd>
          <dt>alg:</dt>
          <dd>
            The signature algorithm. This document defines one value, <tt>ed25519</tt>,
            denoting Ed25519 as specified in <xref target="RFC8032"/>.
          </dd>
          <dt>signature:</dt>
          <dd>
            The signature over the canonical payload of <xref target="canonical"/>, encoded
            in base64url without padding <xref target="RFC4648"/>.
          </dd>
        </dl>
        <t>
          Model identity travels as signed plaintext in the <tt>model</tt> field and is
          verified by checking the signature against a public key obtained from the register
          entry. It is not derived from, encoded within, or extracted from the signature
          value itself.
        </t>
      </section>

      <section anchor="field-constraints">
        <name>Field Value Constraints</name>
        <t>
          The canonical payload of <xref target="canonical"/> is a line-oriented format in
          which header fields are separated by LF and the header block is terminated by an
          empty line. A field value containing LF or CR could therefore introduce additional
          apparent header lines within the signed region, producing bytes that two
          conforming implementations parse differently while both compute the same valid
          signature.
        </t>
        <t>
          Accordingly, the values of <tt>register-entry</tt>, <tt>selector</tt>,
          <tt>model</tt>, <tt>provider</tt>, and <tt>signed-at</tt> <bcp14>MUST NOT</bcp14>
          contain LF (0x0A) or CR (0x0D). A signer <bcp14>MUST</bcp14> reject such a value
          rather than sign it, and a verifier <bcp14>MUST</bcp14> treat a seal carrying such
          a value as invalid without evaluating its signature.
        </t>
        <t>
          The response content is exempt from this constraint. It is the final element of
          the payload and its length in bytes is bound in the header block above it, so no
          content byte sequence can be reinterpreted as a header field.
        </t>
      </section>

      <section anchor="canonical">
        <name>Canonical Payload</name>
        <t>
          The signature is computed over the following byte sequence, in which
          <tt>&lt;LF&gt;</tt> denotes a single LF octet (0x0A), field values are substituted
          verbatim, and <tt>content-length</tt> is the length of the response content in
          bytes when encoded as UTF-8:
        </t>
        <artwork type="ascii-art"><![CDATA[
aidp-seal/v1<LF>
register-entry:<register-entry><LF>
selector:<selector><LF>
model:<model><LF>
provider:<provider><LF>
signed-at:<signed-at><LF>
content-length:<content-length><LF>
<LF>
<content>
]]></artwork>
        <t>
          Field order is fixed as shown and <bcp14>MUST NOT</bcp14> vary. No whitespace
          surrounds the colon separator. There is no trailing LF after the content. The
          entire payload is encoded as UTF-8.
        </t>
        <t>
          The version token <tt>aidp-seal/v1</tt> is the first line and is inside the signed
          region, so a payload constructed under a future version cannot be validated as a
          version 1 payload.
        </t>
        <t>
          No canonicalization is performed on the content. The signature covers the served
          bytes exactly as served. A verifier <bcp14>MUST NOT</bcp14> normalize whitespace,
          line endings, or Unicode representation before verifying.
        </t>
      </section>

      <section anchor="signing">
        <name>Signing</name>
        <t>
          A provider signs the canonical payload with the private key corresponding to the
          public key published under the stated selector in its register entry. The value of
          <tt>signed-at</tt> <bcp14>MUST</bcp14> be the time at which the signature was
          computed.
        </t>
        <t>
          A provider that declares a sealing policy of <tt>all</tt>
          (<xref target="seal-policy"/>) <bcp14>MUST</bcp14> seal every response it serves.
        </t>
      </section>

      <section anchor="transport">
        <name>HTTP Transport Binding</name>
        <t>
          Over HTTP, the seal is carried in the <tt>AIDP-Seal</tt> response header field.
          Its value is the JSON object representation of the seal fields, encoded in
          base64url without padding.
        </t>
        <t>
          The JSON member names are <tt>registerEntryId</tt>, <tt>selector</tt>,
          <tt>model</tt>, <tt>providerIdentity</tt>, <tt>signedAt</tt>, <tt>alg</tt>, and
          <tt>signature</tt>, corresponding in order to the fields of
          <xref target="seal-fields"/>. Member order in the JSON representation is not
          significant; the canonical payload of <xref target="canonical"/> is what is signed,
          and it fixes its own order.
        </t>
        <t>
          The response content over which the signature is computed is the assistant text as
          served, not the enclosing JSON body. A verifier extracts that text according to
          the API in use before computing the canonical payload.
        </t>
        <t>
          A provider <bcp14>MAY</bcp14> additionally carry the same seal as a member of the
          response body. Where both are present and disagree, the header field is
          authoritative.
        </t>
      </section>
    </section>

    <section anchor="register">
      <name>The Serving Register</name>

      <section anchor="register-document">
        <name>Document Structure</name>
        <t>
          A Serving Register document is a JSON object with the following members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>aidpRegisterVersion:</dt>
          <dd>The register format version. This document defines <tt>1</tt>.</dd>
          <dt>issuedAt:</dt>
          <dd>The time of issuance, as an Internet date/time string <xref target="RFC3339"/>.</dd>
          <dt>registrar:</dt>
          <dd>An object identifying the publishing registrar.</dd>
          <dt>entries:</dt>
          <dd>An array of register entries, as specified in <xref target="register-entry"/>.</dd>
        </dl>
        <t>
          The document is accompanied by a detached signature over its exact bytes,
          computed by the registrar.
        </t>
      </section>

      <section anchor="register-entry">
        <name>Entries</name>
        <t>
          Each entry is a JSON object with the following members:
        </t>
        <dl newline="false" spacing="normal">
          <dt>id:</dt>
          <dd>
            The entry identifier, unique within the document. This is the value a seal
            carries in its <tt>register-entry</tt> field.
          </dd>
          <dt>providerIdentity:</dt>
          <dd>The provider's identity as asserted in the <tt>provider</tt> field of its seals.</dd>
          <dt>status:</dt>
          <dd>One of <tt>active</tt>, <tt>probationary</tt>, or <tt>revoked</tt>.</dd>
          <dt>authorizedEndpoints:</dt>
          <dd>
            An array of absolute URIs. A response is authorized only if the endpoint
            contacted matches one of these under <xref target="endpoint-matching"/>.
          </dd>
          <dt>models:</dt>
          <dd>
            An array of model identifiers this provider is registered to serve. A seal
            naming a model outside this array is invalid.
          </dd>
          <dt>keys:</dt>
          <dd>An array of key objects, as specified in <xref target="keys"/>.</dd>
          <dt>sealPolicy:</dt>
          <dd>Either <tt>all</tt> or <tt>none</tt>, as specified in <xref target="seal-policy"/>.</dd>
        </dl>
      </section>

      <section anchor="keys">
        <name>Keys and Selectors</name>
        <t>
          Each key object carries a <tt>selector</tt>, a <tt>publicKeyPem</tt> holding the
          public key in PEM-encoded SubjectPublicKeyInfo form <xref target="RFC8410"/>, and
          a <tt>status</tt> of <tt>current</tt>, <tt>rotating</tt>, or <tt>retired</tt>.
        </t>
        <t>
          Selectors <bcp14>MUST</bcp14> be unique within an entry. A verifier
          <bcp14>MUST</bcp14> reject a seal whose selector names a key with status
          <tt>retired</tt>, and <bcp14>MUST</bcp14> accept keys with status
          <tt>current</tt> or <tt>rotating</tt> as valid for verification.
        </t>
        <t>
          A provider rotating a key publishes the new key as <tt>rotating</tt> alongside the
          <tt>current</tt> key, begins signing under the new selector once the updated
          register has propagated, and subsequently marks the old key <tt>retired</tt>.
          Marking a key <tt>retired</tt> invalidates every seal made under it, including
          seals made before retirement, so this state is appropriate for key compromise and
          not for ordinary scheduled rotation.
        </t>
      </section>

      <section anchor="seal-policy">
        <name>Declared Sealing Policy</name>
        <t>
          A provider's <tt>sealPolicy</tt> declares whether the absence of a seal is
          meaningful. A value of <tt>none</tt> means the provider does not commit to sealing,
          and an unsealed response is simply unsealed. A value of <tt>all</tt> means the
          provider commits to sealing every response it serves, and an unsealed response
          purporting to come from it is therefore invalid on its face rather than merely
          unattributed.
        </t>
        <t>
          This is the mechanism by which stripping a seal becomes detectable. Without it, an
          attacker able to remove the <tt>AIDP-Seal</tt> header field would reduce a sealed
          exchange to an unsealed one and gain the treatment afforded to providers that
          never sealed at all.
        </t>
      </section>

      <section anchor="distribution">
        <name>Distribution and Trust Anchor</name>
        <t>
          A verifier obtains a register document and its detached signature by any means,
          and validates the signature against a registrar public key it holds
          independently. The registrar identification carried inside the document is
          descriptive only. A verifier <bcp14>MUST NOT</bcp14> validate a register document
          against a key obtained from that document.
        </t>
        <t>
          A verifier <bcp14>MUST NOT</bcp14> use a register document whose signature does
          not validate against an independently held registrar key.
        </t>
        <t>
          Because the document is signed and validated independently of how it arrived, the
          transport carries no security burden. A register served over HTTPS, retrieved from
          a transparency log, or shipped with the verifier is subject to the same check.
        </t>
      </section>

      <section anchor="dns-binding">
        <name>DNS Binding</name>
        <t>
          A provider binds its own domain to its register entry by publishing a TXT record
          at the <tt>_aidp</tt> underscored node name <xref target="RFC8552"/> beneath that
          domain. The record value is a sequence of tag-value pairs separated by
          semicolons:
        </t>
        <artwork type="ascii-art"><![CDATA[
_aidp.provider.example. IN TXT
    "v=aidp1; e=provider.example.entry;
     r=https://register.example.net/aidp; p=all"
]]></artwork>
        <dl newline="false" spacing="normal">
          <dt>v:</dt>
          <dd>Version. <bcp14>MUST</bcp14> be <tt>aidp1</tt> and <bcp14>MUST</bcp14> be first.</dd>
          <dt>e:</dt>
          <dd>The provider's register entry identifier.</dd>
          <dt>r:</dt>
          <dd>The URI of the register document that carries the entry.</dd>
          <dt>p:</dt>
          <dd>The declared sealing policy, <tt>all</tt> or <tt>none</tt>.</dd>
        </dl>
        <t>
          The record is anchored at the provider's identity domain, not at any serving
          endpoint. A provider serving from many hosts, from a content delivery network, or
          from infrastructure it does not administer publishes one record under the domain
          whose name its seals assert.
        </t>
        <t>
          The binding is what makes register substitution ineffective. An attacker who
          controls a register document but not the provider's DNS cannot make a verifier
          consult a forged entry, because the entry identifier and the register location
          both come from the provider's own zone. An attacker who controls the provider's
          DNS but not the registrar's signing key cannot produce a validly signed entry.
          Both are required, and they are held by different parties.
        </t>
        <t>
          Where the DNS record and the register entry both declare a sealing policy and the
          two disagree, a verifier <bcp14>MUST</bcp14> apply the policy <tt>all</tt> if
          either source declares it. Where the DNS lookup does not complete, a verifier
          <bcp14>MUST</bcp14> apply the policy declared in the register entry and
          <bcp14>MUST NOT</bcp14> treat the failed lookup as a declaration of <tt>none</tt>.
        </t>
      </section>
    </section>

    <section anchor="verification">
      <name>Verification</name>
      <t>
        A verifier evaluates a response against the register entry of the provider it
        intended to contact. The checks below are performed in order. Each check that fails
        produces a finding; findings marked as refusing mean the response
        <bcp14>MUST NOT</bcp14> be treated as attributed to the named provider.
      </t>

      <section anchor="entry-selection">
        <name>Entry Selection</name>
        <t>
          The verifier <bcp14>MUST</bcp14> select the register entry from the provider
          identity it intended to contact. It <bcp14>MUST NOT</bcp14> select the entry using
          the <tt>register-entry</tt> field of the received seal.
        </t>
        <t>
          Where a seal is present and its <tt>register-entry</tt> field does not equal the
          identifier of the selected entry, the verifier <bcp14>MUST</bcp14> treat the
          response as unattributed. This is a refusing finding and is not a direction to
          consult the entry the seal named.
        </t>
        <t>
          The requirement exists because a signed object that selects its own validating
          authority proves only self-consistency. A response naming an entry that
          legitimately holds the key that signed it produces a seal that verifies perfectly
          and attests to a provider the user never chose to contact.
        </t>
      </section>

      <section anchor="entry-status">
        <name>Entry Status</name>
        <t>
          Where the selected entry is not present in the register, the response
          <bcp14>MUST</bcp14> be treated as unattributed. Where the entry carries status
          <tt>revoked</tt>, the response <bcp14>MUST</bcp14> be treated as unattributed
          regardless of seal validity.
        </t>
      </section>

      <section anchor="seal-presence">
        <name>Seal Presence</name>
        <t>
          Where no seal is present and the applicable sealing policy is <tt>none</tt>, the
          verifier reports the response as unsealed and continues. This is not a failure.
        </t>
        <t>
          Where no seal is present and the applicable sealing policy is <tt>all</tt>, the
          verifier <bcp14>MUST</bcp14> treat this as a downgrade and the response
          <bcp14>MUST NOT</bcp14> be treated as attributed.
        </t>
      </section>

      <section anchor="freshness">
        <name>Freshness</name>
        <t>
          Where a seal is present, the verifier <bcp14>MUST</bcp14> evaluate its
          <tt>signed-at</tt> value against the time at which the response was received.
        </t>
        <t>
          A seal dated more than a permitted forward skew after the receipt time
          <bcp14>MUST</bcp14> be treated as invalid. Signing necessarily precedes receipt,
          so any forward offset is clock disagreement. The <bcp14>RECOMMENDED</bcp14>
          forward skew allowance is 300 seconds.
        </t>
        <t>
          A seal dated more than a permitted age before the receipt time
          <bcp14>MUST</bcp14> be treated as invalid. The <bcp14>RECOMMENDED</bcp14> maximum
          age is 3600 seconds.
        </t>
        <t>
          Freshness is evaluated against the receipt time of the response that carried the
          seal, and not against the verifier's clock at the moment of evaluation. This
          distinction matters where a verifier re-evaluates a stored exchange: verification
          of a retained response yields the same verdict later that it yielded at delivery,
          which would not hold if the comparison were against present time.
        </t>
        <t>
          A seal whose <tt>signed-at</tt> value is not a parseable Internet date/time string
          <bcp14>MUST</bcp14> be treated as invalid.
        </t>
      </section>

      <section anchor="key-resolution">
        <name>Key Resolution and Signature</name>
        <t>
          The verifier locates the key in the selected entry whose selector equals the
          <tt>selector</tt> field of the seal and whose status is not <tt>retired</tt>.
          Where no such key exists, the response <bcp14>MUST</bcp14> be treated as
          unattributed.
        </t>
        <t>
          The verifier reconstructs the canonical payload of <xref target="canonical"/> from
          the seal fields and the received content, and validates the signature against the
          located public key. Where the signature does not validate, the response
          <bcp14>MUST</bcp14> be treated as unattributed.
        </t>
      </section>

      <section anchor="model-authorization">
        <name>Model Authorization</name>
        <t>
          Where the signature validates, the verifier <bcp14>MUST</bcp14> check that the
          <tt>model</tt> field of the seal appears in the <tt>models</tt> array of the
          selected entry. A seal naming a model the entry is not registered to serve
          <bcp14>MUST</bcp14> be treated as invalid.
        </t>
      </section>

      <section anchor="endpoint-matching">
        <name>Endpoint Authorization</name>
        <t>
          The verifier <bcp14>MUST</bcp14> check the endpoint actually contacted against the
          <tt>authorizedEndpoints</tt> array of the selected entry. A contacted URI matches
          a registered URI when all of the following hold:
        </t>
        <ul spacing="normal">
          <li>Neither URI carries userinfo.</li>
          <li>
            The two URIs have identical origins: the same scheme, the same host compared
            case-insensitively, and the same port after normalization of the scheme's
            default port.
          </li>
          <li>
            The contacted path, after removal of trailing slash characters, either equals
            the registered path after the same removal, or begins with the registered path
            followed by a slash.
          </li>
        </ul>
        <t>
          Matching <bcp14>MUST NOT</bcp14> be performed by string prefix comparison on the
          URIs. Such a comparison authorizes a contacted URI of
          <tt>https://api.example.com/v1evil</tt> against a registered URI of
          <tt>https://api.example.com/v1</tt>, because the registered string is a prefix of
          the contacted string without being a prefix of its path segments.
        </t>
        <t>
          Where the contacted endpoint does not match, the response <bcp14>MUST</bcp14> be
          treated as unattributed, whether or not its seal validates.
        </t>
      </section>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>

      <section anchor="iana-header">
        <name>HTTP Field Name Registration</name>
        <t>
          IANA is requested to register the following entry in the "Hypertext Transfer
          Protocol (HTTP) Field Name Registry" defined in <xref target="RFC9110"/>:
        </t>
        <dl newline="false" spacing="compact">
          <dt>Field Name:</dt>
          <dd>AIDP-Seal</dd>
          <dt>Status:</dt>
          <dd>permanent</dd>
          <dt>Reference:</dt>
          <dd>This document, <xref target="transport"/></dd>
        </dl>
        <t>
          Deployments predating this document carry the same value in a field named
          <tt>X-AIDP-Seal</tt>. That name is deprecated in accordance with
          <xref target="RFC6648"/> and is not registered. A verifier
          <bcp14>MAY</bcp14> accept it for compatibility with existing deployments and
          <bcp14>MUST</bcp14> prefer <tt>AIDP-Seal</tt> where both are present.
        </t>
      </section>

      <section anchor="iana-dns">
        <name>Underscored Node Name Registration</name>
        <t>
          IANA is requested to register the following entry in the "Underscored and Globally
          Scoped DNS Node Names" registry defined in <xref target="RFC8552"/>:
        </t>
        <dl newline="false" spacing="compact">
          <dt>RR Type:</dt>
          <dd>TXT</dd>
          <dt>_NODE NAME:</dt>
          <dd>_aidp</dd>
          <dt>Reference:</dt>
          <dd>This document, <xref target="dns-binding"/></dd>
        </dl>
      </section>

      <section anchor="iana-alg">
        <name>AIDP Provenance Seal Algorithms Registry</name>
        <t>
          IANA is requested to create a registry titled "AIDP Provenance Seal Algorithms",
          with registration policy Specification Required <xref target="RFC8126"/>. Each
          entry carries an algorithm token, a reference, and a status of either
          <tt>current</tt> or <tt>deprecated</tt>.
        </t>
        <t>The initial contents are:</t>
        <table>
          <thead>
            <tr><th>Token</th><th>Status</th><th>Reference</th></tr>
          </thead>
          <tbody>
            <tr><td>ed25519</td><td>current</td><td>This document, <xref target="RFC8032"/></td></tr>
          </tbody>
        </table>
        <t>
          A verifier <bcp14>MUST</bcp14> treat a seal carrying an algorithm token that is
          absent from this registry, or present with status <tt>deprecated</tt>, as invalid.
        </t>
      </section>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>

      <section anchor="sec-what-is-proven">
        <name>What a Valid Seal Establishes</name>
        <t>
          A valid seal establishes that a holder of a registered private key asserted the
          named model, the named provider identity, and the given time over exactly the
          received bytes. It does not establish that the named model performed the
          computation. <xref target="non-goals"/> states this limit; it bears repeating here
          because the failure mode is a verifier that reports a valid seal in language a
          user reads as a guarantee about what answered them.
        </t>
        <t>
          Implementations <bcp14>SHOULD</bcp14> surface seal validity in terms of
          attribution rather than in terms of correctness, safety, or identity of
          computation.
        </t>
      </section>

      <section anchor="sec-injection">
        <name>Canonical Payload Injection</name>
        <t>
          <xref target="field-constraints"/> forbids LF and CR in header field values. The
          constraint is enforced at signing rather than only at verification so that an
          ambiguous payload cannot be produced at all. A signer that enforces the constraint
          only on verification remains capable of emitting a seal that a divergent parser
          reads differently, which is the condition the constraint exists to prevent.
        </t>
      </section>

      <section anchor="sec-replay">
        <name>Replay</name>
        <t>
          A seal is bound to its content, so a captured seal cannot be attached to different
          content. It can, however, be replayed together with its original content. The
          freshness bounds of <xref target="freshness"/> limit that window.
        </t>
        <t>
          Within the freshness window, replay of a response together with its seal is not
          detected by this specification. Where a verifier requires stronger assurance, a
          binding between the request and the response is necessary. Such a binding is not
          specified in this document.
        </t>
      </section>

      <section anchor="sec-downgrade">
        <name>Downgrade</name>
        <t>
          The declared sealing policy is the sole defense against seal stripping, and it is
          only as reliable as the verifier's ability to learn it. An attacker positioned to
          strip the <tt>AIDP-Seal</tt> field is frequently also positioned to interfere with
          the verifier's DNS resolution.
        </t>
        <t>
          <xref target="dns-binding"/> therefore requires that a failed DNS lookup fall back
          to the register-declared policy rather than to <tt>none</tt>. Verifiers
          <bcp14>SHOULD</bcp14> additionally cache observed policy declarations and
          <bcp14>SHOULD</bcp14> treat a transition from <tt>all</tt> to <tt>none</tt> for a
          previously observed provider as suspicious rather than as a routine update.
        </t>
      </section>

      <section anchor="sec-registrar">
        <name>Registrar Compromise</name>
        <t>
          A registrar signing key is a trust anchor. Its compromise permits forged entries,
          which permits attribution of arbitrary responses to arbitrary providers. The DNS
          binding of <xref target="dns-binding"/> constrains this: an attacker holding a
          registrar key but not a provider's DNS cannot cause a verifier to consult a forged
          entry for that provider.
        </t>
        <t>
          The residual exposure is a provider for which the verifier has no DNS binding.
          Verifiers <bcp14>SHOULD</bcp14> distinguish, in whatever they report, between an
          entry confirmed by a DNS binding and an entry taken from a register document
          alone.
        </t>
        <t>
          This document does not specify registrar governance, registrar accreditation, or
          the process by which a provider obtains an entry.
        </t>
      </section>

      <section anchor="sec-privacy">
        <name>Privacy</name>
        <t>
          A verifier that resolves <tt>_aidp</tt> beneath a provider's domain before or
          during an exchange discloses to its resolver, and to any observer of that
          resolution, which inference providers a user is contacting and approximately when.
          The DNS queries are a side channel that the exchange itself, carried over TLS to a
          possibly shared host, may not otherwise expose.
        </t>
        <t>
          Verifiers <bcp14>SHOULD</bcp14> cache DNS bindings for their full TTL rather than
          resolving per exchange, and <bcp14>SHOULD</bcp14> use encrypted DNS transport
          where available.
        </t>
        <t>
          The register document itself carries no user-specific information, and retrieving
          it in full rather than querying for individual entries avoids disclosing which
          entries a verifier is interested in. Verifiers <bcp14>SHOULD</bcp14> retrieve
          whole register documents for this reason.
        </t>
      </section>

      <section anchor="sec-endpoint">
        <name>Endpoint Authorization Is Not Transport Security</name>
        <t>
          The endpoint check of <xref target="endpoint-matching"/> establishes that the
          contacted URI is one the provider registered. It is not a substitute for
          authenticating the connection. A verifier <bcp14>MUST</bcp14> continue to perform
          normal TLS server authentication; a registered endpoint reached over an
          unauthenticated connection offers no assurance.
        </t>
      </section>
    </section>

  </middle>

  <back>
    <references>
      <name>Normative References</name>

      <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
        <front>
          <title>Key words for use in RFCs to Indicate Requirement Levels</title>
          <author initials="S." surname="Bradner" fullname="S. Bradner"/>
          <date year="1997" month="March"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="2119"/>
        <seriesInfo name="DOI" value="10.17487/RFC2119"/>
      </reference>

      <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
        <front>
          <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
          <author initials="B." surname="Leiba" fullname="B. Leiba"/>
          <date year="2017" month="May"/>
        </front>
        <seriesInfo name="BCP" value="14"/>
        <seriesInfo name="RFC" value="8174"/>
        <seriesInfo name="DOI" value="10.17487/RFC8174"/>
      </reference>

      <reference anchor="RFC3339" target="https://www.rfc-editor.org/info/rfc3339">
        <front>
          <title>Date and Time on the Internet: Timestamps</title>
          <author initials="G." surname="Klyne" fullname="G. Klyne"/>
          <author initials="C." surname="Newman" fullname="C. Newman"/>
          <date year="2002" month="July"/>
        </front>
        <seriesInfo name="RFC" value="3339"/>
        <seriesInfo name="DOI" value="10.17487/RFC3339"/>
      </reference>

      <reference anchor="RFC4648" target="https://www.rfc-editor.org/info/rfc4648">
        <front>
          <title>The Base16, Base32, and Base64 Data Encodings</title>
          <author initials="S." surname="Josefsson" fullname="S. Josefsson"/>
          <date year="2006" month="October"/>
        </front>
        <seriesInfo name="RFC" value="4648"/>
        <seriesInfo name="DOI" value="10.17487/RFC4648"/>
      </reference>

      <reference anchor="RFC8032" target="https://www.rfc-editor.org/info/rfc8032">
        <front>
          <title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title>
          <author initials="S." surname="Josefsson" fullname="S. Josefsson"/>
          <author initials="I." surname="Liusvaara" fullname="I. Liusvaara"/>
          <date year="2017" month="January"/>
        </front>
        <seriesInfo name="RFC" value="8032"/>
        <seriesInfo name="DOI" value="10.17487/RFC8032"/>
      </reference>

      <reference anchor="RFC8410" target="https://www.rfc-editor.org/info/rfc8410">
        <front>
          <title>Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 for Use in the Internet X.509 Public Key Infrastructure</title>
          <author initials="S." surname="Josefsson" fullname="S. Josefsson"/>
          <author initials="J." surname="Schaad" fullname="J. Schaad"/>
          <date year="2018" month="August"/>
        </front>
        <seriesInfo name="RFC" value="8410"/>
        <seriesInfo name="DOI" value="10.17487/RFC8410"/>
      </reference>

      <reference anchor="RFC8552" target="https://www.rfc-editor.org/info/rfc8552">
        <front>
          <title>Scoped Interpretation of DNS Resource Records through "Underscored" Naming of Attribute Leaves</title>
          <author initials="D." surname="Crocker" fullname="D. Crocker"/>
          <date year="2019" month="March"/>
        </front>
        <seriesInfo name="BCP" value="222"/>
        <seriesInfo name="RFC" value="8552"/>
        <seriesInfo name="DOI" value="10.17487/RFC8552"/>
      </reference>

      <reference anchor="RFC9110" target="https://www.rfc-editor.org/info/rfc9110">
        <front>
          <title>HTTP Semantics</title>
          <author initials="R." surname="Fielding" fullname="R. Fielding" role="editor"/>
          <author initials="M." surname="Nottingham" fullname="M. Nottingham" role="editor"/>
          <author initials="J." surname="Reschke" fullname="J. Reschke" role="editor"/>
          <date year="2022" month="June"/>
        </front>
        <seriesInfo name="STD" value="97"/>
        <seriesInfo name="RFC" value="9110"/>
        <seriesInfo name="DOI" value="10.17487/RFC9110"/>
      </reference>

      <reference anchor="RFC8126" target="https://www.rfc-editor.org/info/rfc8126">
        <front>
          <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
          <author initials="M." surname="Cotton" fullname="M. Cotton"/>
          <author initials="B." surname="Leiba" fullname="B. Leiba"/>
          <author initials="T." surname="Narten" fullname="T. Narten"/>
          <date year="2017" month="June"/>
        </front>
        <seriesInfo name="BCP" value="26"/>
        <seriesInfo name="RFC" value="8126"/>
        <seriesInfo name="DOI" value="10.17487/RFC8126"/>
      </reference>

      <reference anchor="RFC6648" target="https://www.rfc-editor.org/info/rfc6648">
        <front>
          <title>Deprecating the "X-" Prefix and Similar Constructs in Application Protocols</title>
          <author initials="P." surname="Saint-Andre" fullname="P. Saint-Andre"/>
          <author initials="D." surname="Crocker" fullname="D. Crocker"/>
          <author initials="M." surname="Nottingham" fullname="M. Nottingham"/>
          <date year="2012" month="June"/>
        </front>
        <seriesInfo name="BCP" value="178"/>
        <seriesInfo name="RFC" value="6648"/>
        <seriesInfo name="DOI" value="10.17487/RFC6648"/>
      </reference>
    </references>

    <references>
      <name>Informative References</name>

      <reference anchor="RFC6376" target="https://www.rfc-editor.org/info/rfc6376">
        <front>
          <title>DomainKeys Identified Mail (DKIM) Signatures</title>
          <author initials="D." surname="Crocker" fullname="D. Crocker" role="editor"/>
          <author initials="T." surname="Hansen" fullname="T. Hansen" role="editor"/>
          <author initials="M." surname="Kucherawy" fullname="M. Kucherawy" role="editor"/>
          <date year="2011" month="September"/>
        </front>
        <seriesInfo name="STD" value="76"/>
        <seriesInfo name="RFC" value="6376"/>
        <seriesInfo name="DOI" value="10.17487/RFC6376"/>
      </reference>

      <reference anchor="RFC7208" target="https://www.rfc-editor.org/info/rfc7208">
        <front>
          <title>Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1</title>
          <author initials="S." surname="Kitterman" fullname="S. Kitterman"/>
          <date year="2014" month="April"/>
        </front>
        <seriesInfo name="RFC" value="7208"/>
        <seriesInfo name="DOI" value="10.17487/RFC7208"/>
      </reference>

      <reference anchor="RFC7489" target="https://www.rfc-editor.org/info/rfc7489">
        <front>
          <title>Domain-based Message Authentication, Reporting, and Conformance (DMARC)</title>
          <author initials="M." surname="Kucherawy" fullname="M. Kucherawy" role="editor"/>
          <author initials="E." surname="Zwicky" fullname="E. Zwicky" role="editor"/>
          <date year="2015" month="March"/>
        </front>
        <seriesInfo name="RFC" value="7489"/>
        <seriesInfo name="DOI" value="10.17487/RFC7489"/>
      </reference>

      <reference anchor="AIDP" target="https://doi.org/10.5281/zenodo.21610185">
        <front>
          <title>The Accountable Inference Delivery Protocol</title>
          <author initials="J. P." surname="Flores" fullname="Justin Philip Flores"/>
          <date year="2026"/>
        </front>
        <seriesInfo name="DOI" value="10.5281/zenodo.21610185"/>
      </reference>

      <reference anchor="ADVOCATE" target="https://github.com/AIDP-protocol/inference-advocate">
        <front>
          <title>Inference Advocate: a reference implementation of the client side of AIDP</title>
          <author initials="J. P." surname="Flores" fullname="Justin Philip Flores"/>
          <date year="2026"/>
        </front>
      </reference>
    </references>

    <section anchor="implementation">
      <name>Implementation Status</name>
      <t>
        An open-source implementation of the verification procedure of
        <xref target="verification"/> is available at <xref target="ADVOCATE"/> under the
        Apache License 2.0. It implements entry selection, entry status, seal presence and
        policy, freshness, key resolution, signature validation, model authorization, and
        endpoint matching, with a test covering each requirement of this document. It ships
        a mock signing provider so that the signing half is exercisable without a
        cooperating provider.
      </t>
      <t>
        The deployed Serving Register described in <xref target="distribution"/> does not
        exist. The implementation loads a signed register document from local storage and
        validates it against a pinned registrar key, which is the same check a retrieved
        document receives. No production register, registrar, or accreditation process is
        operating.
      </t>
      <t>
        No inference provider known to the author currently signs its responses. Every
        response reaching a deployed verifier today is unsealed, which this document treats
        as a reportable condition rather than an error precisely so that verification can be
        deployed before signing exists.
      </t>
      <t>This section is to be removed before publication as an RFC.</t>
    </section>

    <section anchor="ancestry">
      <name>Relationship to Electronic Mail Authentication</name>
      <t>
        The correspondence to mail authentication is close enough to be worth stating
        plainly, both to credit the design and to help implementers reason by analogy.
      </t>
      <t>
        The Provenance Seal corresponds to DKIM <xref target="RFC6376"/>: a detached
        signature over a message, validated with a key published by the signing party under
        a selector. <xref target="entry-selection"/> departs from DKIM deliberately. DKIM
        takes the signing domain from the signature header itself, which is sound in mail
        because the result feeds an alignment check against a separately obtained identity.
        This document has no equivalent later alignment step, so it forbids the seal from
        selecting its own validating entry rather than permitting it and correcting for it
        afterward.
      </t>
      <t>
        The Serving Register corresponds to SPF <xref target="RFC7208"/>: a published
        statement of which hosts may act for a named party. It is carried as a signed
        document rather than in DNS because the data is larger, changes more often, and
        benefits from audit history, while DNS retains the jobs it does well: proof of
        domain control and the binding of <xref target="dns-binding"/>.
      </t>
      <t>
        The declared sealing policy of <xref target="seal-policy"/> corresponds to the
        published policy of DMARC <xref target="RFC7489"/>. Its function is identical: to
        convert the absence of authentication from an ambiguous condition into a declared
        failure.
      </t>
    </section>

    <section anchor="acknowledgments" numbered="false">
      <name>Acknowledgments</name>
      <t>
        The architecture from which these two mechanisms are drawn is described in
        <xref target="AIDP"/>.
      </t>
    </section>
  </back>
</rfc>
