Skip to main content

The Canonical Action Identifier (CAID)
draft-schrock-canonical-action-identifier-00

Document Type Active Internet-Draft (individual)
Author Iman Schrock
Last updated 2026-07-19
RFC stream (None)
Intended RFC status (None)
Formats
Additional resources CAID reference implementations, registry, and conformance vectors
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-schrock-canonical-action-identifier-00
Network Working Group                                         I. Schrock
Internet-Draft                                     EMILIA Protocol, Inc.
Intended status: Informational                              19 July 2026
Expires: 20 January 2027

                 The Canonical Action Identifier (CAID)
              draft-schrock-canonical-action-identifier-00

Abstract

   Authorization, delegation, execution, and audit artifacts often
   identify an action using format-local content and digests.  Those
   digests are not directly comparable when the formats select or encode
   material action fields differently.  This document defines the
   Canonical Action IDentifier (CAID): a typed action object, a
   canonicalization and digest suite, a compact identifier string, and
   immutable action-type definitions with required material fields.  It
   also defines an Action-Mapping Profile for projecting independently
   verified native artifacts into a common action type, with the closed
   results EQUIVALENT_UNDER_PROFILE, NOT_EQUIVALENT, and INDETERMINATE.
   CAID carries no trust semantics.  It does not establish identity,
   authority, authorization, execution, safety, or legal reliance.

Status of This Memo

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

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

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

   This Internet-Draft will expire on 20 January 2027.

Copyright Notice

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

Schrock                  Expires 20 January 2027                [Page 1]
Internet-Draft                    CAID                         July 2026

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
     1.1.  Terminology . . . . . . . . . . . . . . . . . . . . . . .   3
   2.  The Action Object . . . . . . . . . . . . . . . . . . . . . .   4
   3.  Suites and the Identifier . . . . . . . . . . . . . . . . . .   5
     3.1.  Suites  . . . . . . . . . . . . . . . . . . . . . . . . .   5
     3.2.  The Digest  . . . . . . . . . . . . . . . . . . . . . . .   5
     3.3.  Identifier Syntax . . . . . . . . . . . . . . . . . . . .   6
     3.4.  Parsing . . . . . . . . . . . . . . . . . . . . . . . . .   7
     3.5.  Equality  . . . . . . . . . . . . . . . . . . . . . . . .   7
   4.  Action Types and the Registry . . . . . . . . . . . . . . . .   7
     4.1.  Type Names and Versioning . . . . . . . . . . . . . . . .   8
     4.2.  The Type Definition Schema  . . . . . . . . . . . . . . .   8
     4.3.  Field Types . . . . . . . . . . . . . . . . . . . . . . .   9
     4.4.  Definition Sources and Unknown Types  . . . . . . . . . .  10
   5.  Computation . . . . . . . . . . . . . . . . . . . . . . . . .  10
   6.  Verification  . . . . . . . . . . . . . . . . . . . . . . . .  11
   7.  Action-Mapping Profile  . . . . . . . . . . . . . . . . . . .  11
     7.1.  Native Verification Boundary  . . . . . . . . . . . . . .  12
     7.2.  Mapping Profile Object  . . . . . . . . . . . . . . . . .  12
     7.3.  Mapping and Comparison Algorithm  . . . . . . . . . . . .  14
     7.4.  Completeness Assumption . . . . . . . . . . . . . . . . .  15
   8.  What a CAID Is Not  . . . . . . . . . . . . . . . . . . . . .  15
   9.  Security Considerations . . . . . . . . . . . . . . . . . . .  16
   10. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  18
   11. References  . . . . . . . . . . . . . . . . . . . . . . . . .  18
     11.1.  Normative References . . . . . . . . . . . . . . . . . .  18
     11.2.  Informative References . . . . . . . . . . . . . . . . .  19
   Appendix A.  Acknowledgments  . . . . . . . . . . . . . . . . . .  20
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  20

1.  Introduction

   Many formats for permits, receipts, mandates, delegation, and outcome
   evidence reference "the action" by digest.  Each format selects an
   action representation and canonicalization appropriate to its own
   protocol.  The resulting identifiers are useful inside that format
   but are not necessarily comparable across formats.

Schrock                  Expires 20 January 2027                [Page 2]
Internet-Draft                    CAID                         July 2026

   This creates two interoperability risks.  The first is the material-
   fields failure: a digest over an underspecified object can omit the
   facts a relying party considers material.  A digest computed over
   {"action": "wire"} commits to no amount, no currency, and no
   beneficiary; the artifact carrying it looks cryptographically bound
   to an action while committing to nothing that makes the action
   consequential.  The second is the join failure: absent an agreed
   common definition, two artifacts about the same action, issued by
   different systems in different formats, can carry digests that cannot
   be compared without an explicit, reviewable mapping.

   This document defines the Canonical Action IDentifier (CAID) to close
   both gaps.  A CAID names typed content: an action object that
   declares its own type, carries every material field that type
   requires, is canonicalized under a registered suite, and is digested.
   The identifier is a compact string embedding the version, the action
   type, the suite, and the digest.  When formats cannot emit the same
   action object, an Action-Mapping Profile (Section 7) defines a
   relying-party-pinned, loss-aware projection into the common type and
   abstains when the comparison cannot be made.

   As informative examples of the artifact classes that can carry a
   CAID: authorization receipts [I-D.schrock-ep-authorization-receipts],
   permit receipts [I-D.lee-orprg-permit-receipts], and execution
   outcome attestations [I-D.morrow-sogomonian-exec-outcome-attest] each
   reference an action by digest and could carry a CAID in place of or
   alongside their existing action reference.  These citations are
   examples only; this document neither depends on nor modifies any of
   them, and carrying a CAID changes nothing about how any such artifact
   is verified.

   A CAID deliberately carries no trust semantics.  It does not assert
   that an action was authorized, executed, safe, or wise.  Section 8
   states the boundary normatively.

1.1.  Terminology

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

   Action object:  The typed data object, defined in Section 2, over
      which a CAID's digest is computed.

   Action type:  A versioned type name whose definition (Section 4)

Schrock                  Expires 20 January 2027                [Page 3]
Internet-Draft                    CAID                         July 2026

      declares the material fields an action object of that type is
      required to carry.

   Material field:  A field that a type definition declares REQUIRED
      because its absence would leave the digest uncommitted to
      something that makes the action consequential.

   Suite:  A registered pairing of a canonicalization scheme and a
      digest algorithm (Section 3.1).

   Definition source:  A collection of type definitions in the schema of
      Section 4.2 that an implementation is configured with: the public
      registry, a local definitions file, or both.

   Issuer:  The party that constructs an action object and computes its
      CAID.

   Verifier:  The party that checks a presented CAID against a presented
      action object by recomputation (Section 6).

   Mapping profile:  A hash-identified projection, pinned by the relying
      party, from one exact source format and version into one CAID
      action type (Section 7).

   Native verifier:  The verifier defined by a source artifact's own
      specification.  Native verification precedes mapping and is
      outside the CAID trust boundary.

2.  The Action Object

   An action object is a JSON object (or, under a CBOR suite, a CBOR
   map) that identifies material action content.  The same object is
   referenced, by CAID, from pre-execution artifacts (permits,
   challenges, receipts) and post-execution artifacts (outcome
   attestations, audit records, reliance events).

   An action object:

   *  MUST contain an action_type member whose value is a registered or
      locally defined versioned type name (Section 4).  The type is
      inside the digested content, so the type asserted by an identifier
      cannot be swapped without changing the digest.

   *  MUST contain every REQUIRED material field of that type, encoded
      per the field types the type definition declares (Section 4.3).

   *  MAY contain additional members beyond those the type definition
      declares.  Extra members are covered by the digest.

Schrock                  Expires 20 January 2027                [Page 4]
Internet-Draft                    CAID                         July 2026

   *  MUST NOT encode money or quantity values as JSON numbers where the
      type definition declares the field amount-string.  Floating-point
      and precision malleability across languages makes numeric
      encodings of money unsafe for canonicalization.

   *  Numbers follow a value-based rule: a JSON number is accepted if
      and only if its IEEE 754 double-precision value is an integer with
      magnitude at most 2^53-1, and it is serialized as that integer in
      plain decimal form.  The literal form is irrelevant: the literals
      1e3 and 2.0 denote the integers 1000 and 2, exactly as an
      ECMAScript JSON parser sees them.  Fractional, NaN, infinite, and
      out-of-range values are refused as unsupported_number by every
      conforming implementation, at any depth.  Fractional quantities
      are carried as strings.  Rationale: ECMAScript number
      serialization is the leading source of cross-language
      canonicalization divergence, and a rule over the parsed value is
      the only one that every language can implement identically; a rule
      over the literal form cannot be enforced by implementations, such
      as ECMAScript, whose JSON parsers do not preserve it.

3.  Suites and the Identifier

3.1.  Suites

   A suite names a canonicalization scheme and a digest algorithm.  This
   document defines two suites; the suite registry (Section 10) carries
   one entry per suite.

   jcs-sha256:  The JSON Canonicalization Scheme [RFC8785] followed by
      SHA-256 [RFC6234].  Support for this suite is REQUIRED for
      conforming implementations.

   cbor-sha256:  CBOR core deterministic encoding (Section 4.2 of
      [RFC8949]) followed by SHA-256 [RFC6234].  This suite is defined
      in this version; implementations MAY support it.

3.2.  The Digest

   The digest is computed directly over the canonical bytes of the
   action object:

   digest = SHA-256(canonical_bytes(action_object))

   There is deliberately NO domain separation prefix.  The object is
   self-typed via its action_type member, and a design goal of CAID is
   that existing artifact formats can adopt the identical digest they
   may already compute over canonical bytes.  Conforming verifiers MUST
   check that the in-object action_type equals the action type carried

Schrock                  Expires 20 January 2027                [Page 5]
Internet-Draft                    CAID                         July 2026

   in the CAID string (Section 6); that check, not a byte prefix, is
   where cross-context reinterpretation dies.  Section 9 states this
   trade explicitly.

3.3.  Identifier Syntax

   The identifier is a compact string:

   caid:1:<action_type>:<suite>:<digest-b64url>

   For example:

   caid:1:payment.release.1:jcs-sha256:qL8R4QIcQ_ZsRqOAbeRfcZhilN_MksRt
   DaErMPJk0vM

   (The example digest is shown wrapped for column width; the identifier
   itself contains no whitespace.)

   The grammar, in the ABNF of [RFC5234]:

   caid          = "caid:" caid-version ":" action-type ":"
                   suite ":" digest

   caid-version  = "1"

   action-type   = 1*( name-segment "." ) type-version
   name-segment  = lower-char *( lower-char / DIGIT / "-" )
   type-version  = pos-int
   pos-int       = %x31-39 *DIGIT   ; positive integer, no leading zero

   suite         = lower-char *( lower-char / DIGIT / "-" )

   digest        = 1*b64url-char
   b64url-char   = %x41-5A / %x61-7A / DIGIT / "-" / "_"
                                    ; A-Z / a-z / 0-9 / "-" / "_"

   lower-char    = %x61-7A          ; a-z

   DIGIT is the core rule of [RFC5234].

   caid-version is the version of this identifier syntax and is "1" for
   this document. action-type is one or more lowercase dotted name
   segments followed by a final segment that is the integer version of
   the type (for example, payment.release.1).  suite is a name from the
   suite registry, lowercase. digest is the digest encoded in base64url
   (Section 5 of [RFC4648]), unpadded and case-sensitive; for the two
   suites defined here the digest is exactly 43 characters, encoding 32
   octets.

Schrock                  Expires 20 January 2027                [Page 6]
Internet-Draft                    CAID                         July 2026

3.4.  Parsing

   Parsers are strict.  A conforming parser:

   *  MUST refuse base64url padding characters ("=") in the digest.

   *  MUST refuse uppercase characters in the action-type or suite
      fields.  The digest field is case-sensitive and both cases are
      significant there.

   *  MUST refuse empty segments anywhere in the string, including empty
      dotted segments within the action type.

   *  MUST refuse any content after the digest, including trailing
      separators, whitespace, or additional fields.

   *  MUST refuse a digest that does not decode to exactly the digest
      length of the named suite, or whose final character encodes
      nonzero unused bits.

   *  MUST treat an unknown caid-version as a refusal, never as a value
      to be guessed at or parsed leniently.

   *  MUST treat an unknown suite as a refusal, never as a suite to be
      guessed.

3.5.  Equality

   Two CAIDs are equal if and only if their strings are byte-equal.
   Cross-suite equivalence is out of scope: no procedure in this
   document relates a jcs-sha256 CAID to a cbor-sha256 CAID for the same
   object.  An artifact MAY carry multiple CAIDs for one action, one per
   suite its issuer computed.

   Direct CAID equality is content equality, not inferred semantic
   equality.  The strings "1.50" and "1.5" are different content and
   yield different digests.  Per-field normalization guidance lives in
   the type definition's digest_notes (Section 4.2), and normalization
   is the issuer's job: the issuer normalizes before computing the CAID,
   and no party renormalizes afterward.

   When two native formats cannot produce byte-equal action objects, the
   Action-Mapping Profile in Section 7 provides a narrower result:
   equivalence of the material projection under exact profiles pinned by
   a relying party.  It does not claim general semantic equivalence.

4.  Action Types and the Registry

Schrock                  Expires 20 January 2027                [Page 7]
Internet-Draft                    CAID                         July 2026

4.1.  Type Names and Versioning

   An action type name is one or more lowercase dotted name segments
   with a final segment that is the integer version of the type, per the
   action-type rule of Section 3.3.  Registered types live in the CAID
   action type registry (Section 10), one entry per versioned type.

   Once a version is active, every declaration that affects validation
   or material meaning is immutable.  Adding or removing a required or
   optional field, retyping a field, changing an enum set or
   normalization rule, or changing a field's semantics MUST be published
   as a new version of the type (payment.release.2), never as an in-
   place edit.  This immutability is required so a later verifier can
   reproduce an earlier result.

4.2.  The Type Definition Schema

   The entry schema below is normative, and it is normative for local
   definitions too: a private deployment carries its own definitions in
   this same schema (Section 4.4).

   {
     "action_type": "payment.release.1",
     "status": "active",
     "risk_class": "irreversible-financial",
     "summary": "Release of a payment instruction to settlement.",
     "required_fields": [
       {"name": "amount", "type": "amount-string",
        "notes": "decimal string, no exponent, no leading '+',
                  no thousands separators"},
       {"name": "currency", "type": "enum",
        "values_ref": "ISO 4217 alpha-3"},
       {"name": "beneficiary_account", "type": "digest",
        "notes": "sha256:<lowercase hex> of the normalized account
                  identifier; normalization stated by the issuing
                  system of record"},
       {"name": "payment_instruction_id", "type": "string"}
     ],
     "optional_fields": [
       {"name": "memo", "type": "string"}
     ],
     "digest_notes": "amounts never renormalized after signing; the
                      system of record's form is canonical",
     "references": []
   }

Schrock                  Expires 20 January 2027                [Page 8]
Internet-Draft                    CAID                         July 2026

   action_type is the versioned type name. status is the lifecycle state
   of the entry. risk_class is a descriptive label for the consequence
   class of the action; it carries no verification semantics.
   required_fields declares the material fields, each with a name, a
   field type from Section 4.3, and optional notes or a values_ref
   naming an external value set. optional_fields declares fields the
   type recognizes but does not require.  digest_notes carries per-type
   normalization guidance for issuers. references carries citations for
   the type's semantics.

4.3.  Field Types

   The set of field types in version 1 is closed:

   string:  A JSON string.

   amount-string:  A decimal amount carried as a string: an optional
      leading "-", one or more digits, and an optional "." with one or
      more digits.  No exponent, no leading "+", no thousands
      separators.

   digest:  The literal prefix "sha256:" followed by 64 lowercase
      hexadecimal characters.  Used where a raw identifier must not
      appear in the object (Section 9).

   enum:  A string constrained to a value set named by the field's
      values_ref.

   timestamp:  An RFC 3339 [RFC3339] timestamp in UTC with the "Z"
      designator.

   integer:  A JSON integer.  For counts only, never for money.

   boolean:  A JSON boolean.

   object:  A JSON object, itself subject to the number restriction of
      Section 2.

   array:  A JSON array, itself subject to the number restriction of
      Section 2.

Schrock                  Expires 20 January 2027                [Page 9]
Internet-Draft                    CAID                         July 2026

4.4.  Definition Sources and Unknown Types

   There is no reserved private-use name syntax.  The distinction
   between registered and local types is presence: a type is either
   present in a definition source the implementation is configured with
   (the public registry, or a local definitions file in the same schema)
   or it is unknown.  A deployment inside a single vendor's boundary can
   therefore use CAID with purely local definitions.  Cross-domain use
   requires the parties to pin the same exact definition or registry
   snapshot.  A local definition that collides by name with a different
   registered definition MUST NOT be treated as interoperable.

   An unknown type is a refusal for a conforming issuer (Section 5).
   For a verifier, accepting an identifier whose type is unknown is a
   policy decision: a verifier MAY offer an accept-unregistered option,
   and that option MUST default to off.

5.  Computation

   A conforming issuer computes a CAID from an action object, a suite,
   and its configured definition sources, in the following order.  Each
   check that fails contributes a refusal reason from the closed set
   below; the reason strings are normative.

   1.  The action_type member is present and its value matches the
       action-type grammar of Section 3.3, else invalid_action_type.

   2.  The type is resolvable in the configured definition sources, else
       unknown_action_type.

   3.  Every REQUIRED field of the type definition is present, else
       missing_material_field:<name> for each absent field.

   4.  Every present field that the type definition declares is valid
       for its declared field type, else mistyped_field:<name> for each
       violation.  An amount-string violation MAY be refined to
       invalid_amount:<name>.

   5.  The requested suite is known, else unknown_suite.

   6.  Every number in the object, at any depth, satisfies the value-
       based rule of Section 2 (an integer with magnitude at most 2^53-1
       after IEEE 754 double-precision parsing), else
       unsupported_number.

   7.  Canonicalize under the suite, digest, and emit the CAID string
       and the digest.

Schrock                  Expires 20 January 2027               [Page 10]
Internet-Draft                    CAID                         July 2026

   On success the issuer emits the identifier and the digest.  On any
   failure the issuer emits the accumulated refusal reasons and NO
   identifier.  Computation is fail-closed: malformed or junk input, of
   any shape, yields refusal reasons, never an exception or a partial
   identifier.

6.  Verification

   A conforming verifier checks a presented CAID string against a
   presented action object, using its own configured definition sources,
   in the following order:

   1.  Strict-parse the CAID string per Section 3.4, else
       malformed_caid.

   2.  The in-object action_type equals the action type carried in the
       CAID string, else action_type_mismatch.  This check is mandatory;
       see Section 3.2 and Section 9.

   3.  Recompute the digest over the presented object under the suite
       named in the CAID; the recomputed digest is equal to the
       presented digest, else digest_mismatch.

   4.  Run the same material validation as computation (Section 5, steps
       1 through 6).  An identifier whose object fails that validation
       is invalid_object, not merely mismatched: a digest that matches
       an invalid object still binds nothing material.

   The result is a validity bit and the list of reasons.  Verification
   is deterministic and offline: the same inputs produce the same
   reasons in the same order, and any third party with the object, the
   identifier, and the definitions can replay the check without
   contacting anyone.

7.  Action-Mapping Profile

   Two native formats can represent the same material action with
   different member names, nesting, or format-local metadata.  Direct
   digest comparison cannot establish whether those representations
   denote the same material action.  This section defines a narrow,
   explicit projection into a common CAID action type.  The projection
   is identified by its digest and pinned by the relying party.

   A mapping result is content correlation only.  It does not establish
   identity, authority, authorization, provenance, execution, or legal
   reliance.

Schrock                  Expires 20 January 2027               [Page 11]
Internet-Draft                    CAID                         July 2026

7.1.  Native Verification Boundary

   Before mapping, each source artifact MUST be verified under its
   native specification and the relying party's native trust anchors.
   The source object supplied to the mapper MUST be the payload whose
   integrity that native verification established, or a projection for
   which the native adapter has established that every mapped source
   field is covered by the native integrity mechanism.  A mapper MUST
   NOT read an unsigned sibling member and treat it as part of a signed
   payload.

   The source media type, schema identifier, and version supplied to the
   mapper MUST come from relying-party configuration or the native
   verifier.  They MUST NOT be accepted solely from a label inside the
   presenter-controlled artifact.  CAID mapping does not replace native
   verification.

   The mapping interface MUST receive an affirmative native verification
   result through a relying-party-controlled adapter or equivalent
   trusted call path.  That result is an API precondition, not a member
   a presenter can place in the artifact.  A missing or negative native-
   verification result yields INDETERMINATE.

7.2.  Mapping Profile Object

   A version 1 profile is a JSON object with the following shape:

Schrock                  Expires 20 January 2027               [Page 12]
Internet-Draft                    CAID                         July 2026

   {
     "@version": "CAID-MAPPING-PROFILE-v1",
     "profile_id": "urn:example:map:checkout-to-order:1",
     "source_format": {
       "media_type": "application/example-checkout+json",
       "schema": "urn:example:checkout:1",
       "version": "1"
     },
     "target_action_type": "order.place.1",
     "loss_policy": "no-material-field-loss",
     "material_source_paths": [
       "/checkout/order_id",
       "/checkout/merchant_id",
       "/checkout/total_amount",
       "/checkout/currency",
       "/checkout/line_items",
       "/checkout/customer_id",
       "/checkout/fulfillment"
     ],
     "rules": [
       {"source_path": "/checkout/order_id",
        "target_field": "order_id", "transform": "copy"},
       {"source_path": "/checkout/merchant_id",
        "target_field": "merchant_ref", "transform": "sha256-utf8"},
       {"source_path": "/checkout/total_amount",
        "target_field": "total_amount", "transform": "copy"},
       {"source_path": "/checkout/currency",
        "target_field": "currency", "transform": "copy"},
       {"source_path": "/checkout/line_items",
        "target_field": "items_digest", "transform": "sha256-jcs"},
       {"source_path": "/checkout/customer_id",
        "target_field": "customer_ref", "transform": "sha256-utf8"},
       {"source_path": "/checkout/fulfillment",
        "target_field": "fulfillment_ref", "transform": "sha256-jcs"}
     ]
   }

   The profile digest is the lowercase hexadecimal SHA-256 digest of the
   profile's JCS serialization, prefixed with "sha256:".  The relying
   party MUST pin that exact digest.  A profile identifier by itself is
   not a trust anchor.

   Version 1 is a closed object model.  A mapper MUST reject an unknown
   member in the top-level profile, source_format object, or rule
   object.  This prevents a misspelled or future policy member from
   being covered by the profile digest while being silently ignored by
   the mapping algorithm.

Schrock                  Expires 20 January 2027               [Page 13]
Internet-Draft                    CAID                         July 2026

   source_format binds the exact media type, schema identifier, and
   version accepted by the profile. target_action_type names a type from
   a definition source pinned by the relying party.  loss_policy MUST be
   "no-material-field-loss" in version 1.  source_path values are JSON
   Pointers [RFC6901].  Every material_source_paths entry MUST have
   exactly one rule, and every REQUIRED field of the target action type
   MUST be the target of exactly one rule.  Duplicate target fields,
   malformed pointers, missing fields, and unknown transforms are
   mapping failures.

   The version 1 transform set is closed:

   copy:  Copy the source value after confirming that it has a
      conforming JCS representation.

   sha256-utf8:  For a source string, emit "sha256:" followed by the
      lowercase hexadecimal SHA-256 digest of its UTF-8 bytes.

   sha256-jcs:  Emit "sha256:" followed by the lowercase hexadecimal
      SHA-256 digest of the source value's JCS representation.

   A mapper MUST refuse an unregistered transform.  Version 1 performs
   no unit conversion, currency conversion, date inference, case
   folding, or lossy normalization.

7.3.  Mapping and Comparison Algorithm

   For each source, a conforming mapper:

   1.  Requires an affirmative native-verification result from the
       trusted adapter.

   2.  Validates the complete profile shape and closed transform set.

   3.  Recomputes the profile digest and compares it to the relying-
       party pin.

   4.  Compares the verifier-derived source descriptor to the profile's
       source_format object.

   5.  Confirms one-to-one coverage of material source paths and all
       REQUIRED target fields.

   6.  Computes a source digest over the complete source object for
       reproducibility.

   7.  Extracts and transforms every rule.  A missing path or mistyped
       value is a mapping failure.

Schrock                  Expires 20 January 2027               [Page 14]
Internet-Draft                    CAID                         July 2026

   8.  Computes a CAID for the projected action under Section 5.

   Comparison of two mapping results returns exactly one of:

   EQUIVALENT_UNDER_PROFILE:  Both mappings succeeded, both target the
      same action type, and the resulting CAID strings are byte-equal.

   NOT_EQUIVALENT:  Both mappings succeeded and target the same action
      type, but the resulting CAIDs differ.

   INDETERMINATE:  Either native verification did not succeed, either
      mapping failed, either profile was not pinned, a source descriptor
      differed, a target action type differed, or any required fact was
      absent or ambiguous.

   A consumer MUST NOT convert INDETERMINATE into equivalence.  It also
   MUST NOT treat EQUIVALENT_UNDER_PROFILE as authorization.
   Authorization remains a separate relying-party decision over
   separately verified evidence.

   For reproducibility, each successful per-source mapping result MUST
   carry the complete source-object digest, mapping-profile digest,
   projected action object, resulting CAID, and suite.  A comparison
   result MUST retain both per-source mapping results.  A consumer that
   persists or transmits only the final verdict or CAID loses the
   information needed to reproduce which profiles and source objects
   produced that result.

7.4.  Completeness Assumption

   The algorithm proves that a pinned profile maps every field the
   target action type declares material.  It cannot prove that the
   profile author correctly identified every material concept in the
   native source schema.  The relying party's selection and review of
   mapping profiles is therefore an explicit policy assumption.
   Profiles SHOULD be versioned, publicly reviewable, and accompanied by
   positive, negative, and indeterminate conformance vectors.

8.  What a CAID Is Not

   Under the selected suite's security assumptions, recomputing a CAID
   establishes that an identifier commits to the supplied canonical
   typed content.  Comparing CAIDs emitted directly from the same action
   type, or emitted through pinned Action-Mapping Profiles, provides the
   scoped matching result defined here.  It does not prove that the
   action was authorized, executed, safe, or wise.  It confers no trust,
   names no humans, and replaces no verifier: every artifact that
   carries a CAID still verifies inside its own trust boundary under its

Schrock                  Expires 20 January 2027               [Page 15]
Internet-Draft                    CAID                         July 2026

   own specification, exactly as it did before carrying one.

   In particular:

   *  A CAID is not authorization.  Possession of an identifier, or of
      the object it digests, authorizes nothing.

   *  A capability scope can name one or more CAIDs as exact content
      constraints.  The capability's signature, issuer trust, holder
      proof, budget state, and local policy create that authorization
      context; the CAIDs themselves still grant nothing.

   *  A capability grant, a narrowing delegation, and each capability
      exercise are different material actions and can have separate
      CAIDs.  Equality or EQUIVALENT_UNDER_PROFILE does not establish
      that an exercise falls within a grant.  Scope containment,
      attenuation, remaining budget, and permission to act are evaluated
      by the capability protocol under relying-party-selected inputs.

   *  A CAID is not identity.  It names content, not any human, agent,
      workload, or organization.

   *  A CAID is not proof of execution or of outcome.  An artifact
      asserting execution proves that under its own specification, or
      not at all.

   *  Composition joins on the identifier and never ingests another
      verifier's evidence.  When two artifacts about one action are
      composed, the join key is the CAID; each leg's evidence is
      verified by that leg's own verifier under that leg's own trust
      anchors, and no verifier imports another's conclusions into its
      own trust boundary.

9.  Security Considerations

   Digest strength.  The binding between an identifier and its content
   rests on the second-preimage resistance of SHA-256.  If SHA-256
   weakens, the migration path is suite agility: a new suite is
   registered and issuers move to it, emitting new identifiers.  There
   is no in-place algorithm change within a suite, ever.

Schrock                  Expires 20 January 2027               [Page 16]
Internet-Draft                    CAID                         July 2026

   No domain separation.  The digest input carries no domain separation
   prefix, deliberately, so that existing formats can adopt a digest
   they may already compute over canonical bytes (Section 3.2).  The
   compensating control is mandatory: verifiers MUST enforce the check
   that the in-object action_type equals the type carried in the CAID
   string.  Skipping that check re-opens cross-context reinterpretation,
   in which bytes canonicalized for one context are presented under a
   type label from another.  The check is step 2 of Section 6 and is not
   optional.

   Personally identifiable information.  Action objects, CAIDs, and
   their correlations should be assumed to travel and to appear in logs.
   A plain SHA-256 digest of a low-entropy identifier is pseudonymous,
   not anonymous: an observer can test likely account, patient, or order
   identifiers by dictionary attack.  The digest field type keeps raw
   values out of the action object but does not by itself provide
   confidentiality or unlinkability.  Type authors handling personal
   data SHOULD prefer high-entropy opaque references or a deployment-
   specific privacy-preserving commitment scheme, document its
   normalization and correlation scope, and avoid placing unnecessary
   personal data in the action object.  A deployment-specific scheme can
   require an explicit mapping profile for cross-domain joins.

   Canonicalization malleability.  Cross-language number serialization
   is the historical source of canonicalization divergence, which is why
   numbers are restricted to the value-based integer rule and money is
   carried as amount-string (Section 2).  JCS and CBOR core
   deterministic encoding are the only permitted canonical forms; no
   other serialization, however stable it appears, is a conforming
   digest input.

   A CAID is not a capability.  Possession of an identifier proves
   nothing and grants nothing.  Identifiers SHOULD be treated as public
   values: they may appear in logs, URLs, and audit records without
   weakening anything.  Protocols MUST NOT treat knowledge of a CAID as
   evidence of anything beyond knowledge of the object's content.

   Profile-bounded equivalence.  Direct CAID verification does not infer
   semantic equality.  The Action-Mapping Profile makes only a narrower
   statement about material projections under exact pinned profiles.  A
   malicious or incomplete profile can omit a concept that the relying
   party should have considered material.  Profile selection is
   therefore a relying-party policy decision; unpinned, lossy, or
   ambiguous mappings MUST yield INDETERMINATE.

Schrock                  Expires 20 January 2027               [Page 17]
Internet-Draft                    CAID                         July 2026

   Native integrity coverage.  A valid native signature does not make
   unsigned members beside the signed payload trustworthy.  A native
   adapter MUST establish that every mapped field is covered by the
   native integrity mechanism.  The source descriptor is verifier-
   derived, not presenter-asserted (Section 7.1).

   Definition stability.  A versioned action-type definition is
   immutable once active.  Cross-domain verifiers MUST pin an exact
   definition source or registry snapshot.  A local and a registered
   definition that share a name but differ in validation semantics MUST
   NOT be treated as the same type.

   Duplicate object member names.  A raw JSON parser feeding CAID
   computation or mapping MUST reject duplicate member names before
   constructing the data model.  Accepting duplicate names can make the
   native verifier and mapper select different values.

10.  IANA Considerations

   This document requests no immediate IANA actions.

   Two registries are described: the CAID action type registry
   (Section 4), whose entries follow the normative schema of
   Section 4.2, and the CAID suite registry (Section 3.1), which for
   this version contains jcs-sha256 and cbor-sha256.  Both are published
   as machine-readable JSON under a public-domain dedication and are
   maintained by the author's organization pending adoption.  Active
   entries are immutable in every field that affects validation or
   material meaning.  The stated intent is to transition maintenance to
   IANA or another neutral standards body if this specification is
   adopted.  A future revision would then specify registration policies
   for both registries.

   A URN namespace registration for CAID identifiers may be useful in
   the future; it is out of scope for this revision.

11.  References

11.1.  Normative References

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

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

Schrock                  Expires 20 January 2027               [Page 18]
Internet-Draft                    CAID                         July 2026

   [RFC4648]  Josefsson, S., "The Base16, Base32, and Base64 Data
              Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
              <https://www.rfc-editor.org/info/rfc4648>.

   [RFC5234]  Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
              Specifications: ABNF", STD 68, RFC 5234,
              DOI 10.17487/RFC5234, January 2008,
              <https://www.rfc-editor.org/info/rfc5234>.

   [RFC6234]  Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms
              (SHA and SHA-based HMAC and HKDF)", RFC 6234,
              DOI 10.17487/RFC6234, May 2011,
              <https://www.rfc-editor.org/info/rfc6234>.

   [RFC6901]  Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
              "JavaScript Object Notation (JSON) Pointer", RFC 6901,
              DOI 10.17487/RFC6901, April 2013,
              <https://www.rfc-editor.org/info/rfc6901>.

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

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

   [RFC8949]  Bormann, C. and P. Hoffman, "Concise Binary Object
              Representation (CBOR)", STD 94, RFC 8949,
              DOI 10.17487/RFC8949, December 2020,
              <https://www.rfc-editor.org/info/rfc8949>.

11.2.  Informative References

   [I-D.lee-orprg-permit-receipts]
              Lee, Y. B., "Permit Receipts for Permit-Before-Commit
              Authorization of AI-Agent and Workload External Effects",
              Work in Progress, Internet-Draft, draft-lee-orprg-permit-
              receipts-00, 4 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-lee-orprg-
              permit-receipts-00>.

Schrock                  Expires 20 January 2027               [Page 19]
Internet-Draft                    CAID                         July 2026

   [I-D.morrow-sogomonian-exec-outcome-attest]
              Morrow and A. Sogomonian, "Execution Outcome Attestation
              for AI Agents and Automated Systems", Work in Progress,
              Internet-Draft, draft-morrow-sogomonian-exec-outcome-
              attest-00, 4 April 2026,
              <https://datatracker.ietf.org/doc/html/draft-morrow-
              sogomonian-exec-outcome-attest-00>.

   [I-D.schrock-ep-authorization-receipts]
              Schrock, I., "Authorization Receipts for High-Risk Agent
              Actions", Work in Progress, Internet-Draft, draft-schrock-
              ep-authorization-receipts-06, 6 July 2026,
              <https://datatracker.ietf.org/doc/html/draft-schrock-ep-
              authorization-receipts-06>.

Appendix A.  Acknowledgments

   The separation between cryptographic validity and authority in this
   document was sharpened by review from Eric Rescorla.  Linda Dunbar's
   cross-administrative-domain Agent Gateway scenarios motivated the
   requirement for a reproducible action join across operator
   boundaries.  Chris Hood's work on agent transport and composition
   helped expose the need to keep action identity independent from any
   one authorization artifact.  These acknowledgments do not imply
   endorsement of this document.

Author's Address

   Iman Schrock
   EMILIA Protocol, Inc.
   United States of America
   Email: team@emiliaprotocol.ai

Schrock                  Expires 20 January 2027               [Page 20]