<?xml version="1.0" encoding="utf-8"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     docName="draft-schrock-ep-authorization-evidence-chain-08"
     category="info" ipr="trust200902" submissionType="IETF"
     version="3" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="Authorization Evidence Chains">Authorization Evidence Chains: Composing Heterogeneous Agent-Action Evidence (EP-AEC)</title>
    <seriesInfo name="Internet-Draft" value="draft-schrock-ep-authorization-evidence-chain-08"/>
    <author fullname="Iman Schrock">
      <organization>EMILIA Protocol, Inc.</organization>
      <address>
        <postal>
          <country>US</country>
        </postal>
        <email>team@emiliaprotocol.ai</email>
      </address>
    </author>
    <date year="2026" month="October" day="4"/>
    <area>sec</area>
    <keyword>AI agents</keyword>
    <keyword>authorization</keyword>
    <keyword>evidence</keyword>
    <keyword>composition</keyword>
    <keyword>replay</keyword>
    <keyword>JCS</keyword>
    <abstract>
      <t>Consequential agent actions can produce heterogeneous identity,
      delegation, policy, permit, approval, transparency, capability, and
      execution artifacts. Each artifact can verify under its own
      specification while still referring to a different action, filling a
      different evidentiary role, or failing a relying party's freshness,
      status, or inter-artifact binding requirement. This document defines
      the Authorization Evidence Chain (EP-AEC): a transport-agnostic
      composition object and a fail-closed evaluation algorithm that keeps
      native cryptographic verification separate from relying-party
      acceptance, establishes exact material-action matching, and evaluates a
      relying-party-pinned evidence requirement.</t>
      <t>AEC produces SATISFIED or UNSATISFIED and a replayable evaluation
      record. SATISFIED means only that the presented evidence filled the
      relying party's named evidence requirement at the stated verification
      time. It is not a universal authorization decision, a policy language
      for the protected application, or proof of execution or outcome. The
      executor makes the separate local AUTHORIZED decision and controls
      consumption, invocation, and effect handling. Qualification evidence can
      fill a named evidence role but cannot authorize an action by itself. AEC
      introduces no new component receipt type and does not replace any native
      verifier.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="intro">
      <name>Introduction</name>
      <t>One consequential action can produce several independently useful
      artifacts: a workload credential, a delegation record, a policy permit,
      a named-human authorization receipt, a quorum, a bounded-capability
      operation record, or a transparency receipt. These artifacts answer
      different questions. A relying party may require several of them for one
      action.</t>
      <t>Native verification is not sufficient for composition. A permit for
      action A and an approval for action B, each VERIFIED and ACCEPTED, do
      not jointly authorize either action. Likewise, two VERIFIED and ACCEPTED
      artifacts can still be inadequate if the relying party required a
      fresher approval, a checked revocation status, or a byte-backed relation
      showing that one artifact explicitly references another.</t>
      <t>EP-AEC provides the thin composition layer. It dispatches artifacts
      to their native verifiers, maps only integrity-protected native action
      commitments to the relying party's expected material action, evaluates
      an evidence requirement owned by the relying party, and records the
      exact inputs to that evidence decision. It does not decide whether the
      protected application should act.</t>

      <section anchor="scope">
        <name>Scope and Non-Goals</name>
        <t>This document defines:</t>
        <ul>
          <li>the EP-AEC-v1 composition object;</li>
          <li>the EP-AEC-REQUIREMENT-v1 relying-party evidence requirement;</li>
          <li>a verifier-result contract that keeps native verification,
          relying-party acceptance, and material-action mapping separate;</li>
          <li>a fail-closed SATISFIED or UNSATISFIED evaluation; and</li>
          <li>the EP-AEC-REPLAY-v1 evaluation record and replay digest.</li>
        </ul>
        <t>This document does not define a universal evidence taxonomy, a
        general authorization policy language, a component receipt format, an
        application allow or deny decision, a signed reliance-result format,
        a transparency service, or an execution state machine. It does not
        require a graph wire format or make presenter-asserted graph edges
        authoritative.</t>
      </section>
    </section>

    <section anchor="terminology">
      <name>Terminology</name>
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED",
      "MAY", and "OPTIONAL" in this document are to be interpreted as
      described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
      when, and only when, they appear in all capitals, as shown here.</t>
      <t>BCP 14 is indexed by the RFC Editor at <xref target="BCP14"/>.</t>
      <dl>
        <dt>Native verifier</dt>
        <dd>A verifier selected by the relying party for one artifact format
        and revision. For each artifact it reports two separate results,
        VERIFIED and ACCEPTED (<xref target="native-contract"/>).</dd>
        <dt>VERIFIED</dt>
        <dd>The native verifier's cryptographic and structural checks passed:
        the artifact is well formed under the native format rules the verifier
        implements, and every signature or proof it carries verifies over the
        bytes it covers. Except where a native procedure checks trust inputs
        and cryptography together and cannot attribute a failure
        (<xref target="native-contract"/>), VERIFIED depends only on the
        artifact, the format specification, and the verification key. When a
        format names its key only by reference,
        that key is the one resolved from relying-party key material
        (<xref target="native-contract"/>). VERIFIED says nothing about whether
        the relying party trusts that key, issuer, or policy, and nothing about
        whether the artifact denotes the expected material action.</dd>
        <dt>ACCEPTED</dt>
        <dd>A VERIFIED artifact also meets the relying party's pinned trust
        inputs for its component type (<xref target="acceptance-inputs"/>): the
        verification key is, or chains to, a trust anchor or directory entry
        pinned for that component's role and is usable at the verification
        time; the issuer, audience, key class, native policy, and format
        revision are ones the relying party pinned; and the verification time
        falls within the artifact's native validity period. ACCEPTED is
        relative to one relying party's pins. With the same exception, a party
        with different trust inputs that holds or resolves the same
        verification key can reproduce VERIFIED for the same bytes and reach a
        different acceptance result. ACCEPTED does not depend on the expected material action;
        MATCH decides that.</dd>
        <dt>MATCH</dt>
        <dd>A VERIFIED and ACCEPTED artifact's integrity-protected native action
        commitment denotes the relying party's expected material action by
        direct exact digest equality or by an exact, relying-party-pinned CAID
        mapping profile.</dd>
        <dt>SATISFIED</dt>
        <dd>Eligible evidence filled the relying party's evidence requirement
        at the explicit verification time.</dd>
        <dt>UNSATISFIED</dt>
        <dd>Every evaluation result other than SATISFIED, including an
        evaluation that could not complete. UNSATISFIED does not by itself mean
        that evidence was shown to be missing or invalid; bounded reason codes
        say why.</dd>
        <dt>AUTHORIZED</dt>
        <dd>A separate local application decision permitting an invocation.
        AEC does not produce this state.</dd>
        <dt>Evidence digest</dt>
        <dd>The string "sha256:" followed by the lowercase hexadecimal
        SHA-256 digest of an artifact's JCS <xref target="RFC8785"/>
        serialization.</dd>
        <dt>Normalized evidence fact</dt>
        <dd>A verifier-produced, bounded record of the VERIFIED and ACCEPTED
        results, material-action mapping, time and status checks, and
        byte-backed bindings for one component. It is not supplied by the
        presenter.</dd>
      </dl>
    </section>

    <section anchor="object">
      <name>The Authorization Evidence Chain Object</name>
      <sourcecode type="json"><![CDATA[
{
  "@version": "EP-AEC-v1",
  "action": { "...": "Action Object" },
  "action_digest": "sha256:<hex>",
  "action_caid": "caid:1:<action-type>:<suite>:<digest-b64url>",
  "components": [
    {
      "type": "ep-quorum",
      "label": "two-person human authorization",
      "evidence_digest": "sha256:<hex>",
      "evidence": { "...": "native artifact" }
    },
    {
      "type": "policy-permit",
      "evidence": { "...": "native artifact" }
    }
  ],
  "requirement": "ep-quorum AND policy-permit"
}
]]></sourcecode>
      <ul>
        <li><tt>@version</tt> (string, REQUIRED) MUST equal
        <tt>EP-AEC-v1</tt>.</li>
        <li><tt>action</tt> (object, REQUIRED) is the closed Action Object to
        which the evaluation is joined.</li>
        <li><tt>action_digest</tt> (string, OPTIONAL) is descriptive. When
        present, it MUST equal the verifier's recomputation over
        <tt>action</tt>.</li>
        <li><tt>action_caid</tt> (string, OPTIONAL) is descriptive. It MUST NOT
        establish its own mapping or trust. When the relying party requires a
        CAID, the verifier recomputes or independently obtains the expected
        CAID and compares it as specified in <xref target="matching"/>.</li>
        <li><tt>components</tt> (array, REQUIRED and non-empty) contains
        <tt>type</tt> (string), <tt>evidence</tt> (JSON value suitable for the
        native format), and optional <tt>label</tt> and
        <tt>evidence_digest</tt> strings. A label is display-only. When an
        evidence digest is present, the verifier MUST recompute and compare
        it before native verification.</li>
        <li><tt>requirement</tt> (string, OPTIONAL) is a presenter-supplied
        description. It MUST NOT become the relying party's sufficiency bar
        and MUST NOT produce SATISFIED.</li>
      </ul>
      <t>The chain is a bundle, not an authority-bearing graph. Component
      order is preserved for reporting, but order confers no semantics. All
      credited relations between components come from integrity-protected
      native bytes exposed by a trusted native verifier, never from labels,
      ordering, or presenter-supplied edges.</t>
    </section>

    <section anchor="rp-requirement">
      <name>The Relying-Party Evidence Requirement</name>
      <t>Before returning SATISFIED, a verifier MUST receive an
      EP-AEC-REQUIREMENT-v1 object from relying-party-controlled
      configuration. The chain document cannot supply or weaken it.</t>
      <sourcecode type="json"><![CDATA[
{
  "@version": "EP-AEC-REQUIREMENT-v1",
  "requirement_id": "treasury-wire-evidence@7",
  "purpose": "pre-execution evidence check",
  "expression": "ep-quorum AND policy-permit",
  "freshness_sec": {
    "ep-quorum": 300,
    "policy-permit": 600
  },
  "status_required": ["ep-quorum"],
  "role_constraints": [
    {
      "type": "distinct-subject-quorum",
      "component_type": "ep-human-authorization",
      "threshold": 2,
      "subject_id_source": "native-verifier"
    }
  ],
  "required_bindings": [
    {
      "from_type": "policy-permit",
      "relation": "permits",
      "to_type": "ep-quorum"
    }
  ]
}
]]></sourcecode>
      <ul>
        <li><tt>@version</tt> MUST equal
        <tt>EP-AEC-REQUIREMENT-v1</tt>.</li>
        <li><tt>requirement_id</tt> is a relying-party identifier for the exact
        evidence requirement revision. It carries no authority by itself.</li>
        <li><tt>purpose</tt> is descriptive and MUST NOT alter expression
        evaluation.</li>
        <li><tt>expression</tt> is REQUIRED and follows
        <xref target="expressions"/>.</li>
        <li><tt>freshness_sec</tt> is an OPTIONAL map from component type to a
        non-negative maximum age in seconds.</li>
        <li><tt>status_required</tt> is an OPTIONAL array of component types
        for which a fresh authenticated status result is required.</li>
        <li><tt>role_constraints</tt> is an OPTIONAL array of closed evidence
        constraints. This revision defines only
        <tt>distinct-subject-quorum</tt>. Its <tt>component_type</tt> names an
        evidence role, <tt>threshold</tt> is an integer greater than one, and
        <tt>subject_id_source</tt> MUST equal <tt>native-verifier</tt>. A
        verifier counts distinct subjects only from integrity-protected native
        subject identifiers returned by eligible native verifiers. Presenter
        labels, signer-key encodings, and unverified subject claims MUST NOT be
        counted.</li>
        <li><tt>required_bindings</tt> is an OPTIONAL array of
        <tt>from_type</tt>, <tt>relation</tt>, and <tt>to_type</tt> triples.
        Each triple requires at least one eligible source component whose
        native verified bytes bind, under that relation, the evidence digest
        of an eligible target component of the named type.</li>
      </ul>
      <t>The verifier MUST compute the requirement profile digest, which is
      the evidence digest (<xref target="terminology"/>) of the complete
      requirement object: "sha256:" followed by the lowercase hexadecimal
      SHA-256 digest of its JCS serialization. JCS preserves string
      contents, and the expression enters that serialization exactly as
      stored: a verifier MUST NOT trim it, change its case, apply Unicode
      normalization to it, or otherwise rewrite it before computing the
      digest. Two requirements whose expressions have the same Boolean
      meaning, or the same parse identity (<xref target="parse-identity"/>),
      can have different requirement profile digests. The requirement
      object controls evidence sufficiency only. Application rules about
      amounts, destinations, operator permissions, legal authority, risk
      acceptance, or whether to execute remain in the separate local
      authorization policy.</t>
      <t>Initiator exclusion, executor exclusion, durable one-time consumption,
      resource ceilings, and whether to execute are boundary constraints rather
      than evidence-sufficiency constraints. They are defined and enforced by
      the Action Evidence Boundary <xref target="EP-AEB"/>. AEC MUST NOT report
      them as satisfied merely because an evidence component asserts them.</t>
    </section>

    <section anchor="acceptance-inputs">
      <name>Relying-Party Acceptance Inputs</name>
      <t>Internal agreement among presenter-supplied artifacts cannot satisfy
      a relying party. The verifier MUST receive these values from trusted
      configuration or from the protected boundary that is about to act:</t>
      <ul>
        <li>the EP-AEC-REQUIREMENT-v1 object;</li>
        <li>the expected Action Object or its independently computed canonical
        action digest;</li>
        <li>an expected CAID and mapping profiles when cross-format action
        mapping is used;</li>
        <li>an explicit verification time;</li>
        <li>for each component type, the selected native verifier revision;
        the key-resolution material from which the native verifier obtains a
        verification key that a format names only by reference; the pinned
        trust inputs that decide ACCEPTED, namely trust anchors or directory
        entries (for each key, the principal and role it is bound to, its key
        class, its validity period, and its compromise or revocation state),
        accepted issuers, audiences, key classes, native policy, and format
        revision; and the freshness inputs and status sources; and</li>
        <li>documented resource limits for parsing, nesting, component count,
        and verifier execution. The limits on a requirement expression are not
        configuration; <xref target="expr-limits"/> fixes them.</li>
      </ul>
      <t>These values MUST NOT be taken from the presented chain or from an
      untrusted caller. If any required input is absent, malformed, ambiguous,
      or outside its configured validity, the result is UNSATISFIED.</t>
      <t>The pinned trust inputs decide ACCEPTED. A verifier MUST NOT report
      an artifact as VERIFIED because its signer is pinned, or as ACCEPTED
      because its signatures verify.</t>
      <t>Key-resolution material and the pinned trust inputs can live in one
      directory. Resolution uses only the mapping from a key reference to key
      bytes. Everything else a directory entry states about that key is a
      pinned trust input and decides ACCEPTED, not VERIFIED.</t>
    </section>

    <section anchor="native-contract">
      <name>Native Verification and Normalized Facts</name>
      <t>AEC does not reinterpret a native signature or token. For each
      component, a relying-party-selected native verifier first returns a
      bounded internal result containing:</t>
      <ul>
        <li>the VERIFIED result, or an indication that VERIFIED could not be
        evaluated, and, for a VERIFIED artifact, the ACCEPTED result, each with
        a machine-readable reason when it is negative;</li>
        <li>the integrity-protected native action commitment, if any;</li>
        <li>the protected issuance and expiration instants needed by the
        selected freshness check;</li>
        <li>the protected issuer, audience, and format revision relevant to
        the selected native profile;</li>
        <li>an authenticated status result and status-snapshot digest when
        status checking is required; and</li>
        <li>zero or more relation and target-evidence-digest bindings extracted
        from integrity-protected native fields.</li>
      </ul>
      <t>A component reaches VERIFIED only when its native verifier's
      cryptographic and structural checks succeed, and reaches ACCEPTED only
      when it is VERIFIED and the pinned trust inputs for its component type
      accept it. The native verifier MUST report the two results separately.
      It MUST NOT report ACCEPTED for an artifact that is not VERIFIED, and
      MUST NOT report VERIFIED for an artifact whose integrity it did not
      check. When a native procedure checks trust inputs and cryptography
      together and cannot attribute a failure to one of them, the verifier
      reports the artifact as not VERIFIED. A component that is not both
      VERIFIED and ACCEPTED is ineligible.</t>
      <t>When a format identifies its verification key only by reference, the
      native verifier resolves the key from relying-party key material. If no
      key can be resolved, VERIFIED cannot be evaluated: the artifact is not
      VERIFIED, the normalized fact records its native verification as
      NOT_EVALUATED with a reason such as <tt>key_unresolved</tt>, never as
      FAILED, and the component is ineligible. Resolving a key does not make
      the artifact ACCEPTED: whether that key is pinned for the component's
      role, usable at the verification time, of an accepted class, and bound
      to the principal the artifact names is decided by ACCEPTED. For such
      formats VERIFIED depends on the resolved key as well as on the bytes, so
      relying parties whose key-resolution material resolves the same
      reference to different keys can reach different VERIFIED results for
      the same bytes.</t>
      <t>AEC MUST NOT accept a presenter's <tt>verified</tt> or
      <tt>accepted</tt> Boolean, normalized fact, mapping result, key, trust
      anchor, status assertion, or relation as a substitute for native
      verification or relying-party acceptance.</t>
      <t>A deployment in which a protected boundary performs native
      verification before calling the AEC evaluator MAY pass the verifier
      results internally instead of repeating the cryptographic work. Such
      results MUST carry the VERIFIED and ACCEPTED results separately and MUST
      be integrity-bound inside the same trust boundary to the exact evidence
      digest, native verifier profile digest, trust snapshot, and verification
      time. Serialized results received from the presenter
      are evidence artifacts of their own and require a native verifier; they
      are not trusted internal results.</t>
    </section>

    <section anchor="matching">
      <name>Material-Action Matching</name>
      <t>Native verification, relying-party acceptance, and material-action
      matching are distinct and ordered. Mapping MUST NOT inspect claims from
      an artifact that is not VERIFIED and ACCEPTED as authoritative
      input.</t>
      <ol>
        <li>The boundary computes the expected action digest from the frozen
        action it is actually preparing to perform.</li>
        <li>The native verifier reports the component VERIFIED and ACCEPTED
        and exposes only its integrity-protected native action
        commitment.</li>
        <li>If that commitment uses the same action representation and digest
        algorithm, exact digest equality establishes MATCH.</li>
        <li>Otherwise, a relying-party-pinned Action-Mapping Profile from
        <xref target="CAID"/> projects the VERIFIED and ACCEPTED native
        payload to the expected CAID action type. Only the CAID verdict
        EQUIVALENT_UNDER_PROFILE establishes MATCH.</li>
      </ol>
      <t>NOT_EQUIVALENT, INDETERMINATE, an unknown mapping revision, a lossy
      projection, a presenter-selected profile, or a mismatch between the
      projected CAID and the expected CAID is not MATCH and MUST make that
      component ineligible. CAID carries content identity, not trust or
      authorization semantics.</t>
      <t>A native verifier evaluates the pinned trust inputs against the
      action commitment the artifact itself carries and does not compare it
      with the expected action. An ACCEPTED artifact bound to a different
      action is ineligible because it is not MATCH, and its record says so; it
      is not reported as not ACCEPTED.</t>
    </section>

    <section anchor="expressions">
      <name>Requirement Expressions</name>
      <t>A requirement expression names the evidence roles a relying party
      requires and combines them with AND and OR. This section defines how an
      expression is tokenized, parsed, validated, and evaluated, so that
      every conforming evaluator gives each valid expression the same
      reading. The JavaScript reference parser that accompanied -07 and its
      Python and Go ports already agree with every vector of the corpus in
      <xref target="expr-vectors"/> on syntax validity and Boolean value.
      This section makes that behavior normative and testable, and it
      refuses readings that the -07 text permitted.</t>
      <t>The expression deliberately answers only which evidence roles are
      present. It has no variables for action parameters, principals,
      entitlements, business risk, or effect state. Those belong to native
      artifact verification and acceptance, CAID mapping, or local
      authorization.</t>

      <section anchor="expr-grammar">
        <name>Grammar</name>
        <t>The grammar uses ABNF and its core rules as defined by
        <xref target="RFC5234"/>, with the case-sensitive string syntax of
        <xref target="RFC7405"/>: <tt>%s"AND"</tt> matches only the three
        uppercase characters A, N, and D.</t>
        <sourcecode type="abnf"><![CDATA[
expression = ows term *( ows operator ows term ) ows
term       = identifier / "(" expression ")"
operator   = %s"AND" / %s"OR" / "&&" / "||"
identifier = 1*( ALPHA / DIGIT / "." / ":" / "-" / "_" )
ows        = *( SP / HTAB / CR / LF )
]]></sourcecode>
        <t>An expression is a JSON string. SP, HTAB, CR, and LF are its only
        whitespace characters. Any character that is not whitespace, an
        identifier character, a parenthesis, or part of an "&amp;&amp;" or
        "||" operator makes the expression invalid, so a single "&amp;" or
        "|" does. This includes NO-BREAK SPACE (U+00A0), EM SPACE
        (U+2003), LINE SEPARATOR (U+2028), BYTE ORDER MARK (U+FEFF), ZERO
        WIDTH SPACE (U+200B), VERTICAL TAB (U+000B), FORM FEED (U+000C), and
        every other character outside ASCII. None of them is whitespace, and
        none is removed before parsing.</t>
      </section>

      <section anchor="expr-tokens">
        <name>Token Boundaries</name>
        <t>Because <tt>ows</tt> can be empty, the ABNF alone admits more than
        one division of some inputs into tokens; it would allow
        "<tt>aORb</tt>" to be read as "<tt>a</tt>", "<tt>OR</tt>", "<tt>b</tt>".
        The following tokenization is normative and selects the only valid
        reading. A tokenizer scans the expression from left to right:</t>
        <ol>
          <li>SP, HTAB, CR, and LF separate tokens and are otherwise
          skipped.</li>
          <li>"(" and ")" are each one token.</li>
          <li>"&amp;&amp;" is the operator AND and "||" is the operator OR. A
          single "&amp;" or "|" is invalid.</li>
          <li>At an identifier character, the tokenizer MUST take the longest
          run of identifier characters before classifying it, and MUST then
          classify the complete run: a run that is exactly "<tt>AND</tt>" or
          exactly "<tt>OR</tt>" is that operator, and every other run is an
          identifier.</li>
          <li>Any other character makes the expression invalid.</li>
        </ol>
        <t>Thus "<tt>aORb</tt>", "<tt>ORb</tt>", "<tt>AND.x</tt>",
        "<tt>a.OR.b</tt>", and "<tt>p-OR-q</tt>" are each one identifier, and
        "<tt>a OR b</tt>" contains an operator. Identifiers are case-sensitive.
        Lowercase "<tt>and</tt>" and "<tt>or</tt>", and mixed-case forms such as
        "<tt>And</tt>" and "<tt>oR</tt>", are identifiers, not operators, and
        "<tt>And</tt>" does not match a component type named
        "<tt>and</tt>".</t>
        <t>AND and OR are reserved only as expression tokens. A native
        component type may be named "<tt>AND</tt>" or "<tt>OR</tt>", and such a
        name stays valid in native formats and wherever this document accepts
        a component type outside an expression. An expression cannot name such
        a type as an identifier; this revision defines no quoting
        mechanism.</t>
      </section>

      <section anchor="expr-evaluation">
        <name>Grouping, Validity, and Evaluation</name>
        <t>The parser applies the grammar to the token sequence. AND and OR
        have equal binding strength and group strictly from left to right:
        "<tt>a OR b AND c</tt>" is "<tt>((a OR b) AND c)</tt>". Parentheses are
        the only precedence mechanism. The parser produces one tree in which
        each leaf is an identifier and each interior node is AND or OR with a
        left and a right operand. Implementations MUST use a bounded parser
        and MUST NOT use a general-purpose evaluator.</t>
        <t>The value of the tree is computed over the satisfied type set of
        <xref target="verify"/>: the component types that have at least one
        eligible component. An identifier is true if and only if it equals a
        member of that set by exact comparison of characters, with no case
        folding and no Unicode normalization. An AND node is true when both
        of its operands are true, and an OR node is true when either is.</t>
        <t>Validity is separate from truth. An evaluator MUST validate the
        entire expression, including every operand and parenthesized branch,
        and consume all input before reporting SATISFIED. Boolean
        short-circuiting MUST NOT bypass syntax or configured resource-limit
        validation. A syntactically valid unknown identifier evaluates to
        false; malformed syntax or an exceeded limit makes the evaluation
        UNSATISFIED. The resource limits here are the fixed limits of
        <xref target="expr-limits"/>.</t>
        <t>A valid expression that is false and an invalid expression both
        yield UNSATISFIED, but they are different outcomes, and reason codes
        or diagnostics SHOULD distinguish them. Test vectors for this section
        state syntax validity separately from the Boolean value
        (<xref target="expr-vectors"/>); otherwise a parser that refused
        every expression would pass every test whose expected result is
        UNSATISFIED.</t>
        <t>A relying party's expression is configuration. An evaluator MAY
        validate it when the requirement is configured, before any chain is
        presented, and refuse an invalid requirement there. Such a refusal is
        not an evaluation and produces no replay record.</t>
      </section>

      <section anchor="expr-limits">
        <name>Limits</name>
        <t>The following limits are fixed by this revision and are part of
        the evaluator revision <tt>EP-AEC-EVALUATOR-08-v1</tt>
        (<xref target="replay"/>):</t>
        <dl>
          <dt>Length</dt>
          <dd>At most 4096 octets in the UTF-8 encoding of the expression's
          string value after JSON decoding, whitespace included, so a JSON
          escape sequence counts as the octets of the character it denotes.
          A lone surrogate, which some host languages can hold in a string
          although it is not Unicode text, counts as three octets and is an
          invalid character.</dd>
          <dt>Tokens</dt>
          <dd>At most 256 tokens. Identifiers, operators (including
          "&amp;&amp;" and "||"), and parentheses each count as one token;
          whitespace is not a token. The limit counts tokens, not names: 128
          identifier occurrences joined by 127 operators make 255 tokens, and
          129 occurrences make 257, which exceeds the limit. Distinct
          identifiers, identifier occurrences, component count, and token
          count are different quantities.</dd>
          <dt>Nesting</dt>
          <dd>At most 32 levels of parentheses. The expression outside all
          parentheses is at level 0, and each "(" opens the next level.</dd>
        </dl>
        <t>An expression that exceeds a limit is invalid. When an expression
        is invalid for more than one reason, the reported refusal class
        follows the order in which the input is examined: the length limit;
        then tokenization from left to right, where an invalid character,
        including a single "&amp;" or "|", is a syntax refusal where it is
        met, and a token counts only once it is complete, so that completing
        a 257th token is a limit refusal; then parsing from left to right,
        where a 33rd nesting level is a limit refusal and every other failure
        is a syntax refusal. The refusal class is a diagnostic. Every invalid
        expression yields UNSATISFIED.</t>
        <t>An evaluator MUST apply exactly these limits, neither raising nor
        lowering them. The other resource limits that
        <xref target="acceptance-inputs"/> lists, such as limits on parsing,
        nesting, component count, and verifier execution, are relying-party
        configuration. Such a limit can refuse a requirement or a chain
        regardless of the expression, so it can change which inputs are
        accepted; it MUST therefore be part of the evaluator profile that a
        replay record identifies by its <tt>evaluator_profile_digest</tt>
        (<xref target="replay"/>).</t>
      </section>

      <section anchor="expr-examples">
        <name>Examples</name>
        <t>In <xref target="expr-example-table"/>, "Eligible" is the
        satisfied type set, "Valid" is syntax validity, "n/a" marks a value
        or canonical parse that an invalid expression does not have, and the canonical parse is defined
        in <xref target="parse-identity"/>. Each row is also a vector of the
        corpus in <xref target="expr-vectors"/>.</t>
        <table anchor="expr-example-table">
          <name>Requirement Expression Examples</name>
          <thead>
            <tr><th>Expression</th><th>Eligible</th><th>Valid</th><th>Value</th><th>Canonical parse</th></tr>
          </thead>
          <tbody>
            <tr><td>aORb</td><td>a</td><td>yes</td><td>false</td><td>aORb</td></tr>
            <tr><td>aORb</td><td>aORb</td><td>yes</td><td>true</td><td>aORb</td></tr>
            <tr><td>a OR b</td><td>a</td><td>yes</td><td>true</td><td>(a OR b)</td></tr>
            <tr><td>a OR(b)</td><td>a</td><td>yes</td><td>true</td><td>(a OR b)</td></tr>
            <tr><td>(a)OR(b)</td><td>a</td><td>yes</td><td>true</td><td>(a OR b)</td></tr>
            <tr><td>aOR(b)</td><td>aOR</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>(a)ORb</td><td>a, ORb</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>a ANDb</td><td>a, ANDb</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>and</td><td>and</td><td>yes</td><td>true</td><td>and</td></tr>
            <tr><td>And</td><td>and</td><td>yes</td><td>false</td><td>And</td></tr>
            <tr><td>AND</td><td>AND</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>a or b</td><td>a, b</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>a OR b AND c</td><td>a</td><td>yes</td><td>false</td><td>((a OR b) AND c)</td></tr>
            <tr><td>a OR (b AND c)</td><td>a</td><td>yes</td><td>true</td><td>(a OR (b AND c))</td></tr>
            <tr><td>a OR (b AND)</td><td>a</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>missing AND (b OR)</td><td>none</td><td>no</td><td>n/a</td><td>n/a</td></tr>
            <tr><td>a OR b trailing</td><td>a</td><td>no</td><td>n/a</td><td>n/a</td></tr>
          </tbody>
        </table>
        <t>"<tt>aORb</tt>" is one identifier, so it is false when only
        "<tt>a</tt>" is eligible and true when a component type named
        "<tt>aORb</tt>" is. In "<tt>aOR(b)</tt>" the run "<tt>aOR</tt>" is an
        identifier followed by a group with no operator between them, so the
        expression is invalid; "<tt>(a)ORb</tt>" and "<tt>a ANDb</tt>" fail the
        same way. "<tt>a or b</tt>" is invalid because lowercase "<tt>or</tt>" is
        an identifier, which leaves three adjacent identifiers. Bare
        "<tt>AND</tt>" is an operator with no operands, even when a component
        type named "<tt>AND</tt>" is eligible.</t>
        <t>With only "<tt>a</tt>" eligible, "<tt>a OR b AND c</tt>" is false: it
        groups as "<tt>((a OR b) AND c)</tt>", and "<tt>c</tt>" is not eligible.
        "<tt>a OR (b AND c)</tt>" is true. In "<tt>a OR (b AND)</tt>" and
        "<tt>missing AND (b OR)</tt>", the left operand alone would decide the
        result if the right branch were skipped, but the right branch is
        malformed, so both expressions are invalid.</t>
        <t>At the limits: "<tt>r0 OR r1 OR ... OR r127</tt>", with 128
        identifiers and 255 tokens, is valid. The same expression with a
        trailing "<tt>OR</tt>" has 256 tokens and is a syntax refusal.
        "<tt>r0 OR r1 OR ... OR r128</tt>" has 257 tokens and is a limit
        refusal, and so is a 257-token expression that starts with a
        prefix that would decide the result if the rest were skipped:
        "<tt>a OR</tt>" with "<tt>a</tt>" eligible, or "<tt>missing AND</tt>"
        with no eligible types. Thirty-two nested pairs of parentheses around
        "<tt>a</tt>" are valid, and thirty-three are a limit refusal, also
        after either prefix.</t>
        <t>The parse identity of "<tt>a OR b AND c</tt>" is computed over its
        canonical parse "<tt>((a OR b) AND c)</tt>". It is shown here on two
        lines; the value is one string with no line break:</t>
        <sourcecode type="test-vectors"><![CDATA[
sha256:9c533f1ef06e4240182c300bb12bcae4
       95881c461a54898b6d1f588f83120c1e
]]></sourcecode>
      </section>

      <section anchor="parse-identity">
        <name>Canonical Parse and Parse Identity</name>
        <t>The canonical parse of a valid expression is an ASCII rendering of
        its tree. An identifier renders exactly as written, with its case
        preserved. An AND or OR node renders as "(", its left operand, one
        SP, AND or OR, one SP, its right operand, and ")". The aliases
        "&amp;&amp;" and "||" render as AND and OR. Source parentheses that do
        not change grouping do not appear, but grouping and operand order do:
        operands are never commuted, reassociated, deduplicated, or
        simplified. An invalid expression has no canonical parse.</t>
        <t>The parse identity is the string "sha256:" followed by the
        lowercase hexadecimal SHA-256 digest of the concatenation of three
        octet strings: the ASCII domain separator below, one zero octet, and
        the ASCII canonical parse.</t>
        <sourcecode type="text"><![CDATA[
parse-identity = "sha256:" lowercase-hex( SHA-256(
                   "EP-AEC-EXPRESSION-PARSE-v1" || 0x00 ||
                   canonical-parse ) )
]]></sourcecode>
        <t>The domain separator is versioned; a different canonical form
        would use a different separator.</t>
        <t>An evaluator MUST evaluate the same tree from which it computes the
        canonical parse and parse identity. It MUST NOT compute them from one
        parse and then evaluate the expression text by a separate procedure
        with its own grouping rules.</t>
        <t>The canonical parse and parse identity are interpretation
        diagnostics. They let two implementations, or an implementation and
        the vector corpus, compare how each grouped an expression. A matching
        parse identity does not guarantee matching verdicts. An evaluator can
        compute the correct tree and still evaluate an operator incorrectly,
        match a role without regard to case, or credit a component that is not
        eligible, such as one whose native verification FAILED. Agreement on
        parse identities therefore does not show that two evaluators agree,
        and this document does not claim that every disagreement between
        evaluators is detected.</t>
        <t>The parse identity is not a member of EP-AEC-REQUIREMENT-v1 or
        EP-AEC-REPLAY-v1, and an evaluator MUST NOT add it to either object;
        this revision leaves both member sets unchanged. It does not replace
        the requirement profile digest (<xref target="rp-requirement"/>),
        which commits to the expression exactly as stored. A parse identity
        supplied by anyone other than the relying party carries no authority:
        a presenter that supplies a weaker expression together with that
        expression's parse identity has not changed the relying party's
        requirement.</t>
      </section>

      <section anchor="expr-vectors">
        <name>Test Vectors</name>
        <t>The frozen corpus EP-AEC-EXPRESSION-v1
        <xref target="AEC-EXPRESSION-VECTORS"/> is retrieved from a URL that
        names a fixed commit and is checked against this SHA-256 digest of
        its bytes:</t>
        <sourcecode type="test-vectors"><![CDATA[
927e3663299bd6c11836d4ad22a6dd398b85d16478100921bf68cf03ed459d4b
]]></sourcecode>
        <t>Each of its 104 vectors, 47 valid and 57 invalid, gives an
        expression and the satisfied type set as inputs, and asserts
        separately: syntax validity; for an invalid expression, the refusal
        class (syntax or limit); for a valid expression, the Boolean value;
        the SATISFIED or UNSATISFIED result; and, for a valid expression, the
        canonical parse and the parse identity. The vectors cover every row of
        <xref target="expr-example-table"/>; the four whitespace characters
        and characters that are not whitespace, including those listed in
        <xref target="expr-grammar"/>; operator-like text inside identifiers
        with dots, colons, hyphens, and underscores; the operator aliases;
        grouping; and each limit at, just below, and just beyond its
        threshold, including overflowing branches behind a true OR and a
        false AND.</t>
        <t>The corpus is a test input. An evaluator MUST NOT need it, or fetch
        it, at run time. Producing every assertion in it is necessary for an
        implementation of this section; it is not proof of correctness for
        inputs outside the corpus.</t>
      </section>
    </section>

    <section anchor="verify">
      <name>Verification Algorithm</name>
      <t>Given chain C and the acceptance inputs in
      <xref target="acceptance-inputs"/>, a verifier MUST proceed
      fail-closed:</t>
      <ol>
        <li>Strictly parse C as I-JSON <xref target="RFC7493"/> and enforce all
        configured resource limits. Reject duplicate member names,
        non-integer numbers, malformed Unicode, cycles in an in-memory object,
        and unsupported versions.</li>
        <li>Compute the canonical action digest over C.action. Compare it with
        the executor-owned expected action digest. If C.action_digest is
        present, compare it too. Any mismatch yields UNSATISFIED.</li>
        <li>Validate and digest the relying-party requirement. If the only
        available requirement came from C, yield UNSATISFIED.</li>
        <li>Validate the entire requirement expression under
        <xref target="expressions"/> and produce its one tree: tokenize all
        input, parse every operand and parenthesized branch, consume all
        tokens, and enforce the limits of <xref target="expr-limits"/>. An
        invalid expression yields UNSATISFIED, and no later step can make the
        result SATISFIED. This validation does not depend on which components
        are eligible.</li>
        <li><t>For each component in array order:</t>
          <ol type="a">
            <li>Compute its evidence digest. If a presented evidence digest
            exists and differs, mark the component ineligible.</li>
            <li>Invoke the selected native verifier or consume a trusted
            internal verifier result as constrained by
            <xref target="native-contract"/>, and record the VERIFIED and
            ACCEPTED results separately. Exceptions, unknown verifier types, a
            component whose VERIFIED result could not be evaluated, a
            component that is not VERIFIED, and a VERIFIED component that is
            not ACCEPTED are ineligible.</li>
            <li>Only after VERIFIED and ACCEPTED, establish material-action
            MATCH under <xref target="matching"/>. A different or indeterminate
            action makes the component ineligible.</li>
            <li>If the requirement sets a freshness bound for the component
            type, require protected issuance time, verification time within
            the native validity window, and age not exceeding the bound.
            Future-issued, expired, missing, or malformed times make the
            component ineligible.</li>
            <li>If status is required for the component type, require an
            authenticated, sufficiently fresh status snapshot under the
            selected native profile. Revoked, unknown, stale, or
            unauthenticated status makes the component ineligible.</li>
            <li>Record a normalized fact including component index, type,
            evidence digest, native verifier profile digest, trust snapshot
            digest, the VERIFIED result, the ACCEPTED result, mapping verdict,
            freshness and status results, and only the byte-backed bindings
            returned by the native verifier.</li>
          </ol>
        </li>
        <li>Construct the satisfied type set from eligible components only and
        evaluate the tree produced in step 4 over it. Evaluate every
        <tt>role_constraints</tt> entry over eligible normalized facts only. A
        failed or indeterminate role constraint yields UNSATISFIED.</li>
        <li>For every required binding, require an eligible source and target
        pair with matching types and a source native fact whose named relation
        binds the target's exact evidence digest. A label, component order,
        equal action digest, or presenter's relation claim does not satisfy a
        required binding.</li>
        <li>Return SATISFIED only if the expression is true, every required
        binding exists, and every mandatory check in this algorithm succeeded.
        Otherwise return UNSATISFIED.</li>
        <li>Produce the replay record in <xref target="replay"/>. Any
        unexpected error at any step yields UNSATISFIED and a bounded reason;
        it MUST NOT yield a partial success.</li>
      </ol>
      <t>The result MUST carry <tt>satisfied</tt> as a Boolean and SHOULD carry
      bounded per-component reason codes. Each normalized fact MUST carry the
      VERIFIED and ACCEPTED results as separate fields, and a consumer MUST
      NOT derive one from the other. Reason codes SHOULD distinguish a
      verification failure, a verification that could not be evaluated, an
      acceptance refusal, and a failed material-action match from one
      another. An implementation may
      retain a legacy <tt>allow</tt> alias, but that alias MUST equal
      <tt>satisfied</tt> and MUST NOT be interpreted as local AUTHORIZED.</t>
    </section>

    <section anchor="replay">
      <name>Evidence Evaluation Replay</name>
      <t>An evaluator MUST be able to emit an EP-AEC-REPLAY-v1 record. The
      replay record is an evaluation output, not a presenter input:</t>
      <sourcecode type="json"><![CDATA[
{
  "@version": "EP-AEC-REPLAY-v1",
  "algorithm_revision": "<evaluator algorithm revision>",
  "evaluator_profile_digest": "sha256:<hex>",
  "aec_digest": "sha256:<hex>",
  "expected_action_digest": "sha256:<hex>",
  "expected_caid": "caid:1:<action-type>:<suite>:<digest-b64url>",
  "requirement_profile_digest": "sha256:<hex>",
  "verification_time": "2026-07-27T17:00:00Z",
  "facts": [
    {
      "component_index": 0,
      "type": "ep-quorum",
      "evidence_digest": "sha256:<hex>",
      "native_verification": "VERIFIED",
      "acceptance": "ACCEPTED",
      "mapping_verdict": "MATCH",
      "...": "further normalized fact members"
    }
  ],
  "satisfied": true,
  "reasons": []
}
]]></sourcecode>
      <t>The <tt>algorithm_revision</tt> identifies the evaluation algorithm
      and fact members the evaluator implements. An evaluator implementing
      the algorithm and fact members of this revision of this document sets
      it to the string <tt>EP-AEC-EVALUATOR-08-v1</tt>; a later revision that
      changes either assigns a new value. This revision changes the
      requirement-expression algorithm (<xref target="expressions"/>) and
      keeps the fact members of -07, whose evaluators set
      <tt>EP-AEC-EVALUATOR-07-v1</tt>. Records with different
      algorithm revisions are not compared digest for digest; a record from an
      evaluator implementing -06 of this document carries one combined
      validity member per fact instead of <tt>native_verification</tt> and
      <tt>acceptance</tt>. The <tt>aec_digest</tt> is the evidence digest of
      the complete EP-AEC-v1 object. Facts remain in component array order. Object members
      inside each fact use JCS ordering. The replay digest is the evidence
      digest of the complete EP-AEC-REPLAY-v1 record.</t>
      <t>The <tt>evaluator_profile_digest</tt> identifies the evaluator
      profile that produced the record. It is the evidence digest of a
      description of that profile: the algorithm revision, which fixes the
      expression limits of <xref target="expr-limits"/>; the value of every
      other resource limit it enforces (<xref target="acceptance-inputs"/>);
      and, for each component type with a configured native verifier, the
      native verifier profile, trust snapshot, and mapping profile digests
      and the maximum
      status age the evaluator applies. This document defines neither a
      portable serialization of that description nor a closed list of the
      further normalized fact members, so two implementations compute equal
      replay digests only when they also agree on those.</t>
      <t>In each fact, <tt>native_verification</tt> is <tt>VERIFIED</tt>,
      <tt>FAILED</tt>, or <tt>NOT_EVALUATED</tt>, and <tt>acceptance</tt> is
      <tt>ACCEPTED</tt>, <tt>REJECTED</tt>, or <tt>NOT_EVALUATED</tt>.
      <tt>acceptance</tt> is <tt>NOT_EVALUATED</tt> whenever
      <tt>native_verification</tt> is not <tt>VERIFIED</tt>.
      <tt>native_verification</tt> is <tt>NOT_EVALUATED</tt> when the native
      verifier was not invoked, returned no usable result, or could not
      evaluate VERIFIED because no verification key could be resolved; it is
      <tt>FAILED</tt> only when the checks ran and did not pass.</t>
      <t>The algorithm revision is part of the record, so a new revision
      changes the replay digest even for an expression whose Boolean meaning
      is unchanged. Records move between revisions by re-evaluation, never
      by relabeling:</t>
      <ul>
        <li>A stored record MUST NOT be modified. Its
        <tt>algorithm_revision</tt> MUST NOT be replaced, and its digest MUST
        NOT be recomputed under another revision.</li>
        <li>A replay that is compared with a stored record MUST re-verify the
        original evidence under the identified pins with an evaluator of the
        record's own revision, and MUST compare the complete record by its
        replay digest.</li>
        <li>Re-evaluating the evidence under a different revision produces a
        new, separately identified record. It does not claim digest equality
        with the stored record.</li>
        <li>An evaluator that does not implement a record's revision MUST
        report the comparison as unsupported or refuse it. It MUST NOT compare
        the record as if it had been made under the evaluator's own
        revision.</li>
      </ul>
      <t>Given the same AEC object, expected action inputs, requirement
      profile, evaluator profile, explicit verification time, normalized
      native facts, and algorithm revision, implementations MUST compute the
      same replay digest
      and SATISFIED result. ACCEPTED depends on trust snapshots, and status
      checks depend on status services; therefore the replay record MUST bind
      the selected verifier-profile, trust-snapshot, and status-snapshot
      digests needed to identify those inputs. A party that re-runs the
      evaluation with the same verification keys under different trust inputs
      can reproduce the VERIFIED results but not necessarily the ACCEPTED
      results; the trust-snapshot digests identify whose acceptance the record
      reports. A replay record
      without the underlying evidence and identified trust snapshots can
      identify a decision but cannot independently prove that every recorded
      native fact was true.</t>
      <t>The replay digest is not a signature, authorization, transparency
      receipt, or current-status proof. Another format MAY sign or log it. This
      document intentionally defines no signed reliance-result envelope and no
      legal meaning for a SATISFIED result.</t>
    </section>

    <section anchor="human-leg">
      <name>Human-Authorization Components</name>
      <t>AEC does not infer that a generic operator signature, credential,
      policy decision, or attested workload represents a named-human approval
      ceremony. A relying party that needs an EMILIA human authorization or
      quorum requires <tt>ep-authorization-bundle</tt>, <tt>ep-receipt</tt>, or
      <tt>ep-quorum</tt> explicitly, according to the native artifact's role.</t>
      <t>The <tt>ep-authorization-bundle</tt> component carries the
      pre-execution Authorization Bundle of <xref target="EP-RECEIPTS"/>,
      Section 6. Its native verifier MUST report VERIFIED only when the
      bundle's closed structure, action and context commitments, and
      completed signoff signatures under the keys its signoffs reference
      verify, and MUST report ACCEPTED only when the relying-party-selected
      policy, approver selection, approver keys, their directory status and
      key classes, and required status and presentation evidence are accepted
      under that profile. Whether the bundle's action is the exact expected action is
      established by MATCH under <xref target="matching"/>. Distinct subjects
      MUST come only from verified completed signoffs, not from an unsigned
      label or the wider selected approver roster. A SATISFIED bundle is
      approval evidence, not proof of consumption or execution.</t>
      <t>The <tt>ep-receipt</tt> built-in MUST report VERIFIED only when the
      Trust Receipt's signoff signatures verify under the keys their approver
      key identifiers resolve to and its log checkpoint signature verifies
      under the relying party's pinned log key, which the offline
      verification algorithm of <xref target="EP-RECEIPTS"/>, Section 7.3,
      takes as an input. The checkpoint check therefore combines a trust
      input with cryptography: a checkpoint that does not verify under the
      pinned log key is not VERIFIED (<xref target="native-contract"/>),
      whether it was forged or signed by another log, and without a pinned
      log key VERIFIED cannot be evaluated. The built-in MUST report ACCEPTED
      only for a VERIFIED Trust Receipt that meets a relying-party profile
      pinning the approver directory, accepted key class, WebAuthn RP ID and
      signed-origin allowlist where required, policy hash, maximum evidence
      age, verification time, and fresh registry snapshot as specified by
      <xref target="EP-RECEIPTS"/>. A bare
      operator envelope is not an <tt>ep-receipt</tt> human leg. A terminal
      Trust Receipt and a pre-execution Authorization Bundle MUST NOT be
      substituted for one another. Verifying a consumed receipt does not
      restore authority or permit another execution.</t>
      <t>The <tt>ep-quorum</tt> built-in MUST report VERIFIED only when the
      quorum structure is intact, every member context commits to the quorum
      <tt>action_hash</tt>, and every member signoff verifies under the public
      key that member carries. The built-in MUST report ACCEPTED only when the
      presented quorum policy equals the relying-party-pinned policy and the
      selected approver, role, distinctness, origin, ordering, and freshness
      rules of <xref target="EP-QUORUM"/> hold. A safety-critical profile
      requiring human separation MUST require at least two distinct humans. A
      quorum that is VERIFIED under presenter-selected keys or a weaker
      presenter-selected policy is not ACCEPTED and is ineligible.</t>
      <t>Credential validity and human operation remain distinct. A valid
      credential identifies a key holder under its native profile; it does not
      establish that a human operated an agent for this action, reviewed the
      material fields, or held legal authority.</t>
    </section>

    <section anchor="bounded-capability-leg">
      <name>Bounded-Capability Operation Components</name>
      <t>A static bounded-capability receipt authorizes capability issuance
      and MUST NOT be treated as bound to every later exercise merely because
      the proposed action falls within its scope.</t>
      <t>A <tt>bounded-capability-operation</tt> component is eligible only
      when its operation record is VERIFIED and ACCEPTED and binds the exact
      action, the capability that record references and that capability's
      issuance authorization are each VERIFIED, and ACCEPTED under the
      relying party's pins for its own role, and the native verifier's scope
      result places the operation within that capability. The component is
      not VERIFIED unless the operation record and both referenced artifacts
      are VERIFIED, and not ACCEPTED unless all three are ACCEPTED and the
      native verifier's scope result places the operation within that
      capability. An operation outside the capability's scope is therefore
      not ACCEPTED even when all three artifacts are ACCEPTED. A native
      procedure that checks a referenced artifact's trust inputs and
      cryptography together and cannot attribute a failure falls under the
      rule of <xref target="native-contract"/>. AEC does not query or
      reserve current budget. A capability component MUST NOT satisfy
      <tt>ep-receipt</tt>, <tt>ep-quorum</tt>, or another human role.</t>
    </section>

    <section anchor="aeb-lifecycle">
      <name>Position in the Effect-Boundary Lifecycle</name>
      <t>AEC occupies one deliberately narrow transition in the effect-boundary
      lifecycle described by <xref target="EP-AEB"/>:</t>
      <sourcecode type="text"><![CDATA[
native VERIFIED
  -> relying-party ACCEPTED
  -> material-action MATCH
  -> AEC SATISFIED
  -> local AUTHORIZED
  -> atomic CONSUMED or RESERVED
  -> INVOKED
  -> EXECUTED, FAILED, or INDETERMINATE
]]></sourcecode>
      <t>This document splits the VERIFIED step of that lifecycle into two
      results. An artifact that <xref target="EP-AEB"/> calls VERIFIED, one
      that passed its native verifier under relying-party-selected trust
      inputs, is VERIFIED and ACCEPTED here. FAILED and INDETERMINATE in the
      last line are execution outcomes of <xref target="EP-AEB"/>; they are
      distinct from the <tt>native_verification</tt> value FAILED
      (<xref target="replay"/>) and the CAID verdict INDETERMINATE
      (<xref target="matching"/>).</t>
      <t>AEC can orchestrate native verification, acceptance, and mapping
      itself or consume trusted internal results from the same protected
      boundary. In both arrangements, VERIFIED precedes ACCEPTED, ACCEPTED
      precedes MATCH, and all three precede SATISFIED. AEC MUST NOT collapse
      ACCEPTED into VERIFIED or SATISFIED into AUTHORIZED, consume an
      authorization, invoke an effect, classify an outcome, or reconcile an
      indeterminate effect.</t>
      <t>One-time consumption is stateful and remains at the effect boundary.
      An offline SATISFIED result cannot prove that another executor has not
      already acted. A consequential executor uses shared atomic state keyed
      by an executor-derived action instance and preserves an uncertain
      operation instead of blindly replaying it.</t>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t><strong>Presenter-selected sufficiency.</strong> A presenter can
      construct a weak requirement that its own evidence satisfies. The
      EP-AEC-REQUIREMENT-v1 object MUST come from relying-party configuration.
      C.requirement is descriptive only.</t>
      <t><strong>Presenter-selected action.</strong> Agreement among components
      proves only internal agreement. The expected action digest and CAID must
      be computed or selected by the protected boundary from the action it is
      actually preparing to perform.</t>
      <t><strong>Cross-binding.</strong> An attacker can splice individually
      VERIFIED and ACCEPTED artifacts for different actions. Native verification and
      acceptance before mapping and exact MATCH for each eligible component
      are required. A
      label, shared principal, shared session, or similar-looking parameter is
      not a match.</t>
      <t><strong>Unbacked relations.</strong> A presenter can claim that one
      artifact permits, delegates to, records, or supersedes another. AEC
      credits a relation only when the trusted native verifier extracts the
      target evidence digest and relation from integrity-protected native
      bytes. An unbacked relation never satisfies a required binding.</t>
      <t><strong>Verifier and key-role confusion.</strong> Native verifiers,
      revisions, trust anchors, mapping profiles, and human directories are
      relying-party pins. They MUST NOT be accepted in the same transaction as
      presenter-controlled evidence. A key trusted for one component role
      does not automatically satisfy another role. An artifact signed by a key
      that is not pinned for its role can be VERIFIED; it is never ACCEPTED for
      that role.</t>
      <t><strong>Verification and acceptance.</strong> If trust decisions are
      folded into VERIFIED, a forged or malformed artifact and an intact
      artifact from a signer the relying party does not trust produce the same
      result, and a replay record states more than the relying party's pins
      support. Keeping the results separate lets a later reader who holds the
      evidence and the same verification keys re-derive VERIFIED without
      adopting the original relying party's trust decisions, and keeps
      ACCEPTED attributable to identified trust snapshots. Neither result
      alone makes a component eligible. The separation has limits. An
      unresolvable key reference is recorded as NOT_EVALUATED, not FAILED.
      Where a format does not identify its verification key at all, or a
      native procedure cannot attribute a failure, FAILED does not distinguish
      a forgery from an intact artifact signed under a key the relying party
      does not hold. An artifact bound to a different action is a failed
      MATCH, not a refused acceptance.</t>
      <t><strong>Freshness and status.</strong> Message freshness, artifact
      age, credential validity, credential revocation, authority revocation,
      and policy revision are separate checks. A current credential does not
      make old per-action evidence fresh. A replay record captures the checked
      instant and snapshots; it does not establish current status later.</t>
      <t><strong>Replay overclaiming.</strong> Deterministic replay shows that
      the same normalized inputs produce the same evidence result. It is not a
      refinement proof, a guarantee that a native verifier was correctly
      implemented, or proof that the recorded external status snapshot was
      honest.</t>
      <t><strong>Parser differentials.</strong> Two evaluators that read one
      requirement expression differently can return different results for
      the same evidence. A party that can choose component type names, or
      influence how a relying party writes its expression, can try to use
      such a difference, for example with a type name that one parser keeps
      whole and another splits into an operator and operands, or with a
      character that one parser treats as whitespace and another refuses.
      <xref target="expressions"/> fixes token boundaries, operator case,
      the whitespace set, grouping, whole-input validation, and the limits,
      so that the grammar gives each valid expression one reading, and its
      vector corpus and parse identity let an implementer compare a parser
      with that reading. These measures have limits. A finite corpus can show
      that an implementation is wrong on its vectors, not that it is right
      on every input. A matching parse identity says nothing about how the
      tree was evaluated, how roles were matched, or which components were
      eligible, and it does not detect every disagreement between
      evaluators. Native verifiers, which decide eligibility, remain trusted
      configuration (<xref target="native-contract"/>) and are outside what
      the corpus tests.</t>
      <t><strong>Resource exhaustion.</strong> Implementations MUST bound JSON
      depth, node count, component count, string bytes, expression tokens and
      depth, binding count, native verifier work, and diagnostic output. Any
      bound exceeded is UNSATISFIED.</t>
      <t><strong>Host-language and transport boundaries.</strong> Strict JSON
      parsing must reject duplicate member names before ordinary object
      construction can hide them. AEC inherits the confidentiality and
      integrity properties of its transport. The evidence and frozen action
      passed to later stages must not be mutable after evaluation.</t>
      <t><strong>Signature overclaiming.</strong> A valid signature establishes
      only the signer and statement semantics of the selected native profile.
      It does not inherently prove a natural person's identity, human
      operation, comprehension, legal authority, safety, execution, or
      outcome.</t>
    </section>

    <section anchor="privacy">
      <name>Privacy Considerations</name>
      <t>An AEC bundle can reveal identities, organizational roles,
      destinations, resources, policy choices, and timing. Presenters and
      relying parties SHOULD disclose and retain only evidence needed by the
      selected requirement. A plain digest of low-entropy personal data is not
      anonymization.</t>
      <t>The replay record SHOULD contain normalized facts and content digests,
      not unnecessary raw evidence. Even those facts can reveal relationships
      and decision timing. Access, retention, and correlation controls remain
      deployment responsibilities.</t>
    </section>

    <section anchor="relationship">
      <name>Relationship to Other Work</name>
      <t>CAID <xref target="CAID"/> owns typed material-action identity and
      exact, relying-party-pinned cross-format mapping. AEC uses CAID only
      after native verification and acceptance and does not add trust
      semantics to a CAID.</t>
      <t>Authorization Receipts <xref target="EP-RECEIPTS"/> and Quorum
      <xref target="EP-QUORUM"/> define native human-authorization
      profiles. AEC composes them without generalizing all evidence into
      those formats.</t>
      <t>The earlier Action Evidence Graph draft
      (draft-schrock-ep-action-evidence-graph-00)
      described content-addressed graph references, relying-party evidence
      policy replay, a five-verdict classification, policy packs, and a signed
      reliance result. This revision incorporates the useful composition
      substance into AEC: relying-party-owned evidence requirements,
      content-digested components, byte-backed relations, normalized facts,
      and a replay digest. It intentionally does not adopt the EP-AEG-v1 graph
      envelope, five-verdict taxonomy, policy packs, or signed reliance-result
      format.</t>
      <t>Revision -04 superseded draft-schrock-ep-action-evidence-graph-00 for
      this evidence-composition and replay scope. This revision preserves that
      consolidation.</t>
      <t>Agent Qualification Statements <xref target="EP-QUALIFICATION"/> can be verified as native components
      and can fill a relying-party-named qualification role. Their observation
      and policy-satisfaction claims remain bounded by their native profile;
      qualification MUST NOT be converted into AUTHORIZED without the separate
      boundary decision and controls described by AEB.</t>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions. It creates no universal component,
      relation, verifier, action-mapping, requirement, reason-code, or policy
      registry.</t>
    </section>

    <section anchor="changes-08">
      <name>Changes in -08</name>
      <ul>
        <li>Rewrote Section 8 to make the requirement-expression behavior of
        the -07 reference parsers normative: the longest run of identifier
        characters is taken before the complete run is classified; exact
        uppercase AND and OR are the only word operators and are reserved
        only inside expressions; identifiers and role matching are
        case-sensitive; SP, HTAB, CR, and LF are the only whitespace; the
        ABNF uses case-sensitive strings <xref target="RFC7405"/>. The
        JavaScript reference parser that accompanied -07 and its Python and
        Go ports already agree with every vector of the new corpus on syntax
        validity and Boolean value. The -07 text permitted readings that -08
        refuses.</li>
        <li>Separated validity from truth and required validation of the
        entire expression before SATISFIED, so that short-circuiting cannot
        skip a malformed or over-limit branch (Sections 8.3 and 9).</li>
        <li>Stated the fixed limits and what they count: 4096 UTF-8 octets,
        256 tokens counting identifiers, operators, and parentheses, and 32
        levels of nesting, with a deterministic refusal class (Section 8.4).
        An evaluator applies exactly these limits; the expression size is no
        longer a relying-party resource limit (Section 5). Configured limits
        belong to the evaluator profile.</li>
        <li>Added worked examples (Section 8.5) and a frozen vector corpus
        identified by a commit-pinned URL and a SHA-256 digest
        (Section 8.7).</li>
        <li>Added the canonical parse and parse identity as interpretation
        diagnostics computed from the tree that is evaluated, and stated that
        a matching parse identity does not guarantee matching verdicts
        (Section 8.6).</li>
        <li>Assigned the evaluator revision
        <tt>EP-AEC-EVALUATOR-08-v1</tt>, as Section 10 of -07 requires for an
        algorithm change, and added replay migration rules: stored records are
        never relabeled, a same-revision replay compares the complete record,
        re-evaluation under -08 produces a new record, and an unsupported
        revision is reported or refused (Section 10).</li>
        <li>No wire-format change. EP-AEC-v1, EP-AEC-REQUIREMENT-v1, and
        EP-AEC-REPLAY-v1 keep their versions and member sets; the parse
        identity travels in neither object. Replay digests of -08 records
        differ from those of -07 records because the algorithm revision
        differs.</li>
        <li>The Section 10 record template now shows
        <tt>evaluator_profile_digest</tt>, which the -07 reference evaluator
        already emitted and the -07 template omitted, and says what it
        identifies. Section 10 also states that this document does not define
        a portable serialization of the evaluator profile or a closed list of
        further fact members.</li>
        <li>Section 4 defines the requirement profile digest as the evidence
        digest of the requirement object and states that it covers the
        expression exactly as stored. Section 14 adds parser
        differentials.</li>
        <li>Updated the implementation status, cited CAID -05, and added
        RFC 7405.</li>
      </ul>
    </section>

    <section anchor="changes-07">
      <name>Changes in -07</name>
      <ul>
        <li>Separated VERIFIED from ACCEPTED. In -06, VERIFIED meant that the
        native verifier accepted an artifact under pinned trust inputs, which
        merged the cryptographic result with the relying party's trust
        decision. VERIFIED now means only that the artifact's cryptographic
        and structural checks passed. ACCEPTED is a new, separate result: the
        relying party's pinned trust inputs accept a VERIFIED artifact.</li>
        <li>Native verifiers report both results, never ACCEPTED without
        VERIFIED, and report the artifact as not VERIFIED when a combined
        native procedure cannot attribute a failure. A key resolved from
        relying-party key material makes an artifact checkable, not ACCEPTED;
        a key reference that cannot be resolved is recorded as NOT_EVALUATED,
        not FAILED (Section 6).</li>
        <li>Section 5 lists key-resolution material as its own input and adds
        the key directory and the status of each entry, accepted issuers, key
        classes, native policy, and format revision to the pinned trust inputs
        that decide ACCEPTED.</li>
        <li>Mapping runs only after both results are positive, and eligibility
        requires both. Native verifiers evaluate pins against the action the
        artifact carries, and only MATCH compares it with the expected action
        (Section 7).</li>
        <li>Each normalized fact and replay record carries the two results as
        separate <tt>native_verification</tt> and <tt>acceptance</tt> members,
        the replay record gains <tt>algorithm_revision</tt> (value
        <tt>EP-AEC-EVALUATOR-07-v1</tt> for this revision) and binds
        trust-snapshot digests, and reason codes SHOULD distinguish a
        verification failure, a verification not evaluated, an acceptance
        refusal, and a failed match (Sections 9 and 10).</li>
        <li>Section 11 assigns the built-in checks to the two results and
        states each as a requirement on the result it decides: ep-quorum is
        VERIFIED under the keys its members carry and ACCEPTED under the pinned
        policy; the Authorization Bundle is
        VERIFIED under the keys its signoffs reference; the Trust Receipt is
        VERIFIED under the keys its signoffs reference and, for its log
        checkpoint, under the pinned log key, a combined check under
        Section 6; the Authorization Bundle and Trust Receipt are ACCEPTED
        under the pinned policy, directory, and key classes; the bundle's
        exact action moves from acceptance to MATCH.</li>
        <li>Section 12 requires the capability a bounded-capability operation
        references, and that capability's issuance authorization, each to be
        VERIFIED, and ACCEPTED under the relying party's pins for its own
        role; makes the native verifier's scope result a condition of the
        component's ACCEPTED, so an operation outside the capability is not
        ACCEPTED; and applies the Section 6 rule to a combined check.</li>
        <li>Section 13 adds the relying-party ACCEPTED step to the lifecycle
        and maps the VERIFIED of <xref target="EP-AEB"/> to VERIFIED and
        ACCEPTED here, and distinguishes the lifecycle's execution outcomes
        FAILED and INDETERMINATE from the native verification value and the
        CAID verdict of the same names. Section 14 adds the verification and
        acceptance consideration, including where the separation stops.</li>
        <li>Defined UNSATISFIED explicitly as every result other than
        SATISFIED, including an evaluation that could not complete.</li>
        <li>Updated the implementation status and references.</li>
      </ul>
    </section>

    <section anchor="changes-06">
      <name>Changes in -06</name>
      <ul>
        <li>Added an explicit pre-execution Authorization Bundle component,
        kept separate from the terminal Trust Receipt component.</li>
        <li>Updated implementation status for the structured requirement,
        native facts, role constraints, required bindings, and replay contract.</li>
        <li>Updated references without changing the EP-AEC-v1 envelope or
        converting evidence satisfaction into execution authority.</li>
      </ul>
    </section>

    <section anchor="changes-05">
      <name>Changes in -05</name>
      <ul>
        <li>Added a closed <tt>distinct-subject-quorum</tt> role constraint that
        counts only native-verifier-derived subject identities.</li>
        <li>Made the boundary between evidence sufficiency and AEB authority
        constraints explicit: initiator exclusion, executor exclusion,
        one-time consumption, and execution remain outside AEC.</li>
        <li>Clarified that qualification statements can fill a named evidence
        role but never authorize an action by themselves.</li>
        <li>Updated implementation status and successor references without
        changing the EP-AEC-v1 component envelope.</li>
      </ul>
    </section>

    <section anchor="impl">
      <name>Implementation Status</name>
      <t>The Apache-2.0 JavaScript reference implementation provides
      <tt>createAuthorizationChainEvaluator</tt> for the structured
      EP-AEC-REQUIREMENT-v1 contract. Configuration captures the relying
      party's requirement, native-verifier profiles, trust snapshots, and
      optional action mappings before evaluation. The evaluator implements
      exact expected-action matching, native-derived subject constraints,
      required byte-backed bindings, required freshness and authenticated
      status checks, and EP-AEC-REPLAY-v1 records. Replay re-verifies the
      original evidence under those configuration pins; serialized facts
      are not trusted merely because their digest matches.</t>
      <t>At the time of writing, the latest published release of the
      JavaScript package, @emilia-protocol/verify 6.0.0, implements
      <tt>EP-AEC-EVALUATOR-07-v1</tt>. <tt>EP-AEC-EVALUATOR-08-v1</tt> is
      implemented in the reference repository and is not yet in a published
      release; this draft revision does not by itself imply a released
      package.</t>
      <t>The -08 evaluator parses the relying party's expression once, when
      the evaluator is constructed, and evaluates that tree. It exposes the
      canonical parse, parse identity, and token count as diagnostics outside
      the requirement and replay objects. A malformed expression refuses
      construction, so no replay record is produced for it; the error is
      <tt>aec_requirement_invalid</tt>, or the strict JSON error when the
      requirement is not I-JSON, as with a lone surrogate. A valid
      expression that is false is accepted at construction and evaluates to
      UNSATISFIED. Replay compares
      a stored record only when the record carries
      <tt>EP-AEC-EVALUATOR-08-v1</tt>, by its complete replay digest. It
      reports a record of another revision, including -07, as unsupported
      without modifying it, and always returns a new -08 record. The
      structured result reports <tt>authorization_decision</tt> as false.</t>
      <t>The Python and Go verifier packages implement the Section 8
      expression algorithm and its diagnostics and use it in their legacy
      chain interfaces, also in the reference repository and not yet
      released. They
      do not implement the structured EP-AEC-REQUIREMENT-v1 and
      EP-AEC-REPLAY-v1 contract, and their agreement with the JavaScript
      implementation on the corpus is agreement on expression evaluation
      only. Before this revision, the Go legacy interface trimmed Unicode
      whitespace from a pinned requirement before evaluating it, so a
      requirement made of NO-BREAK SPACE followed by "<tt>a</tt>" was
      evaluated as "<tt>a</tt>"; that is corrected, and the three ports now measure the
      length limit in UTF-8 octets. All three run the corpus of
      <xref target="expr-vectors"/> and agree on every assertion. The
      JavaScript tests also inject faults that keep the parse identity
      unchanged while evaluating an operator wrongly, matching roles without
      regard to case, or crediting a component whose native verification
      FAILED, and reject the resulting wrong verdicts.</t>
      <t>The structured evaluator separates the two results. Native verifier callbacks return separate verified and
      accepted results; every replay fact records native_verification and
      acceptance; a callback result that reports ACCEPTED without VERIFIED, or
      that carries only the earlier combined validity flag, is refused. The
      built-in ep-quorum verifier checks integrity under the public keys a
      quorum carries. The built-in ep-receipt, ep-authorization-bundle, and
      platform-attestation verifiers resolve each key reference from pinned
      key material and check signatures under the resolved key only; a
      reference that cannot be resolved is recorded as NOT_EVALUATED, and the
      directory entry's approver binding, key class, validity period, and
      compromise marker are acceptance inputs. The Trust Receipt checkpoint
      signature is checked under the relying party's log key, so a checkpoint
      that does not verify under that key is FAILED whether it was forged or
      signed by another log. The built-ins evaluate pins against the action
      the artifact carries and leave the expected action to MATCH.</t>
      <t>The older string-requirement API remains a separate legacy interface.
      It does not implement the complete structured contract and keeps one
      combined validity flag per component. The new
      evaluator also dispatches the explicit pre-execution
      <tt>ep-authorization-bundle</tt> component. Evidence satisfaction neither
      authorizes execution nor reserves, consumes, or reconciles authority.</t>
      <t>The associated tests are same-team reference evidence, not an
      independent implementation, a proof of all native verifier profiles, or
      complete deployment mediation. The JavaScript, Python, and Go ports are
      maintained by one team in one repository; their agreement is a
      consistency check, not independent implementation. Custom native verifiers and mapping
      callbacks remain trusted configuration. Input sizes and asynchronous
      verifier work are bounded; untrusted synchronous callback code requires
      separate process or worker isolation.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="BCP14" target="https://www.rfc-editor.org/info/bcp14">
          <front>
            <title>Key Words for Use in RFCs to Indicate Requirement Levels</title>
            <author><organization>Internet Engineering Task Force</organization></author>
            <date year="2017"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
        </reference>
        <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.5234.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7405.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7493.xml"/>
        <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8785.xml"/>
        <reference anchor="CAID" target="https://datatracker.ietf.org/doc/draft-schrock-canonical-action-identifier/">
        <front>
          <title>The Canonical Action Identifier (CAID)</title>
          <author fullname="Iman Schrock"><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="October" day="2"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-schrock-canonical-action-identifier-05"/>
        </reference>
        <reference anchor="EP-RECEIPTS" target="https://datatracker.ietf.org/doc/draft-schrock-ep-authorization-receipts/">
        <front>
          <title>Authorization Receipts for High-Risk Agent Actions</title>
          <author fullname="Iman Schrock"><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="September" day="11"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-schrock-ep-authorization-receipts-13"/>
        </reference>
        <reference anchor="EP-QUORUM" target="https://datatracker.ietf.org/doc/draft-schrock-ep-quorum/">
        <front>
          <title>Multi-Party Quorum Authorization for High-Risk Agent Actions (EP-QUORUM)</title>
          <author fullname="Iman Schrock"><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="September" day="6"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-schrock-ep-quorum-04"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="EP-AEB" target="https://datatracker.ietf.org/doc/draft-schrock-action-evidence-boundary/">
        <front>
          <title>The Action Evidence Boundary for Consequential Agent Effects</title>
          <author fullname="Iman Schrock"><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="September" day="25"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-schrock-action-evidence-boundary-07"/>
        </reference>
        <reference anchor="AEC-EXPRESSION-VECTORS" target="https://raw.githubusercontent.com/emiliaprotocol/emilia-protocol/2ebba2d8439b8e268ba6c3bc2fbbfdd42d2fb318/conformance/vectors/aec-expression.v1.json">
        <front>
          <title>EP-AEC-EXPRESSION-v1 Requirement-Expression Test Vectors</title>
          <author><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="October"/>
        </front>
        <annotation>Frozen corpus at a fixed commit. Its bytes are checked
        against the SHA-256 digest given in Section 8.7, not against the
        URL.</annotation>
        </reference>
        <reference anchor="EP-QUALIFICATION" target="https://datatracker.ietf.org/doc/draft-schrock-agent-qualification-statements/">
        <front>
          <title>Portable Agent Qualification Statements for Consequential Actions</title>
          <author fullname="Iman Schrock"><organization>EMILIA Protocol, Inc.</organization></author>
          <date year="2026" month="July" day="27"/>
        </front>
        <seriesInfo name="Internet-Draft" value="draft-schrock-agent-qualification-statements-00"/>
        </reference>
      </references>
    </references>
    <section anchor="acknowledgments" numbered="false">
      <name>Acknowledgments</name>
      <t>Review of adjacent work sharpened the separation among native
      verification, relying-party acceptance, cross-format action mapping, evidence satisfaction, local
      authorization, credential status, human operation, and effect truth.
      Acknowledgment does not imply endorsement.</t>
    </section>
  </back>
</rfc>
