Network Working Group I. Schrock Internet-Draft EMILIA Protocol, Inc. Intended status: Standards Track 28 September 2026 Expires: 1 April 2027 The Canonical Action Identifier (CAID) draft-schrock-canonical-action-identifier-04 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 versioned action-type definitions with required material fields. External value sets are bound to integrity-checked snapshots. The document specifies a strict JSON input profile, a fixed and ordered set of refusal reasons, and a digest that identifies the validation semantics of a type definition. It requests seven registries: suites, action types, field types, code formats, reason codes, mapping transforms, and mapping loss policies. It also defines an Action-Mapping Profile for projecting natively verified 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 1 April 2027. Schrock Expires 1 April 2027 [Page 1] Internet-Draft CAID September 2026 Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. 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 . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1. Terminology . . . . . . . . . . . . . . . . . . . . . . . 5 1.2. Processing Overview . . . . . . . . . . . . . . . . . . . 7 2. Data Model and JSON Input . . . . . . . . . . . . . . . . . . 8 2.1. The Action Object . . . . . . . . . . . . . . . . . . . . 8 2.2. Data Model . . . . . . . . . . . . . . . . . . . . . . . 9 2.3. Numbers . . . . . . . . . . . . . . . . . . . . . . . . . 10 2.4. JSON Text Input . . . . . . . . . . . . . . . . . . . . . 11 2.5. Host Values . . . . . . . . . . . . . . . . . . . . . . . 12 2.6. Limits . . . . . . . . . . . . . . . . . . . . . . . . . 14 3. Suites and the Identifier . . . . . . . . . . . . . . . . . . 16 3.1. Suites . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2. The Digest . . . . . . . . . . . . . . . . . . . . . . . 17 3.3. Identifier Syntax . . . . . . . . . . . . . . . . . . . . 18 3.4. Parsing . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.5. Equality . . . . . . . . . . . . . . . . . . . . . . . . 19 3.6. Coexistence with Other Identifier Profiles . . . . . . . 20 4. Action Types and the Registry . . . . . . . . . . . . . . . . 21 4.1. Type Names and Versioning . . . . . . . . . . . . . . . . 21 4.2. The Type Definition Schema . . . . . . . . . . . . . . . 22 4.2.1. Definition Conformance . . . . . . . . . . . . . . . 23 4.2.2. Definition Digest . . . . . . . . . . . . . . . . . . 24 4.2.3. Resolution . . . . . . . . . . . . . . . . . . . . . 24 4.2.4. Status and Succession . . . . . . . . . . . . . . . . 25 4.3. Field Types . . . . . . . . . . . . . . . . . . . . . . . 25 4.4. Enum Value-Set Resolution . . . . . . . . . . . . . . . . 27 4.5. Code Fields . . . . . . . . . . . . . . . . . . . . . . . 28 4.6. Definition Sources and Unknown Types . . . . . . . . . . 30 4.7. The tool.call.1 Type . . . . . . . . . . . . . . . . . . 30 5. Computation . . . . . . . . . . . . . . . . . . . . . . . . . 34 5.1. Reason Order . . . . . . . . . . . . . . . . . . . . . . 36 5.2. Result . . . . . . . . . . . . . . . . . . . . . . . . . 36 Schrock Expires 1 April 2027 [Page 2] Internet-Draft CAID September 2026 6. Verification . . . . . . . . . . . . . . . . . . . . . . . . 36 6.1. Verification Details . . . . . . . . . . . . . . . . . . 38 7. Effect-Boundary Use . . . . . . . . . . . . . . . . . . . . . 40 8. Action-Mapping Profile . . . . . . . . . . . . . . . . . . . 41 8.1. Native Verification Boundary . . . . . . . . . . . . . . 41 8.2. Mapping Profile Object . . . . . . . . . . . . . . . . . 41 8.3. Mapping and Comparison Algorithm . . . . . . . . . . . . 44 8.4. Mapping Reasons . . . . . . . . . . . . . . . . . . . . . 47 8.5. Completeness Assumption . . . . . . . . . . . . . . . . . 47 9. What a CAID Is Not . . . . . . . . . . . . . . . . . . . . . 47 10. Security Considerations . . . . . . . . . . . . . . . . . . . 48 10.1. Digest Strength and Suite Agility . . . . . . . . . . . 48 10.2. Domain Separation and Signatures . . . . . . . . . . . . 49 10.3. Truncation . . . . . . . . . . . . . . . . . . . . . . . 50 10.4. Identical Actions and Replay . . . . . . . . . . . . . . 50 10.5. Multiple Identifiers and Downgrade . . . . . . . . . . . 50 10.6. Canonicalization and Parser Differentials . . . . . . . 50 10.7. Limits and Denial of Service . . . . . . . . . . . . . . 51 10.8. Code Format Matching . . . . . . . . . . . . . . . . . . 52 10.9. Unicode Normalization and Confusables . . . . . . . . . 52 10.10. Definition Stability and Distribution . . . . . . . . . 53 10.11. Mapping . . . . . . . . . . . . . . . . . . . . . . . . 53 10.12. A CAID Is Not a Capability . . . . . . . . . . . . . . . 54 11. Privacy Considerations . . . . . . . . . . . . . . . . . . . 54 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 55 12.1. CAID Suites . . . . . . . . . . . . . . . . . . . . . . 56 12.2. CAID Action Types . . . . . . . . . . . . . . . . . . . 56 12.3. CAID Field Types . . . . . . . . . . . . . . . . . . . . 58 12.4. CAID Code Formats . . . . . . . . . . . . . . . . . . . 59 12.5. CAID Reason Codes . . . . . . . . . . . . . . . . . . . 60 12.6. CAID Mapping Transforms . . . . . . . . . . . . . . . . 61 12.7. CAID Mapping Loss Policies . . . . . . . . . . . . . . . 62 12.8. The "caid" URI Scheme . . . . . . . . . . . . . . . . . 62 12.9. Media Types . . . . . . . . . . . . . . . . . . . . . . 63 13. Implementation Status . . . . . . . . . . . . . . . . . . . . 64 14. Changes since -03 . . . . . . . . . . . . . . . . . . . . . . 65 14.1. Newly Refused Inputs . . . . . . . . . . . . . . . . . . 65 14.2. New Rules and Features . . . . . . . . . . . . . . . . . 67 14.3. Reason Changes . . . . . . . . . . . . . . . . . . . . . 69 14.4. Reference Registry . . . . . . . . . . . . . . . . . . . 70 14.5. Requirements on Other Parties . . . . . . . . . . . . . 70 14.6. Other Changes . . . . . . . . . . . . . . . . . . . . . 72 15. Changes since -02 . . . . . . . . . . . . . . . . . . . . . . 74 16. References . . . . . . . . . . . . . . . . . . . . . . . . . 75 16.1. Normative References . . . . . . . . . . . . . . . . . . 75 16.2. Informative References . . . . . . . . . . . . . . . . . 77 Appendix A. Collected ABNF . . . . . . . . . . . . . . . . . . . 80 Appendix B. Reason Codes . . . . . . . . . . . . . . . . . . . . 83 Schrock Expires 1 April 2027 [Page 3] Internet-Draft CAID September 2026 Appendix C. Worked Examples . . . . . . . . . . . . . . . . . . 85 C.1. Computation . . . . . . . . . . . . . . . . . . . . . . . 86 C.2. Refusal and Reason Order . . . . . . . . . . . . . . . . 87 C.3. Verification Details . . . . . . . . . . . . . . . . . . 88 C.4. Definition Digest . . . . . . . . . . . . . . . . . . . . 90 C.5. Code Fields . . . . . . . . . . . . . . . . . . . . . . . 90 C.6. Mapping . . . . . . . . . . . . . . . . . . . . . . . . . 91 Appendix D. Action Types of Reference Registry Version 5 . . . . 93 D.1. Initial IANA Entries . . . . . . . . . . . . . . . . . . 93 D.2. Reference-Registry Entries Not Requested of IANA . . . . 96 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 97 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 97 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. 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 8) 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 Schrock Expires 1 April 2027 [Page 4] Internet-Draft CAID September 2026 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 9 states the boundary. An executor that uses CAID as an authorization or execution join computes the action object from the operation it is prepared to perform, or validates every material field against an authoritative source. A presenter-supplied identifier, discovery document, authorization challenge, or receipt cannot substitute for that derivation (Section 7). 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. Every operation of Section 1.2 that an implementation offers MUST return exactly the result that this document specifies for it, including every reason and the order of the reasons. Action object: The typed data object, defined in Section 2.1, over which a CAID's digest is computed. Action type: A versioned type name whose definition (Section 4) declares the material fields an action object of that type is required to carry. Material field: A field that a type definition lists in its required_fields, because its absence would leave the digest uncommitted to something that makes the action consequential. Data model: The values of Section 2.2. Every action object is a value of the data model. JSON text: Octets that encode a value in JSON [RFC8259], decoded as specified in Section 2.4. Host value: A value of an implementation's programming language that an application constructed itself (Section 2.5). Kind: The JSON kind of a value, or "unsupported" for a host value of Schrock Expires 1 April 2027 [Page 5] Internet-Draft CAID September 2026 no JSON kind (Section 6.1). Which host types have a JSON kind is a property of the language binding (Section 2.5). 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. definition_sha256: The digest of a type definition's validation projection, which identifies its validation semantics (Section 4.2.2). Enum snapshot: A locally available, immutable string array identified by an external value-set reference, a snapshot or edition label, and the SHA-256 digest of the array's JCS encoding (Section 4.4). Code format: A registered grammar that a code field's value must match (Section 4.5). Reason: A string from Appendix B that explains a refusal. Refusals are ordered lists of reasons. 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). Relying party: The party that decides whether to rely on a CAID or a mapping result, and that selects and pins the suites, definition sources, definition_sha256 values, enum snapshots, mapping profiles, and native trust anchors it accepts. A verifier, executor, or mapper applies that configuration. Executor: The party at an effect boundary that performs the operation that an action object describes (Section 7). Presenter: Any party that supplies a CAID, an action object, or a source artifact to a verifier, executor, or mapper. What a presenter supplies is a claim, not configuration. Mapping profile: A hash-identified projection, pinned by the relying party, from one exact source format and version into one CAID action type (Section 8). Schrock Expires 1 April 2027 [Page 6] Internet-Draft CAID September 2026 Native verifier: The verifier defined by a source artifact's own specification. Native verification precedes mapping and is outside the CAID trust boundary. Mapper: An implementation of the map and compare operation (Section 8). 1.2. Processing Overview CAID processing consists of the operations below. Each one returns either its result or an ordered list of reasons from Appendix B. None of them fails in any other way: malformed or hostile input of any shape yields reasons, never an exception, a crash, or a partial result, given the memory that an input within the limits of Section 2.6 can require (Section 10.7). decode: JSON text to a data-model value, or malformed_json (Section 2.4). parse: A CAID string to its version, action type, suite, and digest, or exactly one reason (Section 3.4). compute: An action object, a suite, and definition sources to a CAID, its digest, and the definition_sha256 of the definition used (Section 5). verify: A CAID and an action object to a validity bit, reasons, and details (Section 6). map and compare: Natively verified sources, through relying-party- pinned profiles, to a projected action and a verdict (Section 8). Computation proceeds as follows: Schrock Expires 1 April 2027 [Page 7] Internet-Draft CAID September 2026 JSON text ---decode (2.4), phase 0 (gate)---+ +--> data-model value host value ---convert (2.5)-----------------+ | v phase 1 action_type is a valid type name (gate) phase 2 exactly one conforming definition (gate) phase 3 required fields present phase 4 present fields valid for their types phase 5 suite registered and implemented phase 6 every number, down to depth 64 and within the value count, in the data model phase 7 every other value in the data model | v canonical bytes (suite) --> digest (suite) --> base64url --> caid:1::: The suite fixes the canonical bytes and the digest (Section 3.1). 2. Data Model and JSON Input 2.1. The Action Object An action object is a JSON object 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: * is a value of the data model of Section 2.2; * 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; * 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. Schrock Expires 1 April 2027 [Page 8] Internet-Draft CAID September 2026 2.2. Data Model A value of the data model is one of: * an object: members, each a name and a value, where every name is a string and no two members have the same name; * an array: an ordered sequence of values; * a string: a sequence of Unicode scalar values that contains no noncharacter; * a number whose value is an integer in the range -(2^53-1) through 2^53-1 (Section 2.3); * true, false, or null. Surrogate code points are not Unicode scalar values [UNICODE], so a string that contains an unpaired surrogate is outside the model. The noncharacters are U+FDD0 through U+FDEF and the last two code points of every plane: U+FFFE and U+FFFF, U+1FFFE and U+1FFFF, and so on through U+10FFFE and U+10FFFF. I-JSON [RFC7493] excludes both, and so does this model. The nesting depth of a value MUST NOT exceed 64. The outermost object or array is at depth 1, and each nested object or array adds one. The RFC 8785 encoding of an action object MUST NOT exceed 16,777,216 octets. That size is measured only for a value that is otherwise inside the model: a value outside it has no RFC 8785 encoding, so an oversized object that also holds a number outside the model yields unsupported_number and no unsupported_value. A host value is also bounded by a value count (Section 2.5); past it, a host action object yields unsupported_value from phase 7 and no unsupported_number, whatever else it holds, while phases 3 and 4 still run (Section 5), and any other host value is refused by the step that reads it (Section 2.6). The contents of an object or array nested deeper than 64 are not examined and are not counted toward the value count, so a number inside one adds no unsupported_number; a number held by an object or array at depth 64 or less still does. In a host value, a reference back to an enclosing object or array is a cycle: it counts as one value, and nothing beyond it is counted or examined, since what it refers to is counted and examined where it sits. An action object can be canonicalized when it is a value of the data model whose RFC 8785 encoding is at most 16,777,216 octets, whether or not the checks of computation phases 1 through 4 pass. Schrock Expires 1 April 2027 [Page 9] Internet-Draft CAID September 2026 A value outside the data model is refused and is never rewritten into a value inside it. Computation reports a number outside the model as unsupported_number, and anything else, including nesting beyond 64 and an encoding beyond the limit, as unsupported_value (Section 5, phases 6 and 7). A number is examined only where an object or array at depth 64 or less holds it, and not at all in a host action object past the value count, which yields unsupported_value instead (Section 2.5). 2.3. Numbers The value of a number is the result of converting the exact decimal value it denotes to binary64 [IEEE754] under the roundTiesToEven rounding-direction attribute: the correctly rounded value. Under that attribute, a value of magnitude at least 2^1024 - 2^970 rounds to an infinity. A number is in the data model if and only if its value is finite, is an integer, and has magnitude at most 2^53-1 (9,007,199,254,740,991). It is then canonicalized as that integer, which RFC 8785 serializes in plain decimal form. The literal form is irrelevant: the literals 1e3, 1000.0, and 1000 all denote the integer 1000, exactly as an ECMAScript JSON parser sees them. * A literal whose correctly rounded value is an infinity, such as 1e400 or 1.7976931348623159e308, is not finite, so it is refused as unsupported_number. A literal above the largest finite binary64 value, 2^1024 - 2^971, whose correctly rounded value is still that value, such as 1.7976931348623158e308, is a finite integer beyond 2^53-1: it is refused as unsupported_number too, but the integer field type accepts it (Section 4.3). * A literal whose correctly rounded value is zero, such as 1e-400 or -1e-400, is the integer 0, and so is -0. A literal whose correctly rounded value is a nonzero subnormal, such as 1e-310, is not an integer and is refused as unsupported_number. * A literal whose exact value is not an integer but whose correctly rounded value is, such as 0.99999999999999999999, is that integer. Issuers MUST NOT emit such literals; Section 10.6 states the consequence for a reader that reads numbers as exact decimals. * Fractional, NaN, infinite, and out-of-range values are refused as unsupported_number by every conforming implementation wherever an object or array at depth 64 or less holds them (Section 2.2), except in a host action object past the value count, which yields unsupported_value instead (Section 2.5). Fractional quantities are carried as strings. Schrock Expires 1 April 2027 [Page 10] Internet-Draft CAID September 2026 Rationale: ECMAScript number serialization is the leading source of cross-language canonicalization divergence, and a rule over the correctly rounded 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. 2.4. JSON Text Input An implementation that receives an action object or a mapping source as JSON text MUST decode it as specified in this section before validating, canonicalizing, or mapping it, and MUST refuse input that fails with the single reason malformed_json. An implementation MUST NOT compute, verify, or map over received JSON text through a decoder that does not meet these rules. When the action object arrives as a member of a larger JSON text, such as a receipt, the carrying protocol identifies exactly one member that holds it, and the party that extracts it MUST apply rules 2 through 4 to the whole enclosing text, so that no object anywhere in that text, including one that holds a second candidate action object or a sibling CAID string, has two members with the same name. Rule 1 then limits the octets of the member value that encodes the action object, and rule 5 limits that value's nesting, counted from the action object as depth 1. A failure of any of these is malformed_json. The input is refused unless all of the following hold: 1. It is at most 33,554,432 octets long. This is checked before decoding. 2. It is an I-JSON message [RFC7493], except that Section 2.2 of [RFC7493], on numbers, does not apply: the decoder admits every number token that [RFC8259] admits (below). In particular the input is valid UTF-8 [RFC3629]; no string or member name, after unescaping, contains a surrogate code point or a noncharacter; and no object has two members whose names, after unescaping, are the same sequence of code points. An escaped surrogate pair, such as "\uD83D\uDE00", denotes one scalar value and is valid; an escape of an unpaired surrogate is not. The names "a" and "\u0061" are the same name. A duplicate is refused, never resolved by keeping the first or the last member. 3. It does not begin with the UTF-8 byte order mark (the octets EF BB BF). Section 8.1 of [RFC8259] permits a parser to ignore one; this profile refuses it. Schrock Expires 1 April 2027 [Page 11] Internet-Draft CAID September 2026 4. It is exactly one JSON text [RFC8259]: one value, optionally preceded and followed by the four JSON whitespace characters, and nothing else. The literals NaN and Infinity, comments, and a character U+0000 through U+001F that appears unescaped in a string are not JSON and are refused (Section 7 of [RFC8259]). Other characters, including U+007F and U+0080 through U+009F, may appear unescaped. 5. Its nesting does not exceed 64 (Section 2.2). An implementation MUST check this without unbounded recursion. The decoder never refuses a number token that [RFC8259] admits. It converts the token to its correctly rounded value, and Section 2.3 decides whether that value is in the data model. A very long literal is therefore not a decoding failure; if its value is not a suitable integer, computation reports unsupported_number. Every failure of rules 1 through 5 yields malformed_json and nothing else, whichever rules failed. An implementation MAY report an informative detail beside the reason; that detail is not part of the result. A type definition, a registry, an enum snapshot (Section 4.4 gives its shape), or a mapping profile read from JSON text is decoded under rules 2 through 5. Rule 1 does not apply to them: a registry or a value set can legitimately grow beyond any fixed bound, and these documents are configuration that a relying party pins by digest, not input to an operation. An implementation MUST NOT use such a document when it fails those rules. How the failure is reported is outside this document. 2.5. Host Values An implementation MAY also accept an action object, a type definition, a mapping profile, or a mapping source as a host value that the application constructed. Which host types represent each kind of the data model is a property of the implementation's language binding: a Python dict subclass, for example, can be read as an object through the dict's own accessors, while an ECMAScript object whose prototype is neither Object.prototype nor null is outside the model. Such an implementation: * MUST refuse any host value that is not a value of the data model. In a host action object within the value count below, a number outside the model that an object or array at depth 64 or less holds is refused as unsupported_number, and anything else as unsupported_value (Section 5, phases 6 and 7). A host action object past that count is refused as the value count below states, Schrock Expires 1 April 2027 [Page 12] Internet-Draft CAID September 2026 and any other host value by the step that reads it (Section 2.6). A declared field that holds such a value is also checked under its field type (phase 4) exactly as Section 4.3 states, and fails that check whenever the value is not one that the type accepts. A host number is a host value that the language binding represents as a number, such as a Python int or float; its value is its correctly rounded binary64 value (Section 2.3), as for a number token. A binding may instead represent other numeric host types, such as an ECMAScript BigInt or a Go uint64, as values of kind "unsupported" (Section 6.1), and a host value of kind "unsupported" fails every field type. So NaN or 1.5 in an integer field is mistyped_field: and unsupported_number (unsupported_value past the value count), and so is a host number whose correctly rounded value is an infinity, such as the Python int 10^400; a host number beyond 2^53-1 whose correctly rounded value is finite is refused by phase 6 alone (phase 7 alone past the value count); and a BigInt in an integer field, in a binding that gives it kind "unsupported", is mistyped_field: and unsupported_value, whatever its value. A string with an unpaired surrogate, such as "1" followed by U+D800, is invalid_amount: and unsupported_value in an amount-string field, mistyped_field: and unsupported_value in a digest field, and unsupported_value alone in a string field. A map or a date in an object field is mistyped_field: and unsupported_value. At the top level, a value whose kind is not "object" fails phase 1 as invalid_action_type alone, whatever it is; * MUST NOT serialize a host value as a different value. A map type, a date, a typed array, a cyclic structure, or an object with accessor properties or a non-default prototype is refused, never canonicalized as an empty or partial object; * MUST NOT fail with an exception, a crash, or unbounded recursion for any host value, including cyclic values and values nested deeper than 64. The depth check precedes any recursive traversal; * MUST refuse a host value made of more than 33,554,432 values (Section 2.6), counting the value itself and every value inside it once for every path that reaches it, so that a value reached through two members counts twice, except that an object or array nested deeper than 64 counts as one value and nothing inside it is counted, and a reference back to an enclosing object or array counts as one value and nothing beyond it is counted (Section 2.2). For a host action object past this count, phase 7 yields unsupported_value and phase 6 yields no reason, whatever the value holds, while phases 3 and 4 still run (Section 5); a host definition whose validation projection is past it, or a host mapping profile or mapping source past it, is refused by the step Schrock Expires 1 April 2027 [Page 13] Internet-Draft CAID September 2026 that reads it (Section 2.6). No JSON text within the limit of Section 2.4 holds that many values. An implementation can process a value with shared references without walking its expansion, but the count of a value whose shared references form no cycle is that of the expansion, down to depth 64; * MUST read a host type definition only as far as its validation projection (Section 4.2.2). The projection MUST be a value of the data model, and a member outside it is never read, so a value there that is outside the model changes nothing; * MUST produce, for every value that the decoder of Section 2.4 can produce, exactly the result that the same operation over the corresponding JSON text produces. A host language's representation of an absent member, such as an ECMAScript property whose value is undefined, counts as absent for field presence (phase 3). The value itself is not a value of the data model, so the object is also refused as unsupported_value. The reason for a string that contains an unpaired surrogate or a noncharacter depends on the entry point: malformed_json when it arrives as JSON text, and unsupported_value when it arrives as a host value. It never depends on the implementation language. 2.6. Limits The limits of this document are collected in Table 1. Octets are UTF-8 octets. Every limit is a refusal with the reason shown, never an exception. A length limit on a string that a rule of Appendix A matches is checked before the rule is applied. The document encoding limit applies wherever a document other than an action object is canonicalized: a definition whose validation projection exceeds it is invalid_definition, a mapping source that exceeds it is source_not_canonicalizable, and an enum value array that exceeds it cannot match its values_sha256, so a present field is mistyped_field:. The nesting limit and the value count apply in the same way to a host value that is not an action object (Section 2.5): a host definition whose validation projection nests deeper than 64 or exceeds the value count is invalid_definition, a host mapping profile that does is invalid_mapping_profile and has no digest (Section 8.3), and a host mapping source that does is source_not_canonicalizable. Schrock Expires 1 April 2027 [Page 14] Internet-Draft CAID September 2026 +==========+===========+===================+=======================+ |Limit |Value |Applies to |Refusal | +==========+===========+===================+=======================+ |JSON text |33,554,432 |an action object or|malformed_json | | |octets |a mapping source | | | | |received as JSON | | | | |text (decode) | | +----------+-----------+-------------------+-----------------------+ |Nesting |64 levels |every value |malformed_json (action | |depth | | |object or mapping | | | | |source as JSON text); | | | | |unsupported_value (host| | | | |action object); | | | | |otherwise the reason of| | | | |the step that reads the| | | | |value | +----------+-----------+-------------------+-----------------------+ |Canonical |16,777,216 |an action object |unsupported_value | |encoding |octets | | | +----------+-----------+-------------------+-----------------------+ |Integer |2^53-1 |every number held |unsupported_number | |magnitude | |at depth 64 or less|(action object); | | | |in a value within |otherwise the reason of| | | |the value count |the step that reads the| | | | |value | +----------+-----------+-------------------+-----------------------+ |Value |33,554,432 |a host value, each |unsupported_value and | |count |values |value counted once |no unsupported_number | | | |per path; an object|(host action object); | | | |or array nested |otherwise the reason of| | | |deeper than 64, or |the step that reads the| | | |a reference back to|value | | | |an enclosing one, | | | | |counts as one value| | +----------+-----------+-------------------+-----------------------+ |Document |134,217,728|the RFC 8785 |the reason of the step | |encoding |octets |encoding of a |that needs the encoding| | | |validation | | | | |projection, an enum| | | | |value array, or a | | | | |mapping source | | +----------+-----------+-------------------+-----------------------+ |Identifier|1,024 |a CAID string |malformed_caid | | |octets | | | +----------+-----------+-------------------+-----------------------+ |Code |2,048 |the code_system of |invalid_definition | |system |octets |a code field | | +----------+-----------+-------------------+-----------------------+ Schrock Expires 1 April 2027 [Page 15] Internet-Draft CAID September 2026 |Action |512 octets |an action type in a|malformed_caid; | |type | |CAID, an action |invalid_action_type; | | | |object, or a |invalid_definition | | | |definition | | +----------+-----------+-------------------+-----------------------+ |Mapping |1 to 128 |rules of a mapping |invalid_mapping_profile| |rules |rules |profile | | +----------+-----------+-------------------+-----------------------+ |Source |at most |each source path of|invalid_mapping_profile| |path |2,048 |a mapping profile | | | |octets | | | +----------+-----------+-------------------+-----------------------+ |Profile |1 to 512 |profile_id, |invalid_mapping_profile| |string |octets |media_type, schema,| | | | |version, and | | | | |target_action_type | | +----------+-----------+-------------------+-----------------------+ |Omission |1 to 2,048 |each omission |invalid_mapping_profile| |reason |octets |reason | | +----------+-----------+-------------------+-----------------------+ Table 1: Limits A definition, registry, enum snapshot, or mapping profile read from JSON text that nests deeper than 64 fails the decoding of Section 2.4, whose report this document leaves to the implementation. The JSON text limit is twice the canonical limit, which leaves room for insignificant whitespace and escapes. A tool call whose arguments would push an action object past the canonical limit is addressed in Section 4.7. A protocol that carries action objects can impose tighter limits on its own messages, such as a node count or a bound on each string; such a limit belongs to that protocol and is not a CAID refusal. 3. Suites and the Identifier 3.1. Suites A suite names a canonicalization scheme and a digest algorithm, and fixes the length of its digest in octets. This document defines two suites; the CAID Suites registry (Section 12.1) carries one entry per suite. A registered suite is never removed, reassigned, or redefined. jcs-sha256: The JSON Canonicalization Scheme [RFC8785] followed by Schrock Expires 1 April 2027 [Page 16] Internet-Draft CAID September 2026 SHA-256 [RFC6234], with a 32-octet digest. RFC 8785 sorts member names by their UTF-16 code units, not by their code points (Section 3.2.3 of [RFC8785]), so a name that begins with U+1F600 sorts before one that begins with U+FF61. Support for this suite is REQUIRED for conforming implementations. cbor-sha256: The CBOR encoding of the action object under the core deterministic encoding requirements (Section 4.2.1 of [RFC8949]) followed by SHA-256 [RFC6234], with a 32-octet digest. The data model maps to CBOR as follows: an object is a map whose keys are text strings; an array is an array; a string is a text string; a number, which is always an integer (Section 2.3), is an unsigned or negative integer (major type 0 or 1); and true, false, and null are the simple values 21, 20, and 22. No tag, byte string, or floating-point value appears. The input is always a value of the data model, and the size limit of Section 2.2 is measured on the RFC 8785 encoding for every suite. Map keys sort by the bytewise order of their encodings, which differs from the RFC 8785 member order; Appendix C.1 gives an example. Support for this suite is OPTIONAL. A suite's status is not a type's status (Section 4.2.4). A suite is deprecated once practical collision attacks on its digest are known or anticipated (Section 12.1). Issuers then stop emitting new CAIDs under it (Section 10.1), and a relying party SHOULD remove it from the suites it accepts once the artifacts it relies on carry a CAID under a successor. Deprecation does not by itself make a verifier refuse a CAID: the suites that the relying party accepts decide (Section 3.5). A document that deprecates jcs-sha256 names the suite that becomes mandatory to implement in its place. 3.2. The Digest The digest is computed directly over the canonical bytes of the action object: digest = H(canonical_bytes(action_object)) The suite fixes both the canonicalization that produces canonical_bytes and the digest function H (Section 3.1). For the two suites of this document, H is SHA-256. 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 an existing artifact format whose signed or hashed payload is itself a valid action object can reuse the digest it already computes over the same canonical bytes under the same suite. The goal is limited to that reuse: it does not make an identifier computed under Schrock Expires 1 April 2027 [Page 17] Internet-Draft CAID September 2026 another profile comparable with a CAID (Section 3.6). Conforming verifiers MUST check that the in-object action_type equals the action type carried in the CAID string (Section 6); that check, not a byte prefix, is what prevents cross-context reinterpretation. Section 10 states this trade explicitly, and states that a signature meant to commit to a CAID covers the whole identifier string. 3.3. Identifier Syntax The identifier is a string matched by the caid rule of Appendix A: caid:1::: For example, the action object of Appendix C.1 has this CAID (long lines in this document are folded as specified in [RFC8792]): =============== NOTE: '\' line wrapping per RFC 8792 ================ caid:1:payment.release.1:jcs-sha256:liLG9pKgkLt3silrjf1wa0xIHz5YFrBB\ 9HI-arxrO1Y The grammar uses the ABNF of [RFC5234] with the case-sensitive string syntax of [RFC7405], so the prefix is the lowercase string "caid". 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; the ABNF bounds the names a registry can assign, and a parser accepts only registered names (Section 3.4). digest is the digest encoded in base64url (Section 5 of [RFC4648]), unpadded and case-sensitive. A CAID is at most 1,024 octets, and its action type at most 512 octets (Section 2.6). A suite whose digest is n octets encodes it in ceil(8n/6) characters, and the unused low bits of the final character are zero; Appendix A derives the digest syntax from n. For the two suites defined here the digest is exactly 43 characters, encoding 32 octets. Those 43 characters carry 258 bits, so the two low bits of the final character are unused and zero: the final character is one of "A", "E", "I", "M", "Q", "U", "Y", "c", "g", "k", "o", "s", "w", "0", "4", or "8". 3.4. Parsing A parser takes an identifier string and the suite registry and yields either the four components or exactly one reason. It applies these checks in order and stops at the first that fails: Schrock Expires 1 April 2027 [Page 18] Internet-Draft CAID September 2026 1. The string is at most 1,024 octets and matches the caid rule of Appendix A, and its action type is at most 512 octets, else malformed_caid. The length of the string is checked before the rule is matched. This step does not consult the registry. 2. The suite is in the suite registry, else unknown_suite. The digest of such an identifier is not checked, because the parser has no digest length for its suite. 3. The digest matches the digest syntax of the suite's digest length (Appendix A), else malformed_caid. A parser operates on the exact sequence of code points it is given. It MUST NOT trim, case-fold, Unicode-normalize, or percent-decode it; removing a transport encoding is the carrying protocol's job before parsing. As a consequence, a conforming parser refuses as malformed_caid: base64url padding ("=") in the digest; uppercase characters in the prefix, the action type, or the suite (the digest is case-sensitive, and both cases are significant there); empty segments anywhere, including empty dotted segments within the action type; any content after the digest, including trailing separators, whitespace, or additional fields; a digest that is not exactly the length of the named suite or whose final character encodes nonzero unused bits; and any caid-version other than "1", which is never guessed at or parsed leniently. An unregistered suite is refused as unknown_suite rather than malformed_caid so that the reason says what the relying party needs to know. An identifier under a suite registered after the parser's registry snapshot is well formed, and the right response is a newer suite registry, not a report of corruption. Because a registered suite is never removed or redefined, an identifier that one registry snapshot refuses as malformed_caid is refused as malformed_caid by every later snapshot. A registered suite that an implementation does not implement is not unknown to its parser: the identifier is well formed, and computation and verification report the suite as unknown_suite. 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. Schrock Expires 1 April 2027 [Page 19] Internet-Draft CAID September 2026 A relying party decides which suites it accepts, and a verifier MUST NOT accept a CAID under any other suite. When an artifact carries several CAIDs for one action, a verifier MUST verify every CAID whose suite it accepts and implements, and MUST treat the failure of any one as the failure of all. It MUST NOT select the CAID that verifies. When no carried CAID is under a suite that the verifier accepts and implements, verification fails. The relying party applies the suites it accepts to the suite of the parsed identifier (Section 3.4); the verification operation of Section 6 does not take that policy as an input. 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 8 provides a narrower result: equivalence of the material projection under exact profiles pinned by a relying party. It does not claim general semantic equivalence. 3.6. Coexistence with Other Identifier Profiles Other specifications define their own canonical action identifiers over their own canonical material, some under a distinct namespace prefix. Section 3.2 limits the no-prefix design goal to the reuse of a digest over the same canonical bytes under the same suite. This section states the consequence for identifiers derived under other profiles. An identifier derived under a different profile MUST NOT be compared for equality with a CAID derived under this document, in either direction, and a verifier MUST NOT treat inequality between them as evidence that two artifacts describe different actions. The profiles canonicalize different material; inequality carries no information. An executor holding artifacts under two profiles for what it believes is one action derives an identifier under each profile from its own representation of the effect, compares within each profile, and joins on that representation rather than on the identifier strings. Where a relying party needs a stronger statement than same-representation, the Action-Mapping Profile in Section 8 is the mechanism, and its result is equivalence of a material projection under pinned profiles, not identifier equality. Schrock Expires 1 April 2027 [Page 20] Internet-Draft CAID September 2026 [I-D.thallapelly-oasnt-caid] reaches the same conclusion for its own profile. 4. Action Types and the Registry 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 Appendix A, and is at most 512 octets long (Section 2.6). Registered types live in the CAID Action Types registry (Section 12.2), one entry per versioned type. A registered name has at least two name segments before its version, such as payment.release.1; a local definition (Section 4.6) can use one. Once a version is published, every declaration that affects validation or material meaning is immutable, with the one exception below. Adding or removing a required or optional field, retyping a field, changing a normalization rule or a field's semantics, or changing an enum set in any other way MUST be published as a new version of the type (payment.release.2), never as an in-place edit. Monotone enum advance. A registry version MAY advance the value-set pin of an enum field in place, without a new type version, to a later edition that contains every member of the set the field accepted under the previous registry version, and it MUST NOT advance a pin in place to any other edition. The first pin of a field that previously resolved no set is such an advance, because that field accepted no value. Removing, renaming, or redefining a member is never an advance. The registry records each advance field by field. Under this rule an action object that is valid under one registry version remains valid under every later version of the same registry, while an advance can make valid an object that an earlier version refused. An advance changes the type's definition_sha256 (Section 4.2.2), and every computation and verification result reports definition_sha256, so a relying party that needs exact reproducibility pins definition_sha256, and verification then refuses any other definition as definition_mismatch (Section 6). The registry keeps every definition_sha256 an entry has held (Section 12.2), so an earlier result can be replayed under the definition that produced it. Schrock Expires 1 April 2027 [Page 21] Internet-Draft CAID September 2026 4.2. The Type Definition Schema The members of a type definition are those described after the example below, and they are the same for local definitions (Section 4.6). The example is informative. It is the entry for payment.release.1 in registry version 5 of the reference registry, whose definition_sha256 is the value that Appendix C.1 shows. Line breaks inside its strings are for presentation only: each line break inside a string, and the indentation after it, reads as one space. Its long line is folded as specified in [RFC8792]. =============== NOTE: '\' line wrapping per RFC 8792 ================ { "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", "values_snapshot": "SIX ISO 4217 List One published 2026-09-17", "values_sha256": "sha256:27f824317e9f271b956123fb77608daece5106\ e1ee8253a17769390855ade270"}, {"name": "beneficiary_account", "type": "digest", "notes": "sha256: 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": [] } action_type is the versioned type name. status is the lifecycle state of the entry (Section 4.2.4). 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, the members that field type defines, and optional notes. Notes guide issuers and never change how a field is validated. optional_fields declares fields the type Schrock Expires 1 April 2027 [Page 22] Internet-Draft CAID September 2026 recognizes but does not require. digest_notes carries per-type normalization guidance for issuers. references carries citations for the type's semantics. supersedes and superseded_by, when present, name the type version this one replaces and the one that replaces it. 4.2.1. Definition Conformance A definition conforms if and only if all of the following hold: * It is an object whose action_type member is a string of at most 512 octets that matches the action-type rule of Appendix A. * required_fields is an array of at least one entry, and optional_fields is absent or an array. * Every entry of either array is an object whose type member is a string and whose name member is a field name: a string that matches the field-name rule of Appendix A, which means it is non- empty and does not contain ":" (U+003A), and that is not action_type. No field name appears twice across the two arrays. * An entry whose type is a field type of Section 4.3 has no members other than name, type, notes, and the members that field type defines, and it carries every member that field type requires, well formed. For a code field, code_system is at most 2,048 octets and matches the code-system rule, and format matches the format-name rule, of Appendix A. * The validation projection of the definition (Section 4.2.2) is a value of the data model. An entry whose type is not a field type of Section 4.3 is not member- checked; that field is refused as mistyped_field: whenever it is present, and it does not make the definition nonconforming. The same holds for a code field whose format is well formed but not a registered code format. A definition written for a later field type therefore still computes while the field is absent. The form of an enum field is not checked here: an enum that does not resolve fails as mistyped_field: when present (Section 4.4). Members of a definition other than action_type, required_fields, and optional_fields are not checked and never affect validation; in a host value they are never read (Section 2.5). A definition that does not conform is refused as invalid_definition. Schrock Expires 1 April 2027 [Page 23] Internet-Draft CAID September 2026 4.2.2. Definition Digest The validation projection of a definition that meets the first four conditions of Section 4.2.1 is the object with exactly three members: * action_type; * required_fields; * optional_fields, which is the definition's optional_fields array, or an empty array when the definition has none. The arrays keep their order, because field order fixes the order of reasons (Section 5.1). Each entry is the definition's entry with its notes member removed and every other member kept. definition_sha256 is "sha256:" followed by the 64 lowercase hexadecimal digits of the SHA-256 digest of the RFC 8785 encoding of the validation projection. It is defined only for a conforming definition; computing it for a nonconforming one yields invalid_definition. Everything outside the projection, including status, risk_class, summary, notes, digest_notes, references, supersedes, and superseded_by, never changes validation. Two definitions with equal definition_sha256 therefore validate every action object identically, given the same enum snapshots and the same registered field types and code formats. A field whose type or code format an implementation does not know is refused whenever present (Section 4.3), so implementations that know different field types or code formats can disagree about such a field. definition_sha256 does not cover the normalization guidance that notes and digest_notes give issuers (Section 10.10). Computation and verification report the definition_sha256 of the definition they used (Sections 5 and 6), and verification accepts an expected value. The reference registry lists the definition_sha256 of every type in each registry version. Appendix C.4 gives an example. This is the only digest this document calls a definition digest. A digest over a whole registry entry, including status or notes, identifies that entry's bytes, not its validation semantics, and a specification that uses one names it differently. 4.2.3. Resolution To resolve the definition for an action type, an implementation: Schrock Expires 1 April 2027 [Page 24] Internet-Draft CAID September 2026 1. collects every configured definition, from all of its definition sources, that is an object whose action_type member is exactly that string; 2. refuses with unknown_action_type when none is collected; 3. refuses with invalid_definition when any collected definition does not conform, or when two collected definitions have different definition_sha256 values; 4. otherwise uses the collected definitions, which are all the same definition. The order in which definitions are configured never affects the result. A local definition that shares a name with a registered one resolves only when the two have the same validation projection. 4.2.4. Status and Succession status is "active" or "deprecated". Status never affects resolution, computation, or verification: a deprecated type resolves, computes, and verifies wherever its fields resolve, and deprecating a type never makes an earlier result invalid. Deprecation tells issuers to use the successor that superseded_by names; supersedes, on the successor, names its predecessor. Both are informative and outside definition_sha256. An issuer MAY decline to issue new CAIDs under a deprecated type as a matter of policy. A verifier MUST NOT refuse a CAID because its type is deprecated. 4.3. Field Types A field type fixes which values a field accepts. Every check applies to the whole value: nothing may precede or follow the matched text, not even a line feed. A string field accepts the empty string, and a required field that holds "" is present. The field types of this document are listed below; the CAID Field Types registry (Section 12.3) records them. string: A string. amount-string: A decimal amount carried as a string that matches the Schrock Expires 1 April 2027 [Page 25] Internet-Draft CAID September 2026 amount-string rule of Appendix A. There is no exponent, leading "+", whitespace, or thousands separator, and the integer part has no leading zero. For example, "0", "0.50", "-0", and "-0.50" match, while "01.5", "00", "+1", "1e3", ".5", "1.", and "1,000" do not. The rule is lexical and never normalizes: "0.50" and "0.5" produce different digests (Section 3.5). A string that does not match is refused as invalid_amount:, and a value that is not a string as mistyped_field:. digest: A string that matches the digest-field rule: the literal prefix "sha256:" followed by 64 lowercase hexadecimal characters. Used where a raw identifier must not appear in the object (Section 11). enum: A string in the closed value set resolved as specified in Section 4.4. Its members are values, values_ref, values_snapshot, and values_sha256. code: A string that a registered code format matches as a whole (Section 4.5). Its members are code_system and format, both required. A string that does not match is refused as invalid_code:. timestamp: A string that matches the timestamp rule of Appendix A and whose day does not exceed the length of its month in the proleptic Gregorian calendar. This is the [RFC3339] profile with an uppercase "T" and "Z" and UTC time: a lowercase "t" or "z", an offset other than "Z", and a second of 60 are refused. The fraction is lexical, so "2026-01-01T00:00:00.000Z" and "2026-01-01T00:00:00Z" are different content, as "0.50" and "0.5" are. integer: A number whose value (Section 2.3) is a finite integer, whatever its literal form: 12, 12.0, and 1.2e1 are the integer 12. Magnitude is not part of the type. A finite integer beyond 2^53-1 is type-valid and is refused once, as unsupported_number (unsupported_value in a host action object past the value count, Section 2.5). A literal whose correctly rounded value is an infinity (Section 2.3) is not an integer, so it is refused both as mistyped_field: and as unsupported_number. For counts only, never for money. boolean: true or false. object: An object. Values nested inside it are checked by Schrock Expires 1 April 2027 [Page 26] Internet-Draft CAID September 2026 computation phases 6 and 7, not by this field type: an object field that holds a fractional number fails no field type, and the number is refused as unsupported_number wherever phase 6 examines it (Section 5). array: An array. Values nested inside it are checked by computation phases 6 and 7, not by this field type. Except where stated above, a present field whose value fails its field type is refused as mistyped_field:. A field whose type is not one of these is refused as mistyped_field: whenever it is present. A new validation constraint on an existing field type is always a new field type, never a new member on an existing type. An implementation of an earlier revision ignores an unknown member and would accept what a later one refuses, while an unknown field type makes it refuse. A registered field type or code format is never removed, renamed, or redefined; a changed grammar is registered as a new code format name. 4.4. Enum Value-Set Resolution A member of a field definition is present when its name is present; a values or values_ref member whose value is null is present and malformed, not absent. An enum definition MUST take exactly one of three forms: Inline array: A non-empty, duplicate-free array of non-empty strings in values, and no values_ref member. Compact inline: A values_ref string that begins with inline:. The prefix is case-sensitive. The text after it is split at every "|" character, and each member is trimmed of leading and trailing U+0020 SPACE characters only; no other whitespace or control character is trimmed. The members MUST be non-empty and duplicate-free. A values member that accompanies this form MUST equal the resulting list exactly, in order. External: Any other non-empty values_ref string, together with values_snapshot and values_sha256 members that are non-empty strings. The pinned array is the definition's own values member when that member is present, and otherwise a locally available snapshot whose values_ref, values_snapshot, and values_sha256 all match exactly. A supplied snapshot never replaces an embedded values member. Schrock Expires 1 April 2027 [Page 27] Internet-Draft CAID September 2026 For an external reference, the issuer or verifier MUST check that the pinned array is a non-empty, duplicate-free array of non-empty strings, compute SHA-256 over the RFC 8785 canonical JSON encoding of that complete array, and compare the lowercase hexadecimal result, prefixed with sha256:, to values_sha256 before testing membership. An enum snapshot read from JSON text is a JSON object whose values_ref, values_snapshot, and values_sha256 members are strings and whose values member is the pinned array. Other members, such as a record of provenance, never affect resolution. A set of snapshots read from JSON text is a JSON array of such objects. A definition in none of these forms, a bare external values_ref, a missing or unresolved snapshot, a digest mismatch, or a value absent from the resolved list MUST fail as mistyped_field: whenever the field is present. A type with such a field among its required fields therefore cannot produce or verify any CAID until the value set is pinned. Computation and verification MUST NOT fetch a mutable network resource to resolve an enum. An external source's later additions, removals, or corrections do not change a pinned array. Publishing a different accepted array requires a new action-type version, except for the monotone advance of Section 4.1. 4.5. Code Fields Some material values come from code systems that are large, change often, or are licensed: diagnosis and procedure codes, drug product codes, payment return reasons. A pinned value set cannot follow such a system without a new type version for every edition, and a licensed system cannot be redistributed as a snapshot. A code field identifies such a value by its system and its syntax instead: {"name": "diagnosis_code", "type": "code", "code_system": "http://hl7.org/fhir/sid/icd-10-cm", "format": "icd-10-cm"} * code_system names the code system. It is a string of at most 2,048 octets that matches the code-system rule of Appendix A: a scheme, ":", and URI characters, with no fragment and no IP- literal host. Implementations check only that rule. A code_system SHOULD be the absolute URI [RFC3986] that the code system's owner assigns. It is part of the validation projection, so it distinguishes fields with the same syntax from different systems. No implementation dereferences it. * format names a registered code format. The code formats of this document are the rules of part A.4 of Appendix A, each named by its rule name. Their syntax follows the published code systems: Schrock Expires 1 April 2027 [Page 28] Internet-Draft CAID September 2026 ICD-10-CM [ICD-10-CM], the National Drug Code [NDC], CPT [CPT], HCPCS Level II [HCPCS], ISO 3166-2 [ISO3166-2], the ISO 20022 External Code Sets [ISO20022], and the Nacha Standard Entry Class codes [NACHA]. A format fixes syntax only, never which codes exist. * The value is a string, valid if and only if the format matches the whole string. There is no normalization: the canonical form is the exact string. "G47.33" and "G4733" are different content, and only the first matches icd-10-cm. An issuer converts a native form to the format before computing. * A string that the format does not match is refused as invalid_code:. A value that is not a string, and any value of a field whose format is not a registered code format, is refused as mistyped_field:. CAID pins the syntax and the system of a code field, never a value set. Whether a code exists in some edition of its system, is billable, or suits the action is a question for the relying party. A registry MUST NOT publish a value set for a code field. For a licensed system it MUST NOT redistribute codes, descriptors, or value sets at all; CPT, whose codes the American Medical Association licenses, is the leading example. The hcpcs format accepts HCPCS Level I (CPT) and Level II codes by syntax alone, so a type can carry either without the registry carrying a single CPT code. Each lexical form of a code is its own format, so that no format admits two spellings of one code: the 11-digit and the hyphenated 10-digit forms of a National Drug Code are the formats ndc-11 and ndc-10-hyphenated. A code system whose complete value list is small and stable, and whose maintenance agency publishes that list free of charge, such as ISO 3166-1 alpha-2 [ISO3166-1] or ISO 4217 [ISO4217], is an enum pinned to a snapshot (Section 4.4), never a code format. The Nacha Standard Entry Class codes are few, but their complete list is published only in the licensed Nacha Operating Rules, so nacha-sec is a code format. Every code format matches only strings of bounded length and compiles to a regular expression with no nested quantifiers, no quantified alternatives that can begin with the same character, and no optional repetition whose first characters overlap what can follow it. Matching therefore takes time linear in the length of the value, in backtracking and automaton engines alike (Section 10.8); this document calls that the linear-matching property. A new code format is registered in the CAID Code Formats registry (Section 12.4) with its ABNF and must have this property. Schrock Expires 1 April 2027 [Page 29] Internet-Draft CAID September 2026 4.6. 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. Parties that use CAID across domains MUST pin the same exact definition, registry snapshot, or definition_sha256. A local deployment SHOULD give its types an organization-specific first segment (for example, acmecorp.ledger.close.1), so that a later registration does not take the same name. A local definition that collides by name with a different registered definition MUST NOT be treated as interoperable, and resolution refuses the pair when both are configured (Section 4.2.3). A definition source read from JSON text is a JSON array of type definitions, or a JSON object whose types member is such an array, as the reference registry is. Other members of that object never affect resolution. An unknown type is a refusal for issuers and verifiers alike. A verifier that holds no definition for the type reports invalid_object with the detail unknown_action_type (Section 6). A deployment that correlates identifiers of unknown types by digest alone is not performing CAID verification and MUST NOT report the result as valid. 4.7. The tool.call.1 Type Agent frameworks invoke a named tool with an argument object. That is a common material action in agent deployments. This section registers a type for it so that its action object is fixed by the registry rather than by an implementation. The registration is the tool.call.1 entry of the reference registry [CAID-REGISTRY], reproduced here member for member: Schrock Expires 1 April 2027 [Page 30] Internet-Draft CAID September 2026 { "action_type": "tool.call.1", "status": "active", "risk_class": "varies-by-tool", "summary": "Invocation of a named agent-framework tool with a complete argument object.", "required_fields": [ {"name": "target", "type": "string", "notes": "stable identity of the service that will execute the call, supplied by the governing profile and compared case-sensitively; use the literal local only when execution occurs in the caller process; never infer this value from ambient routing metadata"}, {"name": "tool", "type": "string", "notes": "tool name exactly as the invoking framework declares it"}, {"name": "args", "type": "object", "notes": "complete argument object handed to the tool after framework defaults; all nested values remain subject to the CAID numeric profile"} ], "optional_fields": [ {"name": "occurrence_id", "type": "string", "notes": "executor occurrence identity when the relying profile requires two otherwise identical invocations to remain distinct"} ], "digest_notes": "The CAID Action Object includes action_type, target, tool, args, and occurrence_id when present. Framework-local selector or routing hints derived from args are not separate members. Existing base:sha256: executor-binding strings are a different profile and are not CAIDs.", "references": [] } Line breaks inside the strings of this registration are for presentation only; each line break and the indentation after it read as one space. Schrock Expires 1 April 2027 [Page 31] Internet-Draft CAID September 2026 occurrence_id is optional because args can already carry an occurrence identifier. A deployment that needs to tell repeated identical calls apart (Section 10.4) MUST include occurrence_id unless args already carries an identifier that tells them apart, and one whose calls need to resist recovery by guessing (Section 11) MUST include an occurrence_id that carries at least 128 bits of entropy unless args already carries an identifier with at least that entropy. The member is named args. An implementation MUST NOT substitute another name such as arguments for the same content: the member name is inside the canonical bytes, so a rename produces a different digest for an identical call, and two conforming-looking adapters then emit identifiers that never compare equal. A framework-derived selector or routing key MUST NOT be added as a member when it is computed from values already present in args. Such a hint adds no material content and, being optional in practice, makes the digest depend on whether a particular adapter chose to compute it. This does not apply to target, which is material, is a required field, and is not derived from args. The target field is required because a tool name is not unique across providers. Where a caller can reach two services offering the same tool name, an object omitting the callee yields one identifier for two different executions, and a permit issued against one provider recomputes equal against the other. An issuer MUST NOT omit target merely because its deployment currently reaches one provider: the identifier can outlive that assumption. The governing profile defines the stable target identifier; implementations compare its exact, case-sensitive string and MUST NOT infer it from ambient connection state, a display label, or a derived routing hint. A tool.call.1 action object consists of exactly action_type, target, tool, and args, plus occurrence_id when present. An issuer MUST NOT add any other member to a tool.call.1 action object: content material to the call belongs in args, target, or occurrence_id, and any other member makes the digest depend on the adapter. A verifier still accepts extra members (Section 2.1). The complete object is canonicalized and encoded as the CAID string in Section 3. Existing framework-local strings, such as the base:sha256: executor- binding strings that the digest_notes name, are not CAIDs and MUST NOT be compared with one. For example, this action object: Schrock Expires 1 April 2027 [Page 32] Internet-Draft CAID September 2026 { "action_type": "tool.call.1", "target": "https://payments.example", "tool": "payment.release", "args": { "amount_usd": 4000, "beneficiary": "vendor@example.com", "memo": "invoice 7781" } } has the following CAID under jcs-sha256: =============== NOTE: '\' line wrapping per RFC 8792 ================ caid:1:tool.call.1:jcs-sha256:FdawgFwgN5tAtiZa-SCkVDrV3dS9w1yeXVQaDa\ ZLQQQ The example's args carries amount_usd as a JSON number, as the tool receives it; Section 10.6 states how a relying party that evaluates such a number reads it. This registration is motivated by a divergence observed in the author's own software: two of its framework adapters hashed the same argument object under different member names (args and arguments), and one also hashed a derived selector. The resulting strings were not CAIDs, but the incident showed why a future cross-framework CAID profile cannot leave its material member names to implementers. All nested members of args remain subject to the data model of Section 2.2. A framework call containing a fractional JSON number can use its own exact-action binding profile, or map the quantity to a CAID type that carries the value as a string; it is not a conforming tool.call.1 CAID. A call whose arguments carry a large body inline, such as a file or an image, can push the action object past the canonical limit of 16,777,216 octets (Section 2.6). Such a call is not a conforming tool.call.1 CAID. It is identified by a tool-specific type in which the large member is a digest field over the body's octets: the digest binds the body without placing it in the action object, and the body travels beside the artifact. Schrock Expires 1 April 2027 [Page 33] Internet-Draft CAID September 2026 5. Computation A conforming issuer computes a CAID from an action object (JSON text or a host value), a suite name, its configured definition sources, and the enum snapshots available to it. A suite, definition-source, or enum-snapshot option of the wrong type is treated as absent. An absent suite yields unknown_suite: a suite given as anything other than a string is no suite. Absent definition sources leave every action type unknown, so a valid action type is unknown_action_type. Absent enum snapshots refuse nothing by themselves; they matter only to a present field whose external enum has no embedded values member, which is then mistyped_field: (Section 4.4). Computation evaluates the phases of Table 2 in order. Phases 0 through 2 are gates: the first gate that fails yields exactly one reason, and computation stops. When the gates pass, phases 3 through 7 are all evaluated, and every reason they produce is collected. The reason strings are normative. Each reason of phases 3 and 4 takes the name of the field it concerns as its parameter (Appendix B), as in missing_material_field:. A field is present when the object has a member of that name of its own. A name that an implementation's object model inherits from elsewhere, for example through an ECMAScript prototype, is not present. Phase 4 checks only present fields that the definition declares, in required_fields or in optional_fields. Enum validation includes the snapshot resolution and integrity check of Section 4.4. A string that contains an unpaired surrogate has no UTF-8 encoding, and Section 3.2.2.2 of [RFC8785] requires a JCS implementation to refuse it; phase 7 is that refusal. A host value of kind "object" that holds values outside the data model passes phase 1 and is refused by phase 6 or 7. Phase 6 does not examine values inside an object or array nested deeper than 64, or beyond a reference back to an enclosing object or array, and the value count does not count them (Section 2.2). When a host action object is made of more values than the value count (Section 2.5), phase 6 yields no reason and phase 7 yields unsupported_value, whatever the value holds; phases 3 and 4 still run. Schrock Expires 1 April 2027 [Page 34] Internet-Draft CAID September 2026 +=======+========================+=================================+ | Phase | Reasons | Refused when | +=======+========================+=================================+ | 0 | malformed_json | the object is JSON text that | | | | fails Section 2.4 | +-------+------------------------+---------------------------------+ | 1 | invalid_action_type | the value's kind (Section 6.1) | | | | is not "object", or its | | | | action_type member is absent, | | | | is not a string, is longer than | | | | 512 octets, or does not match | | | | the action-type rule of | | | | Appendix A | +-------+------------------------+---------------------------------+ | 2 | unknown_action_type, | resolution fails | | | invalid_definition | (Section 4.2.3) | +-------+------------------------+---------------------------------+ | 3 | missing_material_field | a required field is not present | +-------+------------------------+---------------------------------+ | 4 | mistyped_field, | a present declared field fails | | | invalid_amount, | its field type (Section 4.3) | | | invalid_code | | +-------+------------------------+---------------------------------+ | 5 | unknown_suite | the suite is not a registered | | | | suite that the implementation | | | | implements | +-------+------------------------+---------------------------------+ | 6 | unsupported_number | a number that an object or | | | | array at depth 64 or less | | | | holds, in an object within the | | | | value count, is outside the | | | | data model | +-------+------------------------+---------------------------------+ | 7 | unsupported_value | any other value is outside the | | | | data model, including a string | | | | or member name with an unpaired | | | | surrogate or a noncharacter, | | | | nesting beyond 64, a canonical | | | | encoding beyond 16,777,216 | | | | octets, and a host value past | | | | the value count | +-------+------------------------+---------------------------------+ Table 2: Computation Phases Schrock Expires 1 April 2027 [Page 35] Internet-Draft CAID September 2026 5.1. Reason Order The collected reasons are sorted by phase. Within phase 3 they are sorted by the field's index in required_fields, and within phase 4 by the field's index in required_fields followed by optional_fields. Identical reason strings are then reduced to the first. A field yields at most one phase 4 reason, and phases 5, 6, and 7 yield at most one reason each. The order does not depend on the order in which an implementation traverses the object, so every implementation, and every suite, reports the same list for the same input. In particular unsupported_number always precedes unsupported_value. The result is an ordered list; implementations MUST NOT reorder, merge, or add reasons. Appendix C.2 gives an example. 5.2. Result On success, computation returns three strings: the CAID; the digest, which is the suite's digest of the canonical bytes, written for the two suites of this document as "sha256:" followed by 64 lowercase hexadecimal digits; and the definition_sha256 of the resolved definition. On failure it returns the ordered list of reasons and no identifier. Computation is fail-closed: malformed or junk input of any shape yields reasons, never an exception or a partial identifier (Section 1.2). 6. Verification A conforming verifier checks a presented CAID string against a presented action object (JSON text or a host value), using its own configured definition sources and enum snapshots and, when the relying party supplies one, an expected definition_sha256. An expected definition_sha256 that is supplied is never treated as absent: phase 5 compares it, whatever its type, with the definition_sha256 of the resolved definition, and any value other than that string is definition_mismatch. A host language's representation of an absent option, such as an ECMAScript undefined, is absent. The verifier evaluates the phases of Table 3 in order. Phases 1 through 3 are gates that yield exactly one reason and stop verification. Phases 4 through 7 are all evaluated, and each yields at most one reason. Schrock Expires 1 April 2027 [Page 36] Internet-Draft CAID September 2026 +=======+======================+====================================+ | Phase | Reasons | Refused when | +=======+======================+====================================+ | 1 | malformed_caid, | parsing fails (Section 3.4) | | | unknown_suite | | +-------+----------------------+------------------------------------+ | 2 | malformed_json | the object is JSON text that | | | | fails Section 2.4 | +-------+----------------------+------------------------------------+ | 3 | invalid_object | the value's kind is not | | | | "object" | +-------+----------------------+------------------------------------+ | 4 | action_type_mismatch | the object's action_type | | | | member is absent, is not a | | | | string, or is not the action | | | | type in the CAID | +-------+----------------------+------------------------------------+ | 5 | definition_mismatch | an expected definition_sha256 | | | | was supplied, a conforming | | | | definition resolved, and the | | | | expected value is not a | | | | string equal to its | | | | definition_sha256 | +-------+----------------------+------------------------------------+ | 6 | unknown_suite, | unknown_suite when the | | | digest_mismatch | verifier does not implement | | | | the CAID's suite; otherwise | | | | digest_mismatch when the | | | | object can be canonicalized | | | | (Section 2.2) and its digest | | | | differs from the CAID's | +-------+----------------------+------------------------------------+ | 7 | invalid_object | computation phases 1 through | | | | 4, 6, and 7 over the object | | | | yield any reason | +-------+----------------------+------------------------------------+ Table 3: Verification Phases The in-object action type check of phase 4 is mandatory; see Section 3.2 and Section 10. No digest comparison is made for an object that cannot be canonicalized. An identifier whose object fails validation is invalid_object, not merely mismatched: a digest that matches an invalid object still binds nothing material. The suite check of computation phase 5 is not part of phase 7, because phase 6 checks the suite of the presented CAID. Schrock Expires 1 April 2027 [Page 37] Internet-Draft CAID September 2026 Phases 5 and 7 resolve the definition of the object's own action_type member, not the type named in the CAID. They run even when phase 4 reports action_type_mismatch, and the definition_sha256 in the result is that of the object's type. Phase 1 is the strict parse of Section 3.4, which yields malformed_caid or, for a grammatical suite outside the suite registry, unknown_suite. Phase 6 yields unknown_suite for a registered suite that the verifier does not implement. The result has the members valid, reasons, and details, plus definition_sha256 whenever a conforming definition resolved, whether or not the result is valid. valid is true if and only if reasons is empty. Verification is deterministic and offline: the same inputs produce the same result, and any third party with the object, the identifier, the definitions, and any referenced enum snapshots can replay the check without contacting anyone. 6.1. Verification Details details lists one entry for each reason, in the order of reasons. The exception is invalid_object, which contributes one entry for each computation reason it stands for instead of one for itself: for verification phase 7, the reasons of computation phases 1 through 4, 6, and 7; for verification phase 3, the computation reason for the value, invalid_action_type. Each entry is an object with exactly these four members: reason: The reason string. field: The parameter of a parameterized reason, the string action_type for invalid_action_type and action_type_mismatch, and null otherwise. rule: The identifier of the rule that failed, from Table 4. observed: The kind of value the check saw, or null. For a reason whose observed source in Table 4 is the member, it is the kind of the object's own member named by field, or "absent" when there is no such member; when the value is not an object, it is the kind of the value itself. For malformed_caid it is the kind of the CAID argument. A kind is one of "absent", "null", "boolean", "number", "string", "array", "object", and "unsupported". Every JSON number, and every host value that the language binding represents as a number (Section 2.5), is "number", whether or not it is in the data model; "unsupported" is a host value of no JSON kind, such as a map, a date, Schrock Expires 1 April 2027 [Page 38] Internet-Draft CAID September 2026 or a numeric type that the binding does not represent as a number. Details carry no other information. They are deterministic: two conforming verifiers given the same inputs produce the same details, as in the example of Appendix C.3. +======================+======================+===========+========+ |Reason |rule |field |observed| +======================+======================+===========+========+ |malformed_json |json-text |null |null | +----------------------+----------------------+-----------+--------+ |malformed_caid |caid |null |the CAID| | | | |argument| +----------------------+----------------------+-----------+--------+ |unknown_suite |suite |null |null | +----------------------+----------------------+-----------+--------+ |invalid_action_type |action-type |action_type|the | | | | |member | +----------------------+----------------------+-----------+--------+ |unknown_action_type |definition-resolution |null |null | +----------------------+----------------------+-----------+--------+ |invalid_definition |definition-conformance|null |null | +----------------------+----------------------+-----------+--------+ |definition_mismatch |definition-sha256 |null |null | +----------------------+----------------------+-----------+--------+ |missing_material_field|required-field |the |the | | | |parameter |member | +----------------------+----------------------+-----------+--------+ |mistyped_field |field-type |the |the | | | |parameter |member | +----------------------+----------------------+-----------+--------+ |invalid_amount |amount-string |the |the | | | |parameter |member | +----------------------+----------------------+-----------+--------+ |invalid_code |code-format |the |the | | | |parameter |member | +----------------------+----------------------+-----------+--------+ |unsupported_number |number |null |null | +----------------------+----------------------+-----------+--------+ |unsupported_value |data-model |null |null | +----------------------+----------------------+-----------+--------+ |action_type_mismatch |action-type-equal |action_type|the | | | | |member | +----------------------+----------------------+-----------+--------+ |digest_mismatch |digest-equal |null |null | +----------------------+----------------------+-----------+--------+ Table 4: Verification Detail Rules Schrock Expires 1 April 2027 [Page 39] Internet-Draft CAID September 2026 7. Effect-Boundary Use When a CAID is used at an effect boundary, the enforcing executor MUST construct the action object from the operation it is prepared to invoke, or MUST validate every material field against a relying- party-controlled system of record. It MUST recompute the CAID from that object. It MUST then invoke the operation using only the values it constructed or validated, read from the data-model value that Section 2.4 or Section 2.5 produced, and MUST NOT use any other member, such as an optional field or an extra member, unless it validated that member too. It MUST NOT re-read the action object through a separate parser to drive the invocation (Section 10.6). A CAID received from a presenter MAY be compared with the recomputed value, but MUST NOT replace executor-side construction. Discovery documents, authorization challenges, receipts, permits, and other evidence can carry a CAID. Their identifiers are claims about content under their own integrity and trust rules. Before comparing such an identifier with the executor-computed CAID, the artifact MUST be verified under its native specification and the relying party's native trust anchors (Section 8.1). If the native representation differs from the CAID action object, comparison MUST use an exact, relying-party-pinned Action-Mapping Profile as specified in Section 8. A successful comparison establishes only the matching result in this document. Evidence satisfaction, local authorization, one-time consumption, invocation, execution status, reconciliation, revocation, and remedy remain separate protocol decisions. The Action Evidence Boundary [I-D.schrock-action-evidence-boundary] and the Authorization Evidence Chain [I-D.schrock-ep-authorization-evidence-chain] are informative examples of specifications that keep those decisions separate. A multi-stage authorization program MAY bind a root CAID and the digests of predecessor stage receipts in a separate program artifact. It MUST NOT reinterpret the root CAID as proof that any stage completed. A stage that authorizes a materially different action uses a different CAID. Program order, quorum, stage completion, and authority attenuation are outside the CAID trust boundary. Schrock Expires 1 April 2027 [Page 40] Internet-Draft CAID September 2026 8. 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. 8.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 a native verification result that is the boolean true 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. Any other native verification result, including an absent one, yields INDETERMINATE. 8.2. Mapping Profile Object A version 1 profile is a JSON object with the following shape: Schrock Expires 1 April 2027 [Page 41] Internet-Draft CAID September 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. The members of a profile are exactly @version, profile_id, source_format, target_action_type, loss_policy, material_source_paths, rules, and, optionally, omitted_source_fields. source_format has exactly media_type, schema, and version; a rule has exactly source_path, target_field, and transform; an omitted_source_fields entry has exactly source_path and Schrock Expires 1 April 2027 [Page 42] Internet-Draft CAID September 2026 reason. A mapper MUST reject an unknown member at any of these levels, and MUST treat a member whose value is null as malformed. This prevents a misspelled or future policy member from being covered by the profile digest while being silently ignored by the mapping algorithm. The members are constrained as follows. Lengths are counted in UTF-8 octets (Section 2.6), and strings are compared as exact sequences of code points. * @version is "CAID-MAPPING-PROFILE-v1". * profile_id, the three source_format members, and target_action_type are strings of 1 to 512 octets. 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 is a registered loss policy (below). * rules is an array of 1 to 128 rules. Each source_path is a JSON Pointer [RFC6901] other than the empty pointer, of at most 2048 octets: the source-path rule of Appendix A. Each target_field is a field name (Section 4.2.1) other than action_type. Each transform is a registered transform (below). * material_source_paths is a non-empty array of source paths. * omitted_source_fields, when present, is an array whose entries each carry a source path and a reason string of 1 to 2048 octets. * No two rules share a source_path or a target_field, no path repeats within material_source_paths or within omitted_source_fields, the set of rule source paths equals the set of material_source_paths, and no omitted path is also a rule source path. Each material source path therefore has exactly one rule. * Every required field of the target action type is the target_field of exactly one rule. The loss policies form a closed set, recorded in the CAID Mapping Loss Policies registry (Section 12.7): no-material-field-loss: omitted_source_fields is absent or empty. Every concept the source treats as material is mapped. declared-source-semantic-loss: omitted_source_fields is non-empty. Schrock Expires 1 April 2027 [Page 43] Internet-Draft CAID September 2026 Each entry names a source path that the source format treats as material to its own action identity but that the target type does not carry, with a reason. A mapping under this policy never succeeds: it yields INDETERMINATE with declared_source_semantic_loss, which makes the loss reviewable instead of silent. The transforms form a closed set, recorded in the CAID Mapping Transforms registry (Section 12.6): copy: Copy the source value after confirming that it is a value of the data model. 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. sha256-hex-to-digest: For a source string of exactly 64 lowercase hexadecimal characters (the hex-sha256 rule), emit "sha256:" followed by that string. A mapper MUST refuse an unregistered transform or loss policy. Version 1 performs no unit conversion, currency conversion, date inference, case folding, or lossy normalization. 8.3. Mapping and Comparison Algorithm A mapper takes a source, a profile, the verifier-derived source descriptor, the relying party's pinned profile digest, the native verification result, definition sources, enum snapshots, and a suite. The suite is jcs-sha256 when the suite argument is absent, and only then. A suite argument that is present but is not a string is no suite, and stage D reports mapped_action:unknown_suite. The mapper runs four stages. Each ends in a gate: when a stage produces a reason, mapping stops after that stage, except that stage B always runs after stage A and the two stop together. Stage A, the profile. If the profile is outside the data model or is not an object, its @version differs, it has a member outside the closed shape, or a member fails its type, length, pointer, field-name, or closed-set constraint, stage A yields exactly invalid_mapping_profile. Otherwise stage A evaluates all of the following: invalid_mapping_profile when a uniqueness, set-equality, disjointness, or loss-policy constraint fails; unknown_action_type or invalid_definition when the target type does not resolve Schrock Expires 1 April 2027 [Page 44] Internet-Draft CAID September 2026 (Section 4.2.3); and, when it resolves, unmapped_material_field: for each required field of its definition that is no rule's target_field, in required_fields order. Stage B, the preconditions. native_verification_required when the native verification result is not the boolean true; mapping_profile_unpinned when no pinned digest was supplied or it differs from the profile digest, which a profile outside the data model does not have; source_format_mismatch when the source descriptor is not an object, when the profile is not an object, or when the RFC 8785 encoding of the descriptor differs from that of the profile's source_format member, as it does when either has no RFC 8785 encoding or that member is absent; source_not_object when the source is not an object; source_not_canonicalizable when the source is not an object of the data model, so that no source digest exists; and declared_source_semantic_loss when the profile's loss_policy member is declared-source-semantic-loss. In this stage an object is a value whose kind (Section 6.1) is "object", and stage B reads the profile's source_format and loss_policy members whenever the profile is an object, whether or not the profile is in the data model and whether or not stage A failed. A source that is not an object yields both source_not_object and source_not_canonicalizable. If stage A or stage B produced any reason, mapping stops. Stage C, extraction. For each rule, in rule order, the mapper resolves source_path against the source as specified in [RFC6901] and applies the transform. A rule yields at most one reason: invalid_source_path:

when a reference token applied to an array does not match the array-index rule; missing_source_field:

when a token names no member of an object, an index is not less than the array's length, or a token is applied to a value that is neither an object nor an array; source_value_type_mismatch:

when sha256-utf8 or sha256-hex-to-digest receives a value it does not accept; and source_value_not_canonicalizable:

when copy or sha256-jcs receives a value outside the data model. Here

is the rule's source_path. Two of these cannot occur: unknown_transform:

, because stage A refuses an unregistered transform, and source_value_not_canonicalizable:

, because stage B admits only a source that is an object of the data model, and every value inside such an object is in the data model. Both are registered for completeness. If any rule produced a reason, mapping stops. Schrock Expires 1 April 2027 [Page 45] Internet-Draft CAID September 2026 Stage D, the projected action. The projected action object has an action_type member equal to target_action_type and one member per rule, named by its target_field and holding its transformed value, and no other members. Computation (Section 5) runs over it with the requested suite, definition sources, and enum snapshots. If computation refuses, each of its reasons r, in computation order, becomes mapped_action:r, for example mapped_action:missing_material_field:amount. Otherwise the mapping succeeds. A source received as JSON text is decoded as specified in Section 2.4 before mapping begins. A decoding failure is the decode operation's malformed_json. It yields no mapping result and no comparison, and it is never a mapping or comparison reason. A successful mapping result carries the source digest ("sha256:" and the SHA-256 of the source's JCS encoding), the profile digest, the projected action object, the resulting CAID, its digest, the definition_sha256 of the target type's definition, and the suite. A comparison result retains both 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. Appendix C.6 gives an example. Both mapping results of a comparison are computed under one suite. Comparison of two mapping results returns exactly one of: INDETERMINATE: Either mapping failed, or both succeeded but target different action types. In the first case the reasons are those of the left mapping, each prefixed with "left:", followed by those of the right mapping, each prefixed with "right:", for example left:mapped_action:invalid_amount:amount. In the second case the reason is target_action_type_mismatch. EQUIVALENT_UNDER_PROFILE: Both mappings succeeded, both target the same action type, and the resulting CAID strings are byte-equal. There are no reasons. NOT_EQUIVALENT: Both mappings succeeded and target the same action type, but the resulting CAIDs differ. The reason is material_projection_mismatch. 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. Schrock Expires 1 April 2027 [Page 46] Internet-Draft CAID September 2026 8.4. Mapping Reasons The mapping reasons are listed in Table 11, except unknown_action_type and invalid_definition, which stage A shares with computation and which Table 10 lists. Within a mapping result, stage A reasons come first, in the order invalid_mapping_profile, unknown_action_type, invalid_definition, and then the unmapped_material_field reasons in required_fields order, followed by stage B reasons in the order listed above; identical reason strings are reduced to the first. Stage C reasons are in rule order, and stage D reasons in computation order. These are the only mapping reasons: a conforming mapper produces a result for every input and never reports an internal fault as a reason. 8.5. 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. 9. What a CAID Is Not Under the selected suite's security assumptions (Section 10.1), 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 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. Schrock Expires 1 April 2027 [Page 47] Internet-Draft CAID September 2026 * 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. 10. Security Considerations CAID defines a data format and processing rules, not a protocol exchange. Issuers and presenters may be adversarial and control every octet of an action object, including extra members (Sections 1.2 and 7). Definition sources and enum snapshots are trusted only through relying-party pins (Sections 4.4 and 10.10), and mapping profiles only through relying-party selection (Section 8.5). Insertion, removal, or substitution of a CAID in transit is governed by the carrying artifact's own integrity mechanism (Sections 7 and 10.2). The property that CAID provides is stated in Section 9; everything else there is a non-goal. 10.1. Digest Strength and Suite Agility When the party that constructs the action object is trusted, the binding between an identifier and its content rests on the second- preimage resistance of the suite's digest. When that party may be adversarial, for example an agent that proposes an action for approval and later requests the operation, the binding rests on collision resistance: free-form fields such as the args of tool.call.1, and extra members (Section 2.1), give such a party bytes to vary. SHA-256 provides about 128 bits of collision resistance and more against second preimages. If practical collision attacks on SHA-256 become known, the migration path is suite agility: a new suite is registered and issuers move to it, emitting new identifiers (Section 3.1). There is no in-place algorithm change within a suite, Schrock Expires 1 April 2027 [Page 48] Internet-Draft CAID September 2026 ever. A suite's digest is at least 256 bits, and the suite registry does not accept a digest formed by truncating the output of a hash function to fewer octets than that function specifies; a function whose specification defines a shorter output, such as SHA-384 or SHA-512/256, is not such a truncation (Section 12.1). Suite agility moves only the CAID digest. Whatever the suite, the following are fixed to SHA-256: definition_sha256 (Section 4.2.2), values_sha256 (Section 4.4), the profile and source digests of a mapping (Sections 8.2 and 8.3), the registry-file digest (Section 12.2), the digest field type, and the sha256-utf8, sha256-jcs, and sha256-hex-to-digest transforms. The "sha256:" prefix of each labels its algorithm. A new digest field type or transform is added through its registry (Sections 12.3 and 12.6). Replacing the algorithm of definition_sha256, of values_sha256, or of the profile and source digests requires a revision of this document, which follows the guidance of [RFC7696]. Equal definition_sha256 values in resolution (Section 4.2.3) and pinned profile digests also rest on collision resistance. A new suite does not migrate digests embedded in action objects, so an object's commitment to a field that it carries only as a digest remains bounded by SHA-256 until the type is versioned with a new field type. 10.2. Domain Separation and Signatures 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 phase 4 of Section 6 and is not optional. Because extra members are permitted, one JSON object can be both a valid action object and another protocol's signed payload, and its bare digest is the same in both roles. Reusing an existing digest for correlation is permitted. A signature, MAC, or commitment that is to be read as a commitment to a CAID MUST cover the complete CAID string, whose caid:1::: prefix supplies the domain separation that the digest omits. Schrock Expires 1 April 2027 [Page 49] Internet-Draft CAID September 2026 10.3. Truncation A CAID MUST NOT be abbreviated for comparison. A display MAY abbreviate an identifier, but an abbreviated form is not a CAID: parsers refuse it (Section 3.4), and a relying party MUST NOT compare it with anything. 10.4. Identical Actions and Replay Identical action objects have identical CAIDs. A CAID is not a nonce and gives no replay protection. A consume-once permit keyed on a CAID alone blocks a legitimate second identical operation, and a permit without consume-once semantics authorizes both. A type that must distinguish repeated identical operations SHOULD require an occurrence identifier. The occurrence_id member of tool.call.1 is optional, so two identical tool calls without it share a CAID; Section 4.7 says when a deployment includes it. 10.5. Multiple Identifiers and Downgrade An artifact that carries several CAIDs for one action invites a verifier to check only the one that passes. Section 3.5 forbids that: a verifier MUST verify every CAID whose suite it accepts and implements, and a relying party pins the suites it accepts, so an attacker cannot steer verification to a weaker suite. That rule protects only CAIDs that the carrying artifact integrity-protects as a set (Section 10.2). Against a suite that has weakened, the protection is the relying party's accepted set: an artifact that carries only a CAID under an accepted but weakened suite verifies, so a relying party removes a deprecated suite from its accepted set (Section 3.1). 10.6. Canonicalization and Parser Differentials 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.3). The canonical form of an action object is the one its suite fixes (Section 3.1); no other serialization, however stable it appears, is a conforming digest input. Host JSON parsers differ in ways that change identified content. Some keep the first of two duplicate members and some the last. Some replace invalid UTF-8 or an unpaired surrogate escape with U+FFFD, so two different inputs yield one CAID. Some accept a byte order mark, NaN, or unbounded nesting. Each difference lets a native verifier and a CAID computation read different values from one text. Section 2.4 fixes one reading of JSON text, including the text that Schrock Expires 1 April 2027 [Page 50] Internet-Draft CAID September 2026 encloses an embedded action object, and Section 2.5 extends it to host values. For every text on which the parsers above disagree about structure or strings, Section 2.4 refuses the text, so no CAID exists to disagree with a native reading. It does not constrain a native verifier, and one number differential remains by design: Section 2.3 maps literals with different exact decimal values to one integer, such as 3999.99999999999999999, 4000.0000000000001, and 4000, or 1e-400 and 0. A native verifier or policy engine that reads numbers as exact decimals can therefore evaluate a value other than the one a matching CAID commits to. A relying party that evaluates a number in an action object SHOULD evaluate the value of Section 2.3; otherwise, before relying on a CAID match, it SHOULD refuse any number token that has a fraction or exponent part. A quantity that policy compares against a threshold SHOULD be typed amount-string. Member names raise a related problem. Some host decoders match member names case-insensitively, as Go's encoding/json does when it decodes into a struct, and some compare names by canonical equivalence, as Swift's String type does. The object {"amount":"1.00","Amount":"99999.00"} has a valid CAID that commits to both members, yet a case-insensitive decoder reads 99999.00 for amount, and a decoder that compares names by canonical equivalence treats "caf" followed by U+00E9 and "cafe" followed by U+0301 as one name in the same way. Section 7 therefore requires an executor to act only on the values it validated. 10.7. Limits and Denial of Service An implementation bounds the work one input can cause: the text limit is checked before decoding, the depth limit before any recursive traversal, and the canonical limit before hashing (Section 2.6). Mapping profiles are bounded in rules and string lengths. Registries, definitions, and enum snapshots are exempt from the text limit, so an implementation bounds the size of the configuration it loads by its own policy. Every limit is a refusal with a reason, never an exception or a crash. The lengths of identifiers, action types, and code_system values are checked before any pattern runs, and a host value is bounded by its value count, so no input reaches the internal limits of a regular expression engine or walks an exponential expansion of shared references. Schrock Expires 1 April 2027 [Page 51] Internet-Draft CAID September 2026 The limits still admit large inputs. Decoding and canonicalizing an action object near the 33,554,432-octet text limit can take seconds and more than a gigabyte of memory in some implementations. A protocol that accepts action objects from parties it does not trust SHOULD bound its own messages well below these limits (Section 2.6). The statement of Section 1.2 that every input yields a result assumes that memory; an implementation that cannot obtain it fails as its platform fails when memory runs out, which this document does not specify. 10.8. Code Format Matching A pattern language chosen per definition would let a definition author, or anyone who can supply a definition over the network, choose a pattern with catastrophic backtracking. A pattern such as (a|a){1,99} takes time exponential in the length of the input in common backtracking engines. CAID has no such language. A code field names a registered format, and every format is a fixed grammar that matches strings of bounded length and compiles to a regular expression with no nested quantifiers, no quantified alternatives that can begin with the same character, and no optional repetition whose first characters overlap what can follow it. A bounded length alone is not enough: (a|a){1,99} matches only strings of at most 99 characters. Matching is therefore linear in the length of the input in every engine. An implementation MAY match a format with a hand- written recognizer instead of a regular expression. 10.9. Unicode Normalization and Confusables CAID performs no Unicode normalization. Visually identical strings in different normalization forms, or homoglyphs such as U+0430 in place of "a", are different content with different CAIDs. That fails safe for equality but not for human review. An interface that displays an action object for approval SHOULD apply confusable detection to identifier-like fields such as hosts, accounts, email addresses, and tool names. It SHOULD also display every member, escape control and bidirectional formatting characters in member names, and flag any member that the type does not declare whose name equals a declared field name after case folding, after NFKC normalization [UNICODE], or under the confusable skeleton of [UTS39], because an executor that matched names that way would read the wrong member (Section 10.6). A relying party MAY refuse such an object as a matter of local policy. A type whose fields name such identifiers SHOULD state their normalization in digest_notes, and issuers apply it before computing. The action type and the suite are ASCII by grammar. Schrock Expires 1 April 2027 [Page 52] Internet-Draft CAID September 2026 A reason carries a field name or a source path verbatim, and a field name can hold control and bidirectional formatting characters. An interface or log that displays reasons escapes them. The field names of the reference registry are printable ASCII. 10.10. Definition Stability and Distribution A versioned action-type definition is immutable once published, apart from the monotone enum advance of Section 4.1. definition_sha256 identifies validation semantics exactly, and a relying party that needs exact reproducibility pins it. A local and a registered definition that share a name but differ in validation semantics are not the same type, and resolution refuses the pair when both are configured, so a second definition slipped into a configured source causes invalid_definition instead of silently changing validation. A definition source obtained over the network MUST be checked against the pinned SHA-256 digest of the registry file (Section 12.2) or against pinned definition_sha256 values before use. The registry- file digest covers the file's octets, so an implementation SHOULD check it before it parses the file; a check against definition_sha256 values necessarily follows decoding under Section 2.4, within a size that the implementation bounds by its own policy (Section 10.7). definition_sha256 does not cover notes or digest_notes, which carry normalization guidance for issuers, so a party that relies on that guidance checks the source against the registry-file digest. A code-set name or URL does not identify immutable validation semantics. Issuers and verifiers MUST use the exact locally available snapshot and verified digest required by Section 4.4. Resolving a mutable network resource at computation or verification time can make the same object alternate between valid and invalid and is prohibited. Missing, unresolved, or digest-mismatched snapshots fail closed. 10.11. Mapping 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. The algorithm of Section 8.3 yields INDETERMINATE when a profile is unpinned or its source format does not match, when it declares source semantic loss, or when a required target field has no rule. It cannot detect a material source concept that the profile neither maps nor declares (Section 8.5); only profile review guards against that. Schrock Expires 1 April 2027 [Page 53] Internet-Draft CAID September 2026 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 8.1). 10.12. A CAID Is Not a Capability Possession of an identifier proves nothing and grants nothing. Protocols MUST NOT treat knowledge of a CAID as evidence of anything beyond knowledge of the object's content. A CAID also hides nothing that can be guessed; Section 11 explains why. 11. Privacy Considerations A CAID has the same confidentiality as its action object. It is an unsalted, deterministic hash of the whole object, and it carries the action type in cleartext. When every member of an object is guessable, as with a small amount, a currency, a known payee, and a sequential instruction identifier, anyone who holds the identifier can recover the object by testing candidates offline, at the cost of one SHA-256 computation each. The tool.call.1 example of Section 4.7 shows this: enumerating amount_usd upward from 1 recovers the value 4000 after 4000 candidates. A CAID therefore SHOULD be logged, transmitted, and placed in URLs only where the action object itself could be. The digest that computation returns and the source digest of a mapping result carry the same exposure. A CAID is meant to be recomputed by a party that already holds the action object, such as a verifier (Section 6) or an executor (Section 7), and receipts and other evidence carry it for such parties. It is not designed as a correlation identifier to propagate to parties that do not hold the object: to them it discloses whatever of the object can be guessed. The digest field type keeps raw values out of an action object but does not by itself provide confidentiality or unlinkability. A plain SHA-256 digest of an account number, email address, or patient identifier is pseudonymous, not anonymous: an observer can test likely values by dictionary attack. The digest-typed values in Appendix C are digests of short example strings and can be recovered this way. 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 type whose required fields can all be low-entropy SHOULD require a member that Schrock Expires 1 April 2027 [Page 54] Internet-Draft CAID September 2026 carries at least 128 bits of entropy from the system of record, such as a random instruction or occurrence identifier. A deployment- specific commitment scheme can require an explicit mapping profile for cross-domain joins. The initial CAID Action Types entries rely on identifiers from the system of record, such as payment_instruction_id, authorization_number, and order_id, that the registry cannot require to be high-entropy. Where such an identifier is sequential and the other members can be guessed, anyone who holds a CAID of that type can recover its action object, so the CAID needs the protection its action object needs, including personal-data protection when the object carries personal data. The notes of a registered type fix what each of its digest fields commits to, and that is part of the entry's immutable meaning (Section 12.2), so a deployment does not carry a keyed commitment, such as HMAC-SHA-256 [RFC6234] under a deployment-scoped key, in a digest field whose notes, like those of patient_ref, describe a plain digest. A deployment that needs a keyed commitment uses a type whose notes specify it: a local type (Section 4.6) or a new version registered for that purpose. Nothing in an action object says which scheme a digest field used, so comparison across deployments then needs a mapping profile (Section 8). Action objects, CAIDs, verification details, and their correlations should be assumed to travel and to appear in logs. 12. IANA Considerations IANA is requested to create a registry group named "Canonical Action Identifier (CAID)" containing the seven registries of Sections 12.1 through 12.7, and to register the URI scheme of Section 12.8. The registration policies are those of [RFC8126]. Until IANA creates the registries, the author's reference registry records their contents: the CAID Suites and CAID Action Types entries in files published under a public-domain dedication beside [CAID-REGISTRY], and the other five registries in the specification sources of the same repository. Its Action Types file records a superset of the initial CAID Action Types contents: it also carries the entries that IANA is not asked to register, which Appendix D.2 lists. The reference for every initial entry of every registry below is this document; each initial CAID Action Types entry also references [CAID-REGISTRY], which holds its definition, and Section 4.7 reproduces the definition of tool.call.1. The change controller of every initial entry is the IETF. Schrock Expires 1 April 2027 [Page 55] Internet-Draft CAID September 2026 Only an entry's change controller may request a change to that entry, such as deprecation with superseded_by or a monotone enum advance, and the designated expert reviews the request under the policy that applies to a new registration. For entries registered by IETF-stream documents, the change controller is the IETF, acting through the IESG. The IESG may also act for any other change controller that cannot be reached or does not respond. 12.1. CAID Suites Registration policy: Specification Required. Each entry records: the suite name, which matches the suite rule of Appendix A; the canonicalization scheme and its reference; the digest algorithm and its reference; the digest length in octets, at least 32; the status, active or deprecated; the change controller; and a reference. The designated expert refuses a digest formed by truncating the output of a hash function to fewer octets than that function specifies, and a name that differs from a registered name only by hyphens; a function whose specification defines a shorter output, such as SHA-384 or SHA-512/256, is not such a truncation. A registered name is never reassigned, an entry is never removed, and a suite is never redefined. A suite is deprecated once practical collision attacks on its digest are known or anticipated: its change controller requests the deprecation, or the IESG does for a controller that cannot be reached or does not respond (Section 12), and a new suite is registered. Section 3.1 states what deprecation means for issuers and relying parties. The initial contents are: +=============+==================+==========+========+========+ | Suite | Canonicalization | Digest | Octets | Status | +=============+==================+==========+========+========+ | jcs-sha256 | RFC 8785 | SHA-256, | 32 | active | | | | RFC 6234 | | | +-------------+------------------+----------+--------+--------+ | cbor-sha256 | RFC 8949, | SHA-256, | 32 | active | | | Section 4.2.1 | RFC 6234 | | | +-------------+------------------+----------+--------+--------+ Table 5: CAID Suites: Initial Contents 12.2. CAID Action Types Registration policy: Specification Required. Each entry records: the action type, which matches the action-type rule of Appendix A and has at least two name segments; the definition, in the schema of Section 4.2; its definition_sha256; the status; supersedes and superseded_by where they apply; the change controller; and a reference. The expert does not register a name whose first segment Schrock Expires 1 April 2027 [Page 56] Internet-Draft CAID September 2026 is organization-specific (Section 4.6) unless that organization is the change controller. The content of an entry that affects validation or material meaning, including the normalization guidance in notes and digest_notes, is immutable, with two exceptions: the status may move from active to deprecated, with superseded_by naming the successor; and the expert may approve a monotone enum advance (Section 4.1) after checking that every previously accepted value remains accepted. An advance request cites the edition and values_sha256 of the new value set. An advance updates definition_sha256, and the entry keeps every earlier definition_sha256. A new version of a registered type name is registered by the change controller of its earlier versions, or with that controller's written agreement, and the expert refuses a registration, or a supersedes or superseded_by value, that would link type versions held by different change controllers without that agreement. The expert applies the material-fields test: every required field is material; field names are printable ASCII; amounts are amount-string; identifiers that are personal or secret-adjacent are digest fields; in a registration made after this document, a type whose required fields can all be low-entropy requires a member that carries at least 128 bits of entropy, or its digest_notes or its specification state why not (Section 11); every enum is closed or pinned to an integrity- checked snapshot; and values from large, changing, or licensed code systems are code fields, with no value set and no licensed content. The initial entries of Appendix D.1 are registered by this document: Section 11 states why their identifiers are not required to carry 128 bits of entropy, and Section 4.7 why occurrence_id is optional in tool.call.1. The 9 deprecated initial entries are registered to record the history of the successors that superseded_by names, not for new identifiers, and they do not meet the test: each has a required enum field whose external values_ref has no pinned snapshot, and four of them hold as enums values that their successors carry as code fields. Such an enum field refuses whenever it is present, so, as registered, none of the 9 produces or verifies a CAID (Section 4.4). A registrant whose type pins an external enum supplies the snapshot file, in the shape of Section 4.4 together with the source it was derived from and what is known of that source's terms, and the SHA-256 digest of the file; the expert confirms that the file is publicly available under the terms it states before approving the entry. The initial contents are the 54 entries of Appendix D.1, 45 active and 9 deprecated. The definition of each entry is the entry with that name in the file action-types.json of [CAID-REGISTRY], registry version 5 of the reference registry, whose SHA-256 digest over the Schrock Expires 1 April 2027 [Page 57] Internet-Draft CAID September 2026 octets of that file, in hexadecimal, is 1e30ddd312c888f6a27055dac0ed453398e20b64cfdcb7c5019fcf0e1ac2551a. Section 4.7 reproduces the tool.call.1 entry member for member. The reference registry also carries types defined by other specifications, and one whose name misdescribes it; they are listed in Appendix D.2 and are not initial entries. Each of the seven types defined by other specifications may be registered under Specification Required with its own specification and change controller. The eighth, dns.zone.transfer.1, is not to be registered, because its name misdescribes the type; the registrar transfer it defines can be registered under a name that describes it. IANA is asked to store each entry's definition, in the schema of Section 4.2, as a file linked from the entry, and to record with each entry every definition_sha256 it has held, in order, with the date of each change, starting with the value that Appendix D.1 gives. A monotone enum advance adds a value to that list and never removes one. IANA is also asked to store, and to link from each entry that pins it, each enum snapshot file that an initial entry pins and that is derived from an IANA registry: the DNS Resource Record TYPEs list, the JOSE algorithm and elliptic curve lists, and the ISO 3166-1 alpha-2 list as the Language Subtag Registry carries it. The ISO 4217 snapshot, which every currency field of the initial entries pins, is archived with those files beside action-types.json at the commit that [CAID-REGISTRY] cites. Each snapshot file records the source it was derived from, and its entry in the enum_snapshot_files member of action-types.json records what is known of its terms. 12.3. CAID Field Types Registration policy: IETF Review. A field type defines new members, refusal behavior, and processing, so it changes what every implementation validates. An entry records the name, which matches the format-name rule of Appendix A; the JSON kind of its values; the members it defines; its refusal reasons; and a reference. A registered field type is never removed, renamed, or redefined. The initial contents are: Schrock Expires 1 April 2027 [Page 58] Internet-Draft CAID September 2026 +===============+=========+=====================+=================+ | Field type | JSON | Members | Refusals | | | kind | | | +===============+=========+=====================+=================+ | string | string | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | amount-string | string | none | invalid_amount, | | | | | mistyped_field | +---------------+---------+---------------------+-----------------+ | digest | string | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | enum | string | values, values_ref, | mistyped_field | | | | values_snapshot, | | | | | values_sha256 | | +---------------+---------+---------------------+-----------------+ | code | string | code_system, format | invalid_code, | | | | | mistyped_field | +---------------+---------+---------------------+-----------------+ | timestamp | string | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | integer | number | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | boolean | boolean | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | object | object | none | mistyped_field | +---------------+---------+---------------------+-----------------+ | array | array | none | mistyped_field | +---------------+---------+---------------------+-----------------+ Table 6: CAID Field Types: Initial Contents 12.4. CAID Code Formats Registration policy: Specification Required. A code format is a grammar applied by the unchanged rule of Section 4.5; it adds no member, reason, or processing step. An implementation that does not know a format refuses only the fields that name it, as mistyped_field (Section 4.2.1), which fails closed, and the checks below bound what a format can admit. An entry records: the format name, which matches the format-name rule; its grammar in ABNF [RFC5234] [RFC7405] over printable ASCII, which is complete, defining every rule it uses other than the core rules of [RFC5234]; the maximum length of a matching string; the reference that defines its syntax; the change controller; and a reference. The designated expert checks that the format fixes syntax only, never a value set; that it matches only strings of bounded length; that it has the linear-matching property of Section 4.5 (see also Section 10.8); that each distinct lexical form of a code is a distinct format; and that the registration carries no Schrock Expires 1 April 2027 [Page 59] Internet-Draft CAID September 2026 licensed content. A registered code format is never removed, renamed, or redefined; a changed grammar is registered as a new format name. The grammar of each initial entry is the rule of part A.4 of Appendix A with the same name, together with the rules of part A.4 that it references: UALPHA and UALNUM, and, for hcpcs, the cpt and hcpcs-level-ii rules. The initial contents are: +========================+=========+===========================+ | Code format | Maximum | Syntax reference | | | length | | +========================+=========+===========================+ | icd-10-cm | 8 | ICD-10-CM Official | | | | Guidelines for Coding and | | | | Reporting, Section I.A.2 | +------------------------+---------+---------------------------+ | ndc-11 | 11 | FDA National Drug Code | | | | format, 11-digit form | +------------------------+---------+---------------------------+ | ndc-10-hyphenated | 12 | FDA National Drug Code | | | | format, 10-digit forms | +------------------------+---------+---------------------------+ | cpt | 5 | AMA CPT code set | +------------------------+---------+---------------------------+ | hcpcs-level-ii | 5 | CMS HCPCS Level II | +------------------------+---------+---------------------------+ | hcpcs | 5 | CMS HCPCS Level II; AMA | | | | CPT (HCPCS Level I) | +------------------------+---------+---------------------------+ | iso-3166-2 | 6 | ISO 3166-2 | +------------------------+---------+---------------------------+ | iso20022-external-code | 4 | ISO 20022 External Code | | | | Sets | +------------------------+---------+---------------------------+ | nacha-sec | 3 | Nacha Operating Rules, | | | | Standard Entry Class | | | | codes | +------------------------+---------+---------------------------+ Table 7: CAID Code Formats: Initial Contents 12.5. CAID Reason Codes Registration policy: Standards Action. A new reason changes what every conforming implementation reports and where the reason sorts (Section 5.1), so it is registered only by a Standards Track RFC that also updates the reason rule of Appendix A and names the phase or stage that reports it. Each entry records: the reason code, in lowercase letters and underscores; the kind of its parameter (none, Schrock Expires 1 April 2027 [Page 60] Internet-Draft CAID September 2026 field-name, source-path, or compute-reason); the operations and phases, or the mapping stage, that report it; and a reference. The reason rule of Appendix A accepts exactly the reasons registered by this document. The prefixes left: and right: of a comparison (Section 8.3) are not registered reasons: each marks which mapping a registered mapping reason came from, and a mapping reason gains both prefixed forms when it is registered. The initial contents are the two tables of Appendix B. 12.6. CAID Mapping Transforms Registration policy: IETF Review. A mapper written from an earlier specification refuses an unknown transform, so a registration changes what mappers accept. Each entry records: the transform name, which matches the format-name rule of Appendix A; the source values it accepts; its output; the reason for a value it does not accept; and a reference. The initial contents are: +===========+========+==========+==================================+ |Transform |Accepts |Output | Refusal | +===========+========+==========+==================================+ |copy |any |the value | source_value_not_canonicalizable | | |value of| | | | |the data| | | | |model | | | +-----------+--------+----------+----------------------------------+ |sha256-utf8|a string|"sha256:" | source_value_type_mismatch | | | |and the | | | | |SHA-256 of| | | | |its UTF-8 | | | | |octets | | +-----------+--------+----------+----------------------------------+ |sha256-jcs |any |"sha256:" | source_value_not_canonicalizable | | |value of|and the | | | |the data|SHA-256 of| | | |model |its RFC | | | | |8785 | | | | |encoding | | +-----------+--------+----------+----------------------------------+ |sha256-hex-|a string|"sha256:" | source_value_type_mismatch | |to-digest |matching|and the | | | |hex- |string | | | |sha256 | | | +-----------+--------+----------+----------------------------------+ Table 8: CAID Mapping Transforms: Initial Contents Schrock Expires 1 April 2027 [Page 61] Internet-Draft CAID September 2026 12.7. CAID Mapping Loss Policies Registration policy: IETF Review. A mapper written from an earlier specification refuses an unknown loss policy, so a registration changes what mappers accept. Each entry records: the policy name, which matches the format-name rule of Appendix A; the constraint on omitted_source_fields; its effect on the mapping result; and a reference. The initial contents are: +==================+===========+===============================+ | Policy | Omissions | Effect | +==================+===========+===============================+ | no-material- | absent or | none | | field-loss | empty | | +------------------+-----------+-------------------------------+ | declared-source- | non-empty | INDETERMINATE, reason | | semantic-loss | | declared_source_semantic_loss | +------------------+-----------+-------------------------------+ Table 9: CAID Mapping Loss Policies: Initial Contents 12.8. The "caid" URI Scheme A CAID is a syntactically valid URI [RFC3986]: the scheme "caid" followed by ":" and a rootless path made of unreserved characters and ":". IANA is requested to register the scheme in the "Uniform Resource Identifier (URI) Schemes" registry with the following template [RFC7595]: Scheme name: caid Status: Permanent Applications/protocols that use this scheme name: Authorization receipts, permits, execution attestations, audit records, and other artifacts that identify an action by its Canonical Action Identifier. Contact: Iman Schrock Change controller: IETF References: This document. Syntax: the caid rule of Appendix A. Semantics: a caid URI identifies typed action content by digest. It is not a locator: no operation is defined on it, and an application MUST NOT dereference it. Encoding: the identifier is ASCII and contains no percent- Schrock Expires 1 April 2027 [Page 62] Internet-Draft CAID September 2026 encoded octets; a percent-encoded form is not a CAID, and a carrying protocol removes any transport encoding before parsing. Interoperability: CAIDs are compared as exact strings (Section 3.5). [RFC3986] treats scheme names as case-insensitive and makes lowercase the normal form; every CAID is already in that form, so normalization under Section 6 of [RFC3986] leaves a CAID unchanged. An application MUST NOT normalize a string before parsing it as a CAID, because normalization can turn a string that a parser refuses, such as one whose scheme is written "CAID", into a CAID (Section 3.4). Security: Section 10 and Section 11. Utility (Section 3.1 of [RFC7595]): a CAID names an action by the digest of a canonicalization that its suite fixes, applied to an action object whose type definition decides which members are required and how each is typed, and the identifier carries the action type and the suite, both of which take part in comparison (Section 3.5). An ni URI [RFC6920] names an object by the digest of its octets, unless a specification defines another input, under an algorithm from the Named Information Hash Algorithm Registry. It names no canonicalization, and two ni names that share the algorithm and the digest value refer to the same object whatever else they carry, so an action type or a suite in their authority or query parameters would take no part in comparison. A URN namespace [RFC8141] could carry the same fields in its namespace-specific string, but URN-equivalence lowercases "urn" and the namespace identifier, ignores the r-, q-, and f-components, and lets a namespace add equivalences but never remove one, so it would equate spellings that a parser under Section 3.4 refuses and that Section 3.5 compares as different strings. 12.9. Media Types This document registers no media type [RFC6838]. A media type earns registration when a recipient must recognize a message by it, and no step of this document sends one of its objects that way: * A type definition is configuration. A relying party pins it by definition_sha256 (Section 4.2.2) or by the SHA-256 digest of the registry file (Section 12.2), and a definition obtained over the network is checked against that pin before use, never trusted for its label. * A mapping profile is pinned by its digest and comes from relying- party configuration; a label inside a presented artifact is never accepted as the profile or its source format (Section 8.1). * An enum snapshot is local by rule: computation and verification never fetch one (Section 4.4). Schrock Expires 1 April 2027 [Page 63] Internet-Draft CAID September 2026 * An action object travels inside the artifact that carries it, under that artifact's own format. A specification that defines a transfer of any of these objects can register a media type for it. 13. Implementation Status This section records the known implementations of this specification at the time of posting, as described in [RFC7942]. Listing an implementation here does not imply endorsement by the IETF. The RFC Editor is asked to remove this section before publication. EMILIA Protocol, Inc., the author's organization, maintains three implementations, in JavaScript, Python, and Go. Each implements decoding, parsing, computation, verification, the definition digest, and mapping for the jcs-sha256 suite, and refuses cbor-sha256 as unknown_suite. The JavaScript implementation uses only the platform's cryptographic library, and the Python and Go implementations use only their standard libraries. All three run one shared conformance corpus of core and mapping vectors, plus candidate cross-format mapping vectors that encode the author's reading of other formats' published specifications and have not been validated by those formats' authors; they skip the corpus vectors that apply only to an implementation of cbor-sha256. They are licensed under Apache-2.0 and published at . The next major release (6.0.0) of the author's verification package will vendor a byte-for-byte copy of caid.mjs, the module of the JavaScript implementation that carries every operation except mapping; the published 5.0.0 vendors a copy of an earlier revision. Contact: team@emiliaprotocol.ai. Version: all three implement revision -04 of this document. Coverage: every operation of Section 1.2, for JSON text and host values, under the jcs-sha256 suite; none implements the cbor-sha256 suite. Maturity: they are the reference implementations of the author's conformance tooling, reviewed only within the author's organization. This section was last updated on 28 September 2026. All three implementations come from the author's organization, and none of them is independent. No independent implementation is known to the author. A party that runs these implementations or their conformance corpus reproduces the author's results; such external re- runs are reproductions, not independent implementations. Schrock Expires 1 April 2027 [Page 64] Internet-Draft CAID September 2026 14. Changes since -03 This section is to be removed before publishing as an RFC. This revision makes the processing model complete and checkable, and it is a substantive revision. The suites, the digest, and the canonical form of every object that both -03 and -04 accept do not change. The identifier syntax changes only by refusing the forms listed in Section 14.1. The lists below give every normative change. Each item in the first four lists changes what an implementation of the operations of Section 1.2 accepts, refuses, or reports, and is pinned by conformance vectors. The fifth list gives new requirements on parties whose behavior those operations cannot observe, and the last list gives changes to the text alone. 14.1. Newly Refused Inputs This revision refuses each of the following inputs, which -03 accepted or did not address. The first four items, and the timestamp, amount, length, and value count items, refuse action objects whose CAIDs were valid under -03. * Action objects nested deeper than 64 levels: malformed_json as JSON text, unsupported_value as host values (Sections 2.2 and 2.4). A host definition whose validation projection is nested that deep, or a host mapping profile or mapping source nested that deep, is refused by the step that reads it: invalid_definition, invalid_mapping_profile, or source_not_canonicalizable (Section 2.6). * Action objects whose canonical encoding exceeds 16,777,216 octets: unsupported_value (Section 2.2). * Strings and member names that contain a Unicode noncharacter, which I-JSON excludes: malformed_json as JSON text, unsupported_value as host values (Sections 2.2 and 2.4). * JSON text longer than 33,554,432 octets, even when the object it encodes is within the canonical limit: malformed_json (Section 2.4). * JSON text that begins with a byte order mark, is not valid UTF-8, is not exactly one JSON text, or contains NaN, Infinity, or a character U+0000 through U+001F unescaped in a string: malformed_json. U+007F and U+0080 through U+009F may appear unescaped. [RFC8259] lets a parser ignore a byte order mark; this profile refuses it. Schrock Expires 1 April 2027 [Page 65] Internet-Draft CAID September 2026 * JSON text with duplicate member names, including names that differ only in escaping: malformed_json. -03 required a raw parser to reject duplicates in its Security Considerations; the rule is now part of the decoder and has a reason. * Host values outside the data model, which an implementation now refuses instead of serializing as another value. A top-level value that is not an object is invalid_action_type, and a host type definition is read only as far as its validation projection (Section 2.5). * Action objects under a nonconforming definition, or under two configured definitions of one type with different validation projections: invalid_definition (Sections 4.2.1 and 4.2.3). -03 did not say what a nonconforming definition does, so an implementation could issue a CAID that bound none of the intended fields. * Definitions with a field name that is empty, contains ":", is action_type, or repeats, and field entries of a registered field type that carry members the type does not define: invalid_definition (Section 4.2.1). * Timestamps with a lowercase "t" or "z", or with a second of 60, which [RFC3339] permits and the -03 description "an RFC 3339 timestamp in UTC" therefore admitted: mistyped_field (Section 4.3). * Identifiers that begin with "CAID:" or "Caid:", which the -03 ABNF admitted because an [RFC5234] string literal is case-insensitive: malformed_caid (Section 3.4). * Amount strings whose integer part has a leading zero, such as "01.5", which the -03 prose admitted: invalid_amount (Section 4.3). * Identifiers whose suite begins with a digit, which the -03 suite ABNF already excluded, and identifiers whose digest's final character sets an unused bit, which -03 did not address: malformed_caid (Section 3.4). The reference implementations accepted both before this revision. * Mapping profiles with two rules for one source path, which -03 already forbade, a member whose value is null, a target_field that is not a string, a string outside its limit when measured in UTF-8 octets, or a target_action_type longer than 512 octets: invalid_mapping_profile (Section 8.2). Schrock Expires 1 April 2027 [Page 66] Internet-Draft CAID September 2026 * Action types longer than 512 octets, identifiers longer than 1,024 octets, and code_system values longer than 2,048 octets, which -03 did not bound: invalid_action_type in an action object, malformed_caid in an identifier, and invalid_definition in a definition (Section 2.6). * Host action objects that hold more than 33,554,432 values, each counted once for every path that reaches it, where an object or array nested deeper than 64, or a reference back to an enclosing object or array, counts as one value: unsupported_value and no unsupported_number, while phases 3 and 4 still run (Section 2.5). A host definition whose validation projection, or a host mapping profile or mapping source, holds that many is refused by the step that reads it: invalid_definition, invalid_mapping_profile, or source_not_canonicalizable (Section 2.6). 14.2. New Rules and Features * JSON text input (Section 2.4). Action objects and mapping sources received as text are decoded under an I-JSON profile, and every decoding failure is the single reason malformed_json. Definitions, registries, snapshots, and profiles get the same rules without the size limit. * The data model (Section 2.2), the number rule (Section 2.3), and one table of limits (Section 2.6). A literal whose correctly rounded value is an infinity is unsupported_number; one whose correctly rounded value is zero is the integer 0, and one whose correctly rounded value is a nonzero subnormal is unsupported_number. * Host values (Section 2.5): refused, never rewritten, never an exception, and with the same result as the corresponding JSON text. A declared field that holds a host value outside the data model is checked under its field type as Section 4.3 states, and the contents of an object or array nested deeper than 64 are not examined (Section 2.2). * Reason order (Section 5.1). Computation phases 0 through 2 are gates that yield exactly one reason. The other phases all run, and their reasons are sorted by phase and field position and deduplicated, so unsupported_number always precedes unsupported_value. * Definition conformance and resolution (Sections 4.2.1 and 4.2.3). A field name is a non-empty string without ":", unique, and not action_type. The order of configured definitions no longer affects the result. Schrock Expires 1 April 2027 [Page 67] Internet-Draft CAID September 2026 * definition_sha256 (Section 4.2.2), which computation, verification, and mapping report. * An expected definition_sha256 for verification, and the reason definition_mismatch (Section 6). * Verification details, one closed-shape entry per underlying reason (Section 6.1). * Status never affects computation or verification, so a deprecated type resolves, computes, and verifies wherever its fields resolve (Section 4.2.4). * The code field type, named code formats, and the reason invalid_code (Section 4.5). * Field types match whole values, empty strings are present, and the integer type is value-based (Section 4.3). * The monotone enum advance (Section 4.1) replaces the narrow correction rule of -03. The -03 sentences that treated any added value as a new type version are replaced; a relying party that needs exact reproducibility pins definition_sha256. The migration from reference registry version 3 to version 4 removed accepted values before this rule existed; its decisions remain decisions under version 3. * A suite, definition-source, or enum-snapshot option of the wrong type counts as absent, and an expected definition_sha256 of any type is compared, never ignored (Sections 5 and 6). * The accept-unregistered verifier option of -03 is removed. An object whose type has no definition fails verification as invalid_object with the detail unknown_action_type (Section 4.6). * The loss policy declared-source-semantic-loss, the transform sha256-hex-to-digest, and the mapping profile member omitted_source_fields (Section 8.2). The reference implementations and their conformance corpus already used them; a mapper written from -03 refused such profiles. * Mapping limits, counted in UTF-8 octets: 1 to 128 rules, source paths of at most 2048 octets, profile strings of 1 to 512 octets, and omission reasons of 1 to 2048 octets (Section 2.6). * A target_field may be any field name other than action_type, so a required field such as @version can be mapped (Section 8.2). Schrock Expires 1 April 2027 [Page 68] Internet-Draft CAID September 2026 * Mapping stages A through D, and the left: and right: composition of comparison reasons, are normative (Sections 8.3 and 8.4). * The mapper uses jcs-sha256 only when no suite is given (Section 8.3). * Mapping stage B reads the profile's source_format and loss_policy members whenever the profile is an object, whether or not it is in the data model, and a profile outside the data model has no digest, so it yields mapping_profile_unpinned (Section 8.3). Before this revision, one of the reference implementations read neither member of a profile nested deeper than 64, past the value count, cyclic, or holding a host value of no JSON kind. * The shape of an enum snapshot read from JSON text, and the requirement that the values_snapshot and values_sha256 members of an external enum be non-empty strings (Section 4.4). * The mapping of the data model to CBOR under cbor-sha256: an object is a map with text-string keys, a number is an integer of major type 0 or 1, and no tag, byte string, or floating-point value appears. The size limit is measured on the RFC 8785 encoding for every suite, support for the suite is optional, and Appendix C.1 gives the encoding, digest, and CAID of an example (Section 3.1). -03 named only CBOR core deterministic encoding (Section 4.2 of RFC 8949). 14.3. Reason Changes * A grammatical suite outside the suite registry parses to unknown_suite instead of malformed_caid (Section 3.4). This changes verification step 1 of -03, "Strict-parse the CAID string ..., else malformed_caid": verification phase 1 now yields malformed_caid or unknown_suite (Section 6). The input is refused either way. * An unpaired surrogate escape in JSON text is malformed_json; in a host value it remains unsupported_value (Sections 2.4 and 2.5). * A string that fails amount-string is invalid_amount and a value that is not a string is mistyped_field; -03 allowed either reason for the former (Section 4.3). * A registered suite that an implementation does not implement parses, and computation and verification report it as unknown_suite; -03 left the verification reason unstated (Section 6). Schrock Expires 1 April 2027 [Page 69] Internet-Draft CAID September 2026 14.4. Reference Registry * The reference registry [CAID-REGISTRY] advances to registry version 5, with 62 type versions: 53 active, every one of which can compute, and 9 deprecated. dns.record.delete.1 and vendor.onboard.1 receive their first enum pins. key.create.2, key.rotate.2, firewall.rule.open.2, pii.export.2, and phi.disclose.2 resolve their open enums with existing field types. payment.refund.2, ach.debit.originate.2, rx.dispense.2, and prior.auth.approve.2 use code fields. contract.execute.2 requires both contract_value and currency; contract.execute.1 stays active for contracts that state no monetary value. The nine superseded version 1 types are deprecated and still resolve. Registry version 4 is kept byte for byte as history/action-types.v4.json, the last file that declared registry version 4, which digests.json pins by its SHA-256, and every type's definition_sha256 is published. 14.5. Requirements on Other Parties These requirements bind issuers, type authors, registrants, executors, carrying protocols, relying parties, deployments, and applications. The operations of Section 1.2 cannot observe them, so no conformance vector pins them. * The party that extracts an action object embedded in a larger JSON text applies rules 2 through 4 of Section 2.4 to the whole enclosing text, so a duplicate member anywhere in it is malformed_json. * An executor invokes the operation only with the values it constructed or validated, and never re-reads the action object through a separate parser (Section 7). * An issuer adds no member to a tool.call.1 action object beyond action_type, target, tool, args, and occurrence_id, and a deployment that must tell identical calls apart, or resist guessing, includes occurrence_id unless args already carries an identifier that does so (Section 4.7). * Issuers do not emit a number literal whose exact value is not an integer but whose correctly rounded value is (Section 2.3). * A relying party that evaluates a number in an action object evaluates the value of Section 2.3, or refuses number tokens that have a fraction or exponent part before relying on a match, and a quantity compared against a threshold is typed amount-string (Section 10.6). Schrock Expires 1 April 2027 [Page 70] Internet-Draft CAID September 2026 * A relying party decides which suites it accepts, and a verifier accepts no CAID under another suite. When an artifact carries several CAIDs for one action, the verifier verifies every CAID whose suite it accepts and implements, treats the failure of any one as the failure of all, and never selects the CAID that verifies (Section 3.5). * A signature, MAC, or commitment that is to be read as a commitment to a CAID covers the complete CAID string (Section 10.2). * A CAID is never abbreviated for comparison, and a relying party compares an abbreviated form with nothing (Section 10.3). * A type that must distinguish repeated identical operations requires an occurrence identifier (Section 10.4). * A protocol that accepts action objects from parties it does not trust bounds its own messages well below the limits of Section 2.6 (Section 10.7). * A suite is deprecated once practical collision attacks on its digest are known or anticipated; issuers then stop emitting CAIDs under it, and relying parties remove it from the suites they accept (Sections 3.1 and 12.1). * An approval interface applies confusable detection to identifier- like fields, displays every member with the control and bidirectional formatting characters of member names escaped, and flags an undeclared member whose name matches a declared one under case folding, NFKC normalization, or the confusable skeleton; an interface or log that displays reasons escapes them (Section 10.9). * A type whose fields name identifiers such as hosts, accounts, email addresses, or tool names states their normalization in digest_notes, and issuers apply it before computing (Section 10.9). * A registry file obtained over the network is checked against its digest before it is parsed (Section 10.10). * Parties that use CAID across domains pin the same definition, registry snapshot, or definition_sha256, as -03 required of cross- domain verifiers, and a local deployment gives its types an organization-specific first segment (Section 4.6). * An application does not dereference a CAID and does not normalize a string before parsing it as one (Section 12.8). Schrock Expires 1 April 2027 [Page 71] Internet-Draft CAID September 2026 * A CAID is logged, transmitted, and placed in URLs only where its action object could be, which reverses the -03 recommendation that identifiers be treated as public values (Section 11). * A type whose required fields can all be low-entropy should require a member that carries at least 128 bits of entropy from the system of record; a later registration without one states why (Sections 11 and 12.2). * A deployment that needs a keyed commitment in a digest field uses a type whose notes specify it (Section 11). * A registrant whose type pins an external enum supplies the snapshot file, with its source and what is known of its terms, and the SHA-256 digest of the file (Section 12.2). 14.6. Other Changes The following changes add or correct text. None of them changes what an implementation of the operations of Section 1.2 accepts, refuses, or reports. * A processing overview (Section 1.2) and four appendices: the collected ABNF, now the only statement of every grammar, with case-sensitive strings [RFC7405]; the reason tables; worked examples that recompute; and the initial CAID Action Types. * The identifier example of Section 3.3, which had no action object, is replaced by the example of Appendix C.1. Long lines in examples are folded as specified in [RFC8792]. * Terminology defines relying party, executor, presenter, mapper, and kind, and one sentence states conformance: every operation of Section 1.2 that an implementation offers returns exactly the result that this document specifies (Section 1.1). * Section 2.4 excludes Section 2.2 of RFC 7493, whose number constraint the decoder does not apply, and states that an escaped surrogate pair is valid. Section 3.1 notes that RFC 8785 sorts member names by UTF-16 code units. Schrock Expires 1 April 2027 [Page 72] Internet-Draft CAID September 2026 * Processing text is corrected where it did not match the processing: what absent options do in Section 5; the phase 1 test of Table 2 and the test of Section 2.5, which use the value's kind, and which host numeric types a binding represents as numbers; the nesting row of Table 1; stage C, which names the two reasons it cannot report; the validation projection, whose definition no longer depends on the conformance condition that uses it; and Section 6.1. * Security Considerations now open with what CAID defines and whom it trusts; name collision resistance where the party that constructs an action object may be adversarial; list the values fixed to SHA-256 and how each migrates; and explain the memory that the limits admit, why code-format matching is linear, and why a new suite leaves digest fields bounded by SHA-256. The requirements that Security Considerations add are listed in Section 14.5. The parser requirements moved from Security Considerations to Section 2.4. * Privacy Considerations are a section of their own. They state that a CAID has the confidentiality of its action object, explain the preimage-guessing risk and the entropy of the identifiers that the initial types rely on, and state that a CAID is meant to be recomputed by parties that hold the action object, not propagated as a correlation identifier to parties that do not. The requirements they add are listed in Section 14.5. * IANA Considerations request seven registries, each with a registration policy set by what a registration changes, and the caid URI scheme with Permanent status, and explain why no media type is registered. Of the 62 types of reference registry version 5, IANA is asked to register the 54 of Appendix D.1; the 8 of Appendix D.2 are defined by other specifications, or carry a name that misdescribes the type, and stay in the reference registry. The section says who may request a change to an entry and that the IESG may act for a change controller that cannot be reached or does not respond; registers a new version of a type name only by, or with the written agreement of, the change controller of its earlier versions; registers a name with an organization-specific first segment only with that organization as change controller; and asks IANA to store the snapshot files derived from IANA registries. The -03 statement that the author's organization maintains the registries is removed. * The registration of the caid URI scheme states why the scheme is defined instead of using an ni URI [RFC6920] or a URN namespace [RFC8141] (Section 12.8). Schrock Expires 1 April 2027 [Page 73] Internet-Draft CAID September 2026 * The example of Section 4.2 is the registry entry for payment.release.1 with its real values_sha256, the registration of Section 4.7 is the registry entry for tool.call.1, member for member, and Appendix C.4 describes the projection correctly. * An Implementation Status section [RFC7942]. * Normative references to RFC 8259, RFC 3629, RFC 7405, RFC 7493, RFC 3986, IEEE 754, and the reference registry at a fixed commit, with the URL of the raw file whose octets its digest covers, and informative references to RFC 7595, RFC 6920, RFC 8141, RFC 7696, RFC 7942, RFC 8126, RFC 8792, RFC 6838, RFC 5730, RFC 5936, the Unicode Standard and its UTS #39, ISO 3166-1 and ISO 4217, whose code lists two enum snapshots carry, and the code systems whose syntax the code formats follow. * Wording that referred to earlier revisions as "this revision" is made revision-neutral. 15. Changes since -02 This section is to be removed before publishing as an RFC. Revision -03 makes enum validation replayable. External enum references now require a snapshot or edition label, a SHA-256 pin over the complete JCS values array, exact local resolution, and a verified membership check. Bare, unresolved, digest-mismatched, and out-of-set values fail closed. The enum definition forms are now exact: a null member is present and malformed, compact inline members are trimmed of U+0020 SPACE only, a values array beside a compact inline reference must equal it, and an embedded values array beside an external reference is the pinned array. Values outside a compact inline list now fail closed. Required-field presence means a member of the action object itself. Strings and member names containing an unpaired surrogate are refused as unsupported_value, making explicit the refusal that RFC 8785 already requires. Registries could correct an existing value-set pin in a new registry version under narrow conditions; -04 replaces that rule with the monotone advance of Section 4.1. The reference registry advances from version 3 to version 4. It pins the SIX ISO 4217 List One snapshot published 2026-09-17 for every currency field, by values digest and by a digest over the whole snapshot file, and pins the Dispense As Written codes of rx.dispense.1 inline. Existing action objects containing a code in that snapshot produce the same CAID bytes; a code that version 3 Schrock Expires 1 April 2027 [Page 74] Internet-Draft CAID September 2026 accepted but the snapshot omits is refused. Eleven active types in the reference registry require an external value set that has no pinned snapshot yet and cannot produce a CAID under version 4 until one is published. Deployments must update their registry and enum- snapshot pins before reporting validation under registry v4. Historical v3 decisions remain decisions under the historical registry and are not retroactively relabeled v4. Revision -03 does not change the action object, identifier syntax, digest suites, or mapping algorithm, and changes canonicalization only by making the unpaired-surrogate refusal explicit. 16. References 16.1. Normative References [CAID-REGISTRY] EMILIA Protocol, Inc., "CAID Reference Registry, Registry Version 5", September 2026, . Registry version 5 is the file action-types.json at this fixed commit, whose octets the URL above serves. The CAID Action Types section of this document gives the SHA-256 digest of those octets. This reference covers that file alone. Beside it at the same commit, digests.json lists the definition_sha256 of every type, history/action-types.v4.json holds registry version 4, and value-sets/ holds the enum snapshots. [IEEE754] IEEE, "IEEE Standard for Floating-Point Arithmetic", IEEE Std 754-2019, DOI 10.1109/IEEESTD.2019.8766229, July 2019, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, . [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, . Schrock Expires 1 April 2027 [Page 75] Internet-Draft CAID September 2026 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, . [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, . [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008, . [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, . [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed., "JavaScript Object Notation (JSON) Pointer", RFC 6901, DOI 10.17487/RFC6901, April 2013, . [RFC7405] Kyzivat, P., "Case-Sensitive String Support in ABNF", RFC 7405, DOI 10.17487/RFC7405, December 2014, . [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, DOI 10.17487/RFC7493, March 2015, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017, . [RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, June 2020, . Schrock Expires 1 April 2027 [Page 76] Internet-Draft CAID September 2026 [RFC8949] Bormann, C. and P. Hoffman, "Concise Binary Object Representation (CBOR)", STD 94, RFC 8949, DOI 10.17487/RFC8949, December 2020, . 16.2. Informative References [CPT] American Medical Association, "Current Procedural Terminology (CPT)". [HCPCS] Centers for Medicare & Medicaid Services, "Healthcare Common Procedure Coding System (HCPCS)", . [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, . [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, . [I-D.schrock-action-evidence-boundary] Schrock, I., "The Action Evidence Boundary for Consequential Agent Effects", Work in Progress, Internet- Draft, draft-schrock-action-evidence-boundary-07, 25 September 2026, . [I-D.schrock-ep-authorization-evidence-chain] Schrock, I., "Authorization Evidence Chains: Composing Heterogeneous Agent-Action Evidence (EP-AEC)", Work in Progress, Internet-Draft, draft-schrock-ep-authorization- evidence-chain-06, 6 September 2026, . Schrock Expires 1 April 2027 [Page 77] Internet-Draft CAID September 2026 [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-13, 11 September 2026, . [I-D.thallapelly-oasnt-caid] Thallapelly, A., "OASNT-CAID: Canonical Action Identifier Derivation and the Named-Human Binding", Work in Progress, Internet-Draft, draft-thallapelly-oasnt-caid-01, 5 August 2026, . [ICD-10-CM] Centers for Medicare & Medicaid Services and National Center for Health Statistics, "ICD-10-CM Official Guidelines for Coding and Reporting". [ISO3166-1] International Organization for Standardization, "Codes for the representation of names of countries and their subdivisions, Part 1: Country code", ISO 3166-1:2020, 2020. [ISO3166-2] International Organization for Standardization, "Codes for the representation of names of countries and their subdivisions, Part 2: Country subdivision code", ISO 3166-2:2020, 2020. [ISO4217] International Organization for Standardization, "Codes for the representation of currencies", ISO 4217:2015, 2015. [ISO20022] ISO 20022 Registration Authority, "ISO 20022 External Code Sets". [NACHA] Nacha, "Nacha Operating Rules". [NDC] U.S. Food and Drug Administration, "National Drug Code Directory". [RFC5730] Hollenbeck, S., "Extensible Provisioning Protocol (EPP)", STD 69, RFC 5730, DOI 10.17487/RFC5730, August 2009, . Schrock Expires 1 April 2027 [Page 78] Internet-Draft CAID September 2026 [RFC5936] Lewis, E. and A. Hoenes, Ed., "DNS Zone Transfer Protocol (AXFR)", RFC 5936, DOI 10.17487/RFC5936, June 2010, . [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, DOI 10.17487/RFC6838, January 2013, . [RFC6920] Farrell, S., Kutscher, D., Dannewitz, C., Ohlman, B., Keranen, A., and P. Hallam-Baker, "Naming Things with Hashes", RFC 6920, DOI 10.17487/RFC6920, April 2013, . [RFC7595] Thaler, D., Ed., Hansen, T., and T. Hardie, "Guidelines and Registration Procedures for URI Schemes", BCP 35, RFC 7595, DOI 10.17487/RFC7595, June 2015, . [RFC7696] Housley, R., "Guidelines for Cryptographic Algorithm Agility and Selecting Mandatory-to-Implement Algorithms", BCP 201, RFC 7696, DOI 10.17487/RFC7696, November 2015, . [RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, July 2016, . [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, . [RFC8141] Saint-Andre, P. and J. Klensin, "Uniform Resource Names (URNs)", RFC 8141, DOI 10.17487/RFC8141, April 2017, . [RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu, "Handling Long Lines in Content of Internet-Drafts and RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020, . [UNICODE] The Unicode Consortium, "The Unicode Standard", . Schrock Expires 1 April 2027 [Page 79] Internet-Draft CAID September 2026 [UTS39] The Unicode Consortium, "Unicode Security Mechanisms", Unicode Technical Standard #39, . Appendix A. Collected ABNF This appendix collects every grammar of this document in the ABNF of [RFC5234], with the case-sensitive string syntax of [RFC7405]. ALPHA, DIGIT, and HEXDIG are the core rules of [RFC5234]. Each rule matches a string as a whole. Part A.1 is the identifier and part A.2 the digest syntax of each suite. Part A.3 holds the lexical field types, and part A.4 the code formats that this document registers (Section 4.5), each named by its rule name. Part A.5 constrains definitions, part A.6 the mapping profile, and part A.7 accepts every reason of Appendix B, including nested forms such as mapped_action:missing_material_field:amount. A timestamp's day is further limited by the length of its month (Section 4.3). ; Collected ABNF [RFC5234] with case-sensitive strings [RFC7405]. ; A string matches a rule only as a whole: nothing precedes or ; follows it, not even a final line feed. ; A.1 Identifier caid = %s"caid" ":" caid-version ":" action-type ":" suite ":" digest ; at most 1024 octets, and its ; action-type at most 512 (2.6) caid-version = "1" action-type = 1*( name-segment "." ) type-version ; at most 512 octets (2.6) 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 ; A.2 Digest syntax per suite ; ; A suite whose digest is n octets encodes it in c = ceil(8n/6) Schrock Expires 1 April 2027 [Page 80] Internet-Draft CAID September 2026 ; base64url characters. The final character carries u = 6c - 8n ; unused low bits, which are zero: of the 64 base64url characters, ; only those whose 6-bit value is a multiple of 2^u may end the ; digest. For n = 32 (jcs-sha256 and cbor-sha256), c = 43 and ; u = 2. digest-256 = 42b64url-char b64url-z2 b64url-z2 = %x41 / %x45 / %x49 / %x4D / %x51 / %x55 / %x59 / %x63 / %x67 / %x6B / %x6F / %x73 / %x77 / %x30 / %x34 / %x38 ; A E I M Q U Y c g k o s w 0 4 8 ; A.3 Field types amount-string = [ "-" ] int-part [ "." frac-part ] int-part = "0" / ( %x31-39 *DIGIT ) ; no leading zero frac-part = 1*DIGIT digest-field = %s"sha256:" 64hex-lower hex-lower = DIGIT / %x61-66 ; 0-9 / a-f timestamp = full-date %x54 utc-time %x5A ; "T" and "Z" full-date = date-year "-" date-month "-" date-mday date-year = 4DIGIT date-month = "0" %x31-39 / "1" %x30-32 ; 01-12 date-mday = "0" %x31-39 / %x31-32 DIGIT / "3" %x30-31 ; 01-31, within the month utc-time = time-hour ":" time-minute ":" time-second [ time-fraction ] time-hour = %x30-31 DIGIT / "2" %x30-33 ; 00-23 time-minute = %x30-35 DIGIT ; 00-59 time-second = %x30-35 DIGIT ; 00-59, never 60 time-fraction = "." 1*DIGIT ; A.4 Code formats ; ; The rule name of each code format is its registered format name. ; A format fixes syntax only, never which codes exist. icd-10-cm = UALPHA 2UALNUM [ "." 1*4UALNUM ] ndc-11 = 11DIGIT ndc-10-hyphenated = 4DIGIT "-" 4DIGIT "-" 2DIGIT / 5DIGIT "-" 4DIGIT "-" 1DIGIT / 5DIGIT "-" 3DIGIT "-" 2DIGIT cpt = 4DIGIT ( DIGIT / UALPHA ) hcpcs-level-ii = UALPHA 4DIGIT Schrock Expires 1 April 2027 [Page 81] Internet-Draft CAID September 2026 hcpcs = cpt / hcpcs-level-ii iso-3166-2 = 2UALPHA "-" 1*3UALNUM iso20022-external-code = 1*4UALNUM nacha-sec = 3UALNUM UALPHA = %x41-5A ; A-Z UALNUM = UALPHA / DIGIT ; A.5 Definitions field-name = 1*field-char field-char = %x00-39 / %x3B-D7FF / %xE000-10FFFF ; any scalar value except ":"; a ; field name is also a string of ; the data model (2.2), so it ; holds no noncharacter format-name = lower-char *( lower-char / DIGIT / "-" ) ; the formats of this document: A.4 code-system = uri-scheme ":" 1*uri-char ; a scheme, ":", and URI characters: ; no fragment and no IP-literal ; host; at most 2048 octets (2.6) uri-scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) uri-char = ALPHA / DIGIT / "-" / "." / "_" / "~" / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" / ":" / "@" / "/" / "?" / pct-encoded pct-encoded = "%" HEXDIG HEXDIG ; A.6 Action-Mapping Profile json-pointer = *( "/" reference-token ) ; [RFC6901] source-path = "/" reference-token json-pointer ; a json-pointer other than "" reference-token = *( unescaped / escaped ) unescaped = %x00-2E / %x30-7D / %x7F-D7FF / %xE000-10FFFF escaped = "~" ( "0" / "1" ) array-index = "0" / ( %x31-39 *DIGIT ) hex-sha256 = 64hex-lower ; A.7 Reasons reason = core-reason / mapping-reason / comparison-reason Schrock Expires 1 April 2027 [Page 82] Internet-Draft CAID September 2026 core-reason = compute-reason / core-only core-only = %s"malformed_json" / %s"malformed_caid" / %s"action_type_mismatch" / %s"definition_mismatch" / %s"digest_mismatch" / %s"invalid_object" compute-reason = compute-bare / field-code ":" field-name compute-bare = %s"invalid_action_type" / %s"unknown_action_type" / %s"invalid_definition" / %s"unknown_suite" / %s"unsupported_number" / %s"unsupported_value" field-code = %s"missing_material_field" / %s"mistyped_field" / %s"invalid_amount" / %s"invalid_code" mapping-reason = mapping-bare / %s"unmapped_material_field" ":" field-name / pointer-code ":" source-path / %s"mapped_action" ":" compute-reason mapping-bare = %s"invalid_mapping_profile" / %s"unknown_action_type" / %s"invalid_definition" / %s"native_verification_required" / %s"mapping_profile_unpinned" / %s"source_format_mismatch" / %s"source_not_object" / %s"source_not_canonicalizable" / %s"declared_source_semantic_loss" pointer-code = %s"invalid_source_path" / %s"missing_source_field" / %s"source_value_type_mismatch" / %s"source_value_not_canonicalizable" / %s"unknown_transform" comparison-reason = ( %s"left" / %s"right" ) ":" mapping-reason / %s"target_action_type_mismatch" / %s"material_projection_mismatch" Appendix B. Reason Codes These tables list every reason. A reason with a parameter is the code, ":", and the parameter, which matches the ABNF rule named in the Parameter column. Computation and verification phases are those of Sections 5 and 6; "(gate)" marks a phase that yields exactly one reason. Decoding and parsing are single steps, named without a phase. Mapping stages are those of Section 8.3, and comparison prefixes a failed mapping's reasons with "left:" or "right:". A reason that computation and mapping stage A share is listed once, in the first table. These tables are the initial contents of the CAID Reason Codes registry (Section 12.5). Schrock Expires 1 April 2027 [Page 83] Internet-Draft CAID September 2026 +========================+============+==========================+ | Reason | Parameter | Operations and phases | +========================+============+==========================+ | malformed_json | none | decode; compute 0 | | | | (gate); verify 2 (gate) | +------------------------+------------+--------------------------+ | malformed_caid | none | parse; verify 1 (gate) | +------------------------+------------+--------------------------+ | unknown_suite | none | parse; compute 5; verify | | | | 1 (gate); verify 6 | +------------------------+------------+--------------------------+ | invalid_action_type | none | compute 1 (gate) | +------------------------+------------+--------------------------+ | unknown_action_type | none | compute 2 (gate); | | | | mapping stage A | +------------------------+------------+--------------------------+ | invalid_definition | none | compute 2 (gate); | | | | mapping stage A | +------------------------+------------+--------------------------+ | definition_mismatch | none | verify 5 | +------------------------+------------+--------------------------+ | missing_material_field | field-name | compute 3 | +------------------------+------------+--------------------------+ | mistyped_field | field-name | compute 4 | +------------------------+------------+--------------------------+ | invalid_amount | field-name | compute 4 | +------------------------+------------+--------------------------+ | invalid_code | field-name | compute 4 | +------------------------+------------+--------------------------+ | unsupported_number | none | compute 6 | +------------------------+------------+--------------------------+ | unsupported_value | none | compute 7 | +------------------------+------------+--------------------------+ | action_type_mismatch | none | verify 4 | +------------------------+------------+--------------------------+ | digest_mismatch | none | verify 6 | +------------------------+------------+--------------------------+ | invalid_object | none | verify 3 (gate); verify | | | | 7 | +------------------------+------------+--------------------------+ Table 10: Core Reasons Schrock Expires 1 April 2027 [Page 84] Internet-Draft CAID September 2026 +==================================+================+============+ | Reason | Parameter | Stage | +==================================+================+============+ | invalid_mapping_profile | none | A | +----------------------------------+----------------+------------+ | unmapped_material_field | field-name | A | +----------------------------------+----------------+------------+ | native_verification_required | none | B | +----------------------------------+----------------+------------+ | mapping_profile_unpinned | none | B | +----------------------------------+----------------+------------+ | source_format_mismatch | none | B | +----------------------------------+----------------+------------+ | source_not_object | none | B | +----------------------------------+----------------+------------+ | source_not_canonicalizable | none | B | +----------------------------------+----------------+------------+ | declared_source_semantic_loss | none | B | +----------------------------------+----------------+------------+ | invalid_source_path | source-path | C | +----------------------------------+----------------+------------+ | missing_source_field | source-path | C | +----------------------------------+----------------+------------+ | source_value_type_mismatch | source-path | C | +----------------------------------+----------------+------------+ | source_value_not_canonicalizable | source-path | C | +----------------------------------+----------------+------------+ | unknown_transform | source-path | C | +----------------------------------+----------------+------------+ | mapped_action | compute-reason | D | +----------------------------------+----------------+------------+ | target_action_type_mismatch | none | comparison | +----------------------------------+----------------+------------+ | material_projection_mismatch | none | comparison | +----------------------------------+----------------+------------+ Table 11: Mapping Reasons Appendix C. Worked Examples Every value in this appendix recomputes from the objects shown and the definitions of reference registry version 5 [CAID-REGISTRY], with the enum snapshots archived beside it at the same commit (Section 12.2). Long lines are folded as specified in [RFC8792]. Schrock Expires 1 April 2027 [Page 85] Internet-Draft CAID September 2026 C.1. Computation This payment.release.1 action object: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "action_type": "payment.release.1", "amount": "250.00", "currency": "EUR", "beneficiary_account": "sha256:9f86d081884c7d659a2feaa0c55ad015a3b\ f4f1b2b0b822cd15d6c15b0f00a08", "payment_instruction_id": "pi-2026-000117", "memo": "invoice 4471" } has members in a different order from its canonical encoding, which sorts them. Its RFC 8785 encoding is 230 octets: =============== NOTE: '\' line wrapping per RFC 8792 ================ {"action_type":"payment.release.1","amount":"250.00","beneficiary_ac\ count":"sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6\ c15b0f00a08","currency":"EUR","memo":"invoice 4471","payment_instruc\ tion_id":"pi-2026-000117"} Computation under jcs-sha256 returns the CAID, the SHA-256 digest of those octets, and the definition_sha256 of payment.release.1 in registry version 5: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "caid": "caid:1:payment.release.1:jcs-sha256:liLG9pKgkLt3silrjf1wa\ 0xIHz5YFrBB9HI-arxrO1Y", "digest": "sha256:9622c6f692a090bb77b2296b8dfd706b4c481f3e5816b041\ f4723e6abc6b3b56", "definition_sha256": "sha256:3a5ad4c0a3a8dbf7eb9ea5f4c3b2ceb07ba19\ 72fac49acc6006dcac64726ff12" } Under cbor-sha256, the core deterministic CBOR encoding of the same object is 207 octets. Its map keys sort by their encoded octets, so shorter keys come first and the members appear in the order memo, amount, currency, action_type, beneficiary_account, and payment_instruction_id, which differs from the RFC 8785 order. In hexadecimal, 32 octets to a line: Schrock Expires 1 April 2027 [Page 86] Internet-Draft CAID September 2026 a6646d656d6f6c696e766f696365203434373166616d6f756e74663235302e30 306863757272656e6379634555526b616374696f6e5f74797065717061796d65 6e742e72656c656173652e317362656e65666963696172795f6163636f756e74 78477368613235363a3966383664303831383834633764363539613266656161 3063353561643031356133626634663162326230623832326364313564366331 356230663030613038767061796d656e745f696e737472756374696f6e5f6964 6e70692d323032362d303030313137 Computation under cbor-sha256 returns this result; the definition_sha256 does not depend on the suite: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "caid": "caid:1:payment.release.1:cbor-sha256:7bBO8giRaW3iBRR-C6cZ\ FnqkRjAPTwTPMrvwd-200vY", "digest": "sha256:edb04ef20891696de205147e0ba719167aa446300f4f04cf\ 32bbf077edb4d2f6", "definition_sha256": "sha256:3a5ad4c0a3a8dbf7eb9ea5f4c3b2ceb07ba19\ 72fac49acc6006dcac64726ff12" } C.2. Refusal and Reason Order This object lacks two required fields, carries an amount with a leading zero, and carries a fractional number in the optional memo field: { "action_type": "payment.release.1", "amount": "01.50", "currency": "EUR", "memo": 7.5 } Computation refuses it. The missing fields come first, in required_fields order; then the phase 4 reasons in field order, where amount is field 0 and memo, the first optional field, is field 4; then unsupported_number for the fractional value: Schrock Expires 1 April 2027 [Page 87] Internet-Draft CAID September 2026 { "refusals": [ "missing_material_field:beneficiary_account", "missing_material_field:payment_instruction_id", "invalid_amount:amount", "mistyped_field:memo", "unsupported_number" ] } C.3. Verification Details Verifying the CAID of Appendix C.1 against the object of Appendix C.2 yields invalid_object. The action types match, and no digest comparison is made because the object cannot be canonicalized. The details expand invalid_object into its computation reasons, and definition_sha256 is reported because a conforming definition resolved: Schrock Expires 1 April 2027 [Page 88] Internet-Draft CAID September 2026 =============== NOTE: '\' line wrapping per RFC 8792 ================ { "valid": false, "reasons": [ "invalid_object" ], "details": [ { "reason": "missing_material_field:beneficiary_account", "field": "beneficiary_account", "rule": "required-field", "observed": "absent" }, { "reason": "missing_material_field:payment_instruction_id", "field": "payment_instruction_id", "rule": "required-field", "observed": "absent" }, { "reason": "invalid_amount:amount", "field": "amount", "rule": "amount-string", "observed": "string" }, { "reason": "mistyped_field:memo", "field": "memo", "rule": "field-type", "observed": "number" }, { "reason": "unsupported_number", "field": null, "rule": "number", "observed": null } ], "definition_sha256": "sha256:3a5ad4c0a3a8dbf7eb9ea5f4c3b2ceb07ba19\ 72fac49acc6006dcac64726ff12" } Schrock Expires 1 April 2027 [Page 89] Internet-Draft CAID September 2026 C.4. Definition Digest The validation projection of the tool.call.1 definition of Section 4.7 keeps action_type, required_fields, and optional_fields, drops the definition's other members (status, risk_class, summary, digest_notes, and references), and drops the notes member of every field entry. Its RFC 8785 encoding is: =============== NOTE: '\' line wrapping per RFC 8792 ================ {"action_type":"tool.call.1","optional_fields":[{"name":"occurrence_\ id","type":"string"}],"required_fields":[{"name":"target","type":"st\ ring"},{"name":"tool","type":"string"},{"name":"args","type":"object\ "}]} and its definition_sha256 is: =============== NOTE: '\' line wrapping per RFC 8792 ================ sha256:c95e21136fd8b6df646be2957fe42fbf18935add20da6bc9569aa2d1a771a\ fa2 C.5. Code Fields prior.auth.approve.2 carries a HCPCS code in service_code (format hcpcs) and an ICD-10-CM code in diagnosis_code (format icd-10-cm). This object computes: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "action_type": "prior.auth.approve.2", "patient_ref": "sha256:8d3148217a50cc7dc5c03c79a8932e5bf60dde17db0\ b3af90c9fed46d0c47e76", "service_code": "E0601", "diagnosis_code": "G47.33", "authorization_number": "PA-2026-000418", "valid_from": "2026-10-01T00:00:00Z", "valid_until": "2026-12-31T23:59:59Z" } Schrock Expires 1 April 2027 [Page 90] Internet-Draft CAID September 2026 =============== NOTE: '\' line wrapping per RFC 8792 ================ { "caid": "caid:1:prior.auth.approve.2:jcs-sha256:j7WskhX5l_V70KUTEf\ d1ysXivWV5oFT1q-J1Tvra57U", "digest": "sha256:8fb5ac9215f997f57bd0a51311f775cac5e2bd6579a054f5\ abe2754efadae7b5", "definition_sha256": "sha256:c25345a298c9b0ec96d019e4e2bcfd6ddd259\ ad064a7cb75b581999eaaf10086" } The same object with the codes written "e0601" and "G4733" is refused, because no format folds case or inserts a dot: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "action_type": "prior.auth.approve.2", "patient_ref": "sha256:8d3148217a50cc7dc5c03c79a8932e5bf60dde17db0\ b3af90c9fed46d0c47e76", "service_code": "e0601", "diagnosis_code": "G4733", "authorization_number": "PA-2026-000418", "valid_from": "2026-10-01T00:00:00Z", "valid_until": "2026-12-31T23:59:59Z" } { "refusals": [ "invalid_code:service_code", "invalid_code:diagnosis_code" ] } C.6. Mapping Under the profile of Section 8.2, with a native verification result of the boolean true, a source descriptor equal to the profile's source_format, and the profile digest pinned, this source: Schrock Expires 1 April 2027 [Page 91] Internet-Draft CAID September 2026 { "checkout": { "order_id": "ord-7781", "merchant_id": "merchant-17", "total_amount": "129.95", "currency": "USD", "line_items": [ { "sku": "A-1", "qty": 2 } ], "customer_id": "cust-42", "fulfillment": { "method": "ship", "postal_code": "94107" } }, "channel": "web" } projects to this order.place.1 action object. The channel member is not a material source path and is not mapped: =============== NOTE: '\' line wrapping per RFC 8792 ================ { "action_type": "order.place.1", "order_id": "ord-7781", "merchant_ref": "sha256:9a52791e954783da73f738762755102e10296f3cfd\ 07cebae3ed4fd540d82074", "total_amount": "129.95", "currency": "USD", "items_digest": "sha256:82cff441e6205b34ff18c69acdd583fe265b410b61\ 48f22c40bfcfbbcb117c75", "customer_ref": "sha256:8a3c5a67cad508582b5edf6b8352cea3ffbad7f448\ 12c1a736b4444c0f5746aa", "fulfillment_ref": "sha256:35a83b30c4e6d088acc77990cf683e55d8f101c\ 3d5570a8913528039cdb29f3c" } The mapping result carries these digests and this CAID: Schrock Expires 1 April 2027 [Page 92] Internet-Draft CAID September 2026 =============== NOTE: '\' line wrapping per RFC 8792 ================ { "profile_digest": "sha256:ec833ebc5793db1cc25e917fb838856c048bedee\ eb35ff7cb2d172943b0732fa", "source_digest": "sha256:371f6feb2f3d9767efe4190f25e0ba7b82208d9bc\ 916cf1114c84b0c396feaf9", "caid": "caid:1:order.place.1:jcs-sha256:UI-wYRrJp-P5iI5a2E2qKfT7_\ -ijOogjNoN-wjwIEcg" } Appendix D. Action Types of Reference Registry Version 5 This appendix lists the 62 type versions of registry version 5 of the reference registry [CAID-REGISTRY] in two parts: Appendix D.1, the initial contents of the CAID Action Types registry (Section 12.2), and Appendix D.2, the entries that IANA is not asked to register. Each entry is one line with the action type, the status, and, for a deprecated type, "successor" and the type that its superseded_by member names, followed by an indented line with the 64 hexadecimal digits that follow "sha256:" in its definition_sha256 (Section 4.2.2). The definition of each entry is the entry with the same name in the registry file; Section 4.7 reproduces the tool.call.1 entry member for member. D.1. Initial IANA Entries These 54 entries, 45 active and 9 deprecated, are the initial contents of the CAID Action Types registry. payment.release.1 active 3a5ad4c0a3a8dbf7eb9ea5f4c3b2ceb07ba1972fac49acc6006dcac64726ff12 payment.refund.1 deprecated, successor payment.refund.2 4fd20a272ef42f027c832b3cab3500219d695f2516e030a1d9cb1c1402a17df3 payment.refund.2 active 9421a7b0166e9c4e69aa1d166c779b93cff1236ae4940ee883d75cb45d2bdb50 payout.batch.execute.1 active f717a2a675fc94abf61cad351a6e7698da335b8bce18ece4f904cb3f3d873c3b wire.transfer.1 active 29ae2cafd17694e2ca65096bfc7cbd86c8c309082e7e9fc8cf92b67928fdfef2 ach.debit.originate.1 deprecated, successor ach.debit.originate.2 b3875a1ee1855fd8ab9a8481578af72f13e151a8297c283ec3a68ea9c482b4ee ach.debit.originate.2 active 2ac0e6c6cbd6c8c0acc5ac4b71f9aaeb0adb9ed7511b5b7d0bf11b90425b7aba iam.role.grant.1 active 24950ca02a77db28221df4f2e2bb81b20162ac9c7f8c5cc75db306374606509a iam.role.revoke.1 active 7ed8339092856720580669a5e2692cb4350f37ddafd97afad51672043e2163ea Schrock Expires 1 April 2027 [Page 93] Internet-Draft CAID September 2026 iam.user.delete.1 active f5365e3dc46b2a04b9e804d5921b5debc129a9eee0d1b916679fdf9232ce068f key.create.1 deprecated, successor key.create.2 739b77a1dbf3fd164f2ed047368bd8cdc55757c3a840db9140f43dc923111778 key.create.2 active a6fcdb0e1644ad65449ba2bfe48baea60cd97f8ed1063f15fb5510b1affe1c5c key.delete.1 active 2840d845e32c5f09b3ba2a2b952a2ef495a2f28180a23e33bacf39a6d37ba3cd key.rotate.1 deprecated, successor key.rotate.2 f2c43de398bc9d1bd62554f867fdec194cb07bb241415d6dc8165f860a32725d key.rotate.2 active d0aa8847da551efe214d27c3e5fe0a341654b8682b0dc03e30c64242142a24aa mfa.disable.1 active dc15633426de52ba4862948414a50182105ed839cc7c221ca46ac95913b19b8d dns.record.delete.1 active 0b320a2b0e944df0820439683032e2ce216c6601300d71368cd6cbc2245cc9e4 instance.terminate.1 active ebb2e0a621a000f7dced69226a60ffc0b034781b412fceb99fc147414de782c4 cluster.delete.1 active 25345b085c2bc02d92eeb5c909ec035d327eef33f0f1b0f56e890a0f26b9be29 firewall.rule.open.1 deprecated, successor firewall.rule.open.2 4a768f2ed30354b053c40f3b6ca0bfdd4dc29d78fc5b6d5558f8f6970e890e8a firewall.rule.open.2 active 254b72b169a6675fed28ff2e5da97a10cb0332965ab222deccd3c48ffa8d2f74 storage.bucket.public.1 active fab030e96ff68a3ccf2b9ce53a732ed95d8c2053d95f1a826b8da19a8b9e8aa1 dataset.delete.1 active 1caf662180cbfc278f9d8d4549481b22198ea77d72243bef0accebc48663f0bf backup.delete.1 active 4cd79cec67565c65f7c99e14fc3b36a6ac18a352a9bf7d9f9475bd300f0b5d15 retention.policy.override.1 active cbc581e8642f85425b300bef9c83c7ed86b04b998aaf0b62d72ebc2d3fbed508 pii.export.1 deprecated, successor pii.export.2 842fd0e6d0f7c7ec168e6c29fa992230dea8da1dcb8295e4b56e044eea6e1648 pii.export.2 active fbef9a2810f87e8df07c84c0a71964f4f4606408df59a5d302dc22ca70556075 email.send.external.1 active 04c79261361a0db6caf4a2c69a19a3b9d19a39c5df7e3fb7ace8d29fe100d589 announcement.publish.1 active ed2f14b052e7ac7ba84c58391cf360176a8084b37cca55cd86faba4f2c551890 social.post.publish.1 active f56db5382d2a7ca5a7640664408778c1b6b4da8a632978a6337872ab08a16459 press.release.distribute.1 active 33b97769d9edbad183d13907468dbfaa85010629c305aaa70d8c0dc44814557a package.publish.1 active 31af7ddad65e14e9b5577e812934db3098fe8c23e53468e3ac0476aac110818b release.deploy.prod.1 active 103c8410093d6b0d15994a65e2cc3afbb725fc5c1db229178c743019a1448de7 Schrock Expires 1 April 2027 [Page 94] Internet-Draft CAID September 2026 secret.rotate.1 active 5244e9721e4d97321bc45e2512860949092a650de0693f6ef48d11bf4704e527 repo.delete.1 active 8a18c77f7a211bfc64e64014d9f3ee8ab6122406d440a26ad180f7820baafb1f branch.protection.disable.1 active 6b0cf385a056e763c9a1a705ef96267af9c854ec0498e9e0828258a6daeb94a9 order.place.1 active 7ba6606177cad27ac3d12ac7875cf2b52e653229ccc3890097eb24129d0cac81 subscription.cancel.1 active 7ed8974c8f020de6aa6da1984f86a7feacbf4dcf4a859e170144d6143971e192 refund.issue.1 active f5819f5e049731f3490d8a3d0a19b4079ebc629c8370cc51e16095da9a3d506c listing.delist.1 active 8b14243a3c9cf02f6d92a4d725be08fd38f12e74be91c60a60291eb507aa4c73 contract.execute.1 active 468e056e3c1b3993af7cf0da05b7ab2c098421b25d631a792ac112ddb52fa250 contract.execute.2 active d1f43cb28204cae2d330abb9a51a8e7934a966c15eea10695149f904083b4dbc regulatory.filing.submit.1 active 4b57279dd56a3007fda65844f90c4ffd5271a884685f37c485154f00b1a16a73 legal.hold.release.1 active 9e8f90820e84ea12a51dac9ba678a66df2aaba3b64e1f77f53c14a1568cf0c0c rx.dispense.1 deprecated, successor rx.dispense.2 54d81e6db3cb38b0e5b8a53d476100558f4c211a074c2543423eb6cde38338f7 rx.dispense.2 active 943609964f09155f5509b045c23a7a0dc1003aec09f2d3b833cdf4fdabb79012 prior.auth.approve.1 deprecated, successor prior.auth.approve.2 7b1f54c3dde91b1c7faa656859021a775e27f2d36bbe88cf6a1deafe6deb6d76 prior.auth.approve.2 active c25345a298c9b0ec96d019e4e2bcfd6ddd259ad064a7cb75b581999eaaf10086 phi.disclose.1 deprecated, successor phi.disclose.2 bde03fd967ff8129af1b9ed23a6de6259ecc3dde0ac0a88b7ef06d74f28c8b69 phi.disclose.2 active 23beb6c5da8d75d8443b314ef59fd46459b9d1378d6356fbb721cbf6e985ef80 benefit.disburse.1 active 5b5fbca19b3c59a0fa3594b67f8321ed02b5f1473b2ab739b2359f8de589ef76 invoice.approve.1 active 2a5424eb4ac66ff7bdd1e10473c7c0384e5ea9d1b8645b8f2a022a30e77a05f3 vendor.onboard.1 active 716562ad88964db0c27e99594917e55a624565ccabb051ef293707984fde3dcc tool.call.1 active c95e21136fd8b6df646be2957fe42fbf18935add20da6bc9569aa2d1a771afa2 Schrock Expires 1 April 2027 [Page 95] Internet-Draft CAID September 2026 D.2. Reference-Registry Entries Not Requested of IANA These 8 entries, all active, stay in registry version 5 unchanged member for member (their RFC 8785 encodings are identical), so that an object valid under registry version 4, which carries them, stays valid (Section 4.1), but IANA is not asked to register them. emilia.mobile.authorized-action.1 is named for a product of the author's organization and is defined by that organization's specification. agent.state.export.1, agent.state.import.1, agent.state.key-release.1, and agent.state.retire-source.1 are defined by another specification of the author's organization, science.bio.experiment.execute.1 by another Internet-Draft of the author, and travel.cancel-notify.1 by an Internet-Draft that the author did not write; this document defines none of them. dns.zone.transfer.1 defines a registrar transfer of a domain under the Extensible Provisioning Protocol [RFC5730], not a DNS zone transfer [RFC5936], and a registered name is never reassigned. Each of the seven types defined by other specifications may be registered under Specification Required (Section 12.2) with its own specification and change controller, and the type emilia.mobile.authorized-action.1, whose first segment names an organization, only with that organization as its change controller. dns.zone.transfer.1 is not to be registered: the path for the registrar-transfer type is a successor whose name describes it. dns.zone.transfer.1 active b83fb16d90f9c61eedb802454b150cd5f2ee841b493935e5adcf2361b9575279 travel.cancel-notify.1 active 1599e98a6409c57ef3d022d586f4eb21bc7821a75f3316e2e6ae2a5e509d39c1 science.bio.experiment.execute.1 active e80d210c9e009a1e1e1bd6ec4d2afa902d0620ac10eaab51d4e49c25e744a819 emilia.mobile.authorized-action.1 active a3007f508e4d84e07a7c90a728496a5665f893919f2c7cde25de96c98d50fcb7 agent.state.export.1 active 057c9aee5a661416e510bc620f0bbb6efdf3870a92ca389d535bbf0064b67285 agent.state.import.1 active e539901b9f14afe604952b0cd071337bb6269ab5d1d11ceee2a1292e46c9ab32 agent.state.key-release.1 active 939f6a2b8ccfb4fed835e6bac211681b7ec51032270761c19b711f349839386f agent.state.retire-source.1 active d95b4a14ab5b7989bbc0d0047acf564648b381e1f48e0cc1411d8d911018a365 Schrock Expires 1 April 2027 [Page 96] Internet-Draft CAID September 2026 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 discussions also benefited from A. Thallapelly's OASNT-CAID profile and its explicit treatment of profile-local identifier comparison. 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 1 April 2027 [Page 97]