Verifiable Attenuated Delegation for AI Agent Chains
draft-asor-wimse-agent-delegation-chain-03
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Rafael Asor | ||
| Last updated | 2026-10-27 | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-asor-wimse-agent-delegation-chain-03
WIMSE R. Asor
Internet-Draft Attenu
Intended status: Standards Track 27 October 2026
Expires: 30 April 2027
Verifiable Attenuated Delegation for AI Agent Chains
draft-asor-wimse-agent-delegation-chain-03
Abstract
AI agents increasingly delegate tasks to other agents. Each
delegation should convey only a subset of the delegating party's
authority, that subset should be bounded in scope, magnitude, and
time, and any enforcement point should be able to verify -- offline,
with no call to an authorization server -- that a token presented at
hop N carries authority no greater than the token at hop N-1, back to
a trusted root, and that every hop acts under the same accountable
principal. OAuth 2.0 Token Exchange (RFC 8693) models two-party
delegation and records prior actors in a nested "act" claim, but that
claim is informational only and cannot enforce attenuation across a
chain of depth two or more. This document defines the Agent
Delegation Chain: a profile of OAuth 2.0 JWT access tokens (RFC 9068)
that carries authority as Rich Authorization Requests (RFC 9396),
binds the chain to one principal and names the agent acting at each
hop, links each delegation to its parent by a cryptographic byte-
commitment, and specifies a deterministic offline verification
algorithm that enforces monotonic attenuation, bounded depth,
monotonic expiry, and principal invariance. It reuses existing JOSE,
proof-of-possession (RFC 9449), and status-list machinery (the OAuth
Status List draft) and introduces no new cryptography.
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 30 April 2027.
Asor Expires 30 April 2027 [Page 1]
Internet-Draft Agent Delegation Chain October 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 . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. The gap in existing mechanisms . . . . . . . . . . . . . 3
1.2. Relationship to the OAuth actor drafts . . . . . . . . . 4
2. Conventions and Definitions . . . . . . . . . . . . . . . . . 5
3. Token Format . . . . . . . . . . . . . . . . . . . . . . . . 6
3.1. Principal and Acting Agent . . . . . . . . . . . . . . . 7
4. Authority Representation . . . . . . . . . . . . . . . . . . 8
4.1. Scope Syntax and Wildcards . . . . . . . . . . . . . . . 8
4.2. Constraint Vocabulary . . . . . . . . . . . . . . . . . . 10
4.3. Subsumption Rules . . . . . . . . . . . . . . . . . . . . 11
4.4. Authorization Detail Types and the Verifier . . . . . . . 12
4.5. Open Issue: Scope Vocabulary . . . . . . . . . . . . . . 13
5. Chain Linkage . . . . . . . . . . . . . . . . . . . . . . . . 14
6. Offline Verification Algorithm . . . . . . . . . . . . . . . 14
6.1. What Verification Establishes . . . . . . . . . . . . . . 16
6.2. Verification Outcomes . . . . . . . . . . . . . . . . . . 18
6.3. Several Chains Reaching One Agent . . . . . . . . . . . . 20
6.4. Open Issue: Trust-Anchor Provenance . . . . . . . . . . . 20
7. Holder Binding . . . . . . . . . . . . . . . . . . . . . . . 21
8. Revocation . . . . . . . . . . . . . . . . . . . . . . . . . 22
9. Security Considerations . . . . . . . . . . . . . . . . . . . 22
9.1. Parent tokens remain valid after attenuation . . . . . . 22
9.2. Chain splicing . . . . . . . . . . . . . . . . . . . . . 23
9.3. Confused deputy and over-broad delegation . . . . . . . . 23
9.4. Unbounded depth, fan-out, and aggregate budgets . . . . . 23
9.5. Offline verification vs. revocation latency . . . . . . . 24
9.6. Why not macaroons; algorithm agility . . . . . . . . . . 25
9.7. Root issuance is the policy decision point . . . . . . . 25
10. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 26
11. Implementation Status . . . . . . . . . . . . . . . . . . . . 26
12. References . . . . . . . . . . . . . . . . . . . . . . . . . 27
12.1. Normative References . . . . . . . . . . . . . . . . . . 27
Asor Expires 30 April 2027 [Page 2]
Internet-Draft Agent Delegation Chain October 2026
12.2. Informative References . . . . . . . . . . . . . . . . . 29
Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . 32
Appendix B. Reference Implementation and Test Vectors . . . . . 34
Appendix C. Changes Since -02 . . . . . . . . . . . . . . . . . 35
Appendix D. Changes Since -01 . . . . . . . . . . . . . . . . . 36
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 38
1. Introduction
An AI agent that receives a task from a user or another agent
frequently decomposes it and delegates sub-tasks to further agents or
tools. In production deployments this produces delegation chains of
depth greater than two. The security requirement is a single
invariant: the authority exercised at any hop MUST be a subset of the
authority granted at the hop that delegated to it, and this MUST be
verifiable by the enforcement point that ultimately honors a tool
call, without that point contacting an authorization server.
1.1. The gap in existing mechanisms
OAuth 2.0 Token Exchange [RFC8693] defines delegation and
impersonation semantics and a nestable "act" claim. However,
[RFC8693] Section 4.1 states that a recipient considers only the top-
level claims and the current (outermost) actor; the nested chain is
history for audit, not enforced authority. Token Exchange also
normally contacts the authorization server at each hop. Neither
property supports offline, enforced, depth >= 2 attenuation.
Cross-domain identity chaining (see
[I-D.ietf-oauth-identity-chaining]) and transaction tokens address
related but distinct problems (crossing trust domains and propagating
immutable context within one domain, respectively) and explicitly do
not provide chained cryptographic attenuation.
Capability systems that do provide offline attenuation -- macaroons
[Macaroons], Biscuit [Biscuit] -- either verify with a shared secret
(macaroons: symmetric HMAC, so every verifier holds the minting key)
or use a non-IETF wire format (Biscuit: protocol buffers with an
embedded Datalog engine). The historical standards-track ancestor is
SDSI/SPKI [RFC2693].
This document fills the gap by reusing the JOSE/OAuth stack and
adding only the chain linkage, the principal binding, and the
subsumption-enforcing verification algorithm. It is designed as the
attenuation mechanism satisfying requirements R1 and R5 of
[I-D.reece-wimse-cross-org-delegation] and as a companion to
[I-D.ietf-wimse-aims], whose placement of the acting agent in
"client_id" and the on-behalf-of party in "sub" this profile follows.
Asor Expires 30 April 2027 [Page 3]
Internet-Draft Agent Delegation Chain October 2026
It shares its approach with, and is intended to converge with,
[I-D.niyikiza-oauth-attenuating-agent-tokens] and
[I-D.coetzee-oauth-spt-txn-tokens]. Its offline verification model
is complementary to the online Delegation Server and synchronous
revocation model in [I-D.sweeney-wimse-credential-delegation]. The
two are halves of one design, separated by a single axis: whether a
server is in the path. The in-token mechanisms this document
requires -- constraints carried in the token, parent-hash
verification, and a child expiry bounded by its parent's -- are how a
verifier with no network reconstructs what such a server would
otherwise know first-hand; where a server is in every hop, they are
redundant rather than absent. The verifier-side evaluation rules of
[I-D.jackson-wimse-evaluation] describe the receiving half of the
same problem; this document cites that work informatively, and no
requirement here depends on it.
1.2. Relationship to the OAuth actor drafts
Two individual Internet-Drafts directed to the OAuth working group
record who acted along a delegation and are complementary to this
document. [I-D.mcguinness-oauth-actor-profile] represents delegated
actors in the "act" claim of OAuth 2.0 Token Exchange [RFC8693]: the
outermost actor is the immediate actor, inner actors are prior-actor
context preserved for audit and not inputs to access-control
decisions, and the authorization server that extends a chain confirms
that the new actor is authorized to act for the subject, enforces a
locally configured maximum depth, and issues a token whose effective
scope does not exceed the scope ceiling, if any, that the profile
assigns to the inbound subject token. [I-D.mw-oauth-actor-chain]
builds on the same "act" claim and adds, in its verified profiles, an
actor proof and an authorization server acceptance at every actor
step and a salted commitment to the actor-visible path, and in its
verified-full profile optional path evidence that a recipient
validates from the root to the current actor; its path validation
applies the scope comparison to the final step and does not compare
different hops' resource identifiers as if they had subset semantics.
In both, the authorization server bounds the authority of the token
it issues at each exchange, and the resource server applies its own
authorization policy when the token is used. A recipient can check
which actors took part, as the issuer asserts them in "act" or, in
the verified profiles of [I-D.mw-oauth-actor-chain], through actor
proofs and acceptances, and, as that draft's Section 8 states,
without a retained historical token path evidence does not
reconstruct that token's effective authority. This document bounds
what each hop may do in the chain itself: every token carries its
Authority, each child commits to its parent, and any holder of the
chain can check at step 4 of Section 6 that each hop's Authority is a
Asor Expires 30 April 2027 [Page 4]
Internet-Draft Agent Delegation Chain October 2026
subset of its parent's, with no authorization server present at
verification. A deployment that wants an authorization server's
record of actors as well as an offline-checkable bound on authority
can carry an "act" chain beside a Delegation Chain, whose "client_id"
already names the acting agent at each hop (Section 3.1); this
document places no requirement on an "act" claim and defines no
mapping between the two.
2. Conventions and Definitions
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.
Delegation Token (DT): An OAuth 2.0 JWT access token [RFC9068]
profiled by this document, carrying the authority granted to one
agent at one hop of a chain.
Delegation Chain: An ordered sequence of Delegation Tokens DT_0,
DT_1, ... DT_n, where DT_0 is the root, and each DT_i (i > 0) is
linked to DT_{i-1} by the mechanism in Section 5. A chain is one
path. An agent that holds tokens issued along several paths holds
several chains; see Section 6.3.
Principal: The party accountable for the chain: the party whose
grant every token in the chain acts under. Carried in "sub",
identical at every hop (Section 3).
Acting Agent: The agent that holds, and acts under, one Delegation
Token. Carried in "client_id", which names the agent acting at
each hop.
Authority: The set of permitted scope values carried by an
"agent_delegation" authorization detail in the
"authorization_details" claim [RFC9396], together with the
constraints in Section 4.2.
Attenuation: The construction of a child Delegation Token whose
Authority is a subset of its parent's, per the subsumption rules
in Section 4.3.
Enforcement Point: The component that verifies a Delegation Chain
and permits or denies an action.
Verifier: Any component that runs the algorithm of Section 6,
Asor Expires 30 April 2027 [Page 5]
Internet-Draft Agent Delegation Chain October 2026
whether or not it is presented with an action. An Enforcement
Point is a Verifier that is presented with an action and decides
it.
3. Token Format
A Delegation Token is a JWT [RFC7519] signed with JWS [RFC7515] using
a fully-specified algorithm [RFC9864]. Implementations MUST support
Ed25519 [RFC8032] [RFC8037] and MAY support ES256 and, for post-
quantum readiness, ML-DSA [RFC9964]. The token uses the
"application/at+jwt" header type of [RFC9068] and includes the claims
that profile requires: "iss", "exp", "aud", "sub", "client_id",
"iat", and "jti". The protected header SHOULD contain "c14n": "JCS"
as an informational label. Verifiers MUST NOT rely on this field.
The canonicalization of the protected header and payload JSON is the
JSON Canonicalization Scheme (JCS) [RFC8785]: producers MUST
serialize both with JCS before base64url encoding, and verifiers MUST
reject either decoded byte string unless it is exactly the JCS
serialization of the parsed object. Verifiers MUST also reject
duplicate object member names, non-finite numbers, and lone UTF-16
surrogates. Because JCS numbers are IEEE 754 binary64 values, an
integer whose magnitude exceeds 2^53-1 is not represented exactly;
producers MUST NOT emit one, and verifiers MUST reject a token
carrying one as malformed.
The [RFC9068] claims carry the following meaning in a Delegation
Token:
sub: REQUIRED. The Principal. [RFC9068] Section 2.2 makes "sub"
the resource owner where one exists; in a Delegation Chain the
resource owner is the party whose grant the chain acts under, and
the same value MUST appear in every DT_i of the chain. A verifier
denies a chain in which any DT_i carries a "sub" that differs from
DT_0's (Section 6, step 3). A chain whose DT_0 carries no "sub",
or a "sub" that is not a non-empty string, is malformed.
client_id: REQUIRED. The Acting Agent at this hop, as a string. It
identifies which software exercised the authority; "sub"
identifies whose grant it exercised. The value MAY be a workload
identifier as defined by [I-D.ietf-wimse-identifier]; this
document places no requirement on its format beyond being a
string.
aud: REQUIRED. The audience, as [RFC7519] Section 4.1.3 defines it:
Asor Expires 30 April 2027 [Page 6]
Internet-Draft Agent Delegation Chain October 2026
a string, or an array of one or more strings. A token whose "aud"
is absent, null, or an empty array is malformed. The Enforcement
Point applies the audience check of [RFC9068] Section 4 to DT_n
(Section 6, step 8); this document places no requirement on the
audience of DT_i for i < n beyond presence and shape.
iss, exp, iat, jti: REQUIRED, as in [RFC9068]. "exp" is additionally
subject to the monotonic expiry rule of Section 4.3. "jti"
identifies the token instance for the purposes of Section 5 and of
per-lifetime constraints (Section 4.2).
In addition, a Delegation Token contains:
authorization_details: REQUIRED. An array of authorization detail
objects [RFC9396] expressing the Authority. See Section 4.
cnf: REQUIRED. A confirmation claim [RFC7800] binding the token to
the holder's key, proven per DPoP [RFC9449]. See Section 7.
del_depth: REQUIRED. A non-negative integer; the position of this
token in the chain. DT_0 has del_depth 0.
del_max_depth: REQUIRED in DT_0. A positive integer; the maximum
permitted chain length. MUST NOT be increased by any child (see
Section 4.3).
par_hash: REQUIRED in every DT_i with i > 0; MUST be absent in DT_0.
The base64url-encoded SHA-256 digest of the parent token's JWS
Signing Input ([RFC7515] Section 5.1), i.e. of the exact bytes
"ASCII(BASE64URL(parent JOSE Header)) || '.' ||
ASCII(BASE64URL(parent JWS Payload))". This is the byte-
commitment that binds a child to one specific parent and prevents
chain splicing.
3.1. Principal and Acting Agent
A Delegation Chain answers two questions that a holder key alone does
not: who is accountable for what the chain does, and which agents
took part. The first is answered by "sub", which names the Principal
and is invariant along the chain: a child token is issued under the
same grant as its parent, so it names the same Principal, and a token
that names a different one is not a member of the chain. The second
is answered by "client_id", which names the agent acting at each hop.
Together they make a chain auditable as well as verifiable.
The "par_hash" commitment (Section 5) already prevents a child from
being re-parented onto a different token. It does not, by itself,
prevent a child from carrying a different "sub" than its parent,
Asor Expires 30 April 2027 [Page 7]
Internet-Draft Agent Delegation Chain October 2026
because the child is a new token with its own payload. The
invariance check in step 3 of Section 6 is what closes that gap, and
it is a comparison of two strings, not new machinery.
This revision defines no transition mode for chains shaped by the
-01. A chain whose tokens carry no "client_id" or no "cnf", or whose
"aud" is null, is malformed under this revision. A verifier that
also accepts such chains under the -01's rules does so outside this
document and reports which revision's rules it applied.
4. Authority Representation
For this profile, Authority is expressed by an authorization detail
object [RFC9396] whose "type" is "agent_delegation". A Delegation
Token MUST carry exactly one authorization detail object, and its
type MUST be "agent_delegation"; a token carrying a second detail, or
a detail of any other type, is malformed (Section 4.4). The object
contains a REQUIRED "scopes" member: an array of strings, where each
string names one permitted operation. An empty array conveys no
permitted operation. Numeric and enumerated bounds ("ceilings") that
[RFC9396] does not standardize are carried in the "constraints"
member defined here. The object MUST NOT carry members other than
"type", "scopes", and "constraints"; a verifier that encounters
another member MUST reject the token as malformed, because it would
otherwise report success on a detail it had not fully read.
4.1. Scope Syntax and Wildcards
Each member of "scopes" MUST match the following ABNF [RFC5234]:
lower = %x61-7A
digit = %x30-39
segment = lower *(lower / digit / "_" / "-")
literal-scope = segment "." segment *("." segment)
wildcard-scope = segment *("." segment) ".*"
opaque-scope = 1*( %x21 / %x23-29 / %x2B-5B / %x5D-7E )
scope = literal-scope / wildcard-scope / opaque-scope
The "opaque-scope" form is the "scope-token" of [RFC6749] Section 3.3
with the asterisk (%x2A) removed. It exists so that a chain can
carry a scope string issued by an OAuth authorization server under
that server's own naming, which the two structured forms do not
admit.
A verifier classifies each scope value by its bytes alone, trying the
forms in this order: a value that matches "literal-scope" is a
literal scope; otherwise, a value that matches "wildcard-scope" is a
wildcard scope; otherwise, a value that matches "opaque-scope" is an
Asor Expires 30 April 2027 [Page 8]
Internet-Draft Agent Delegation Chain October 2026
opaque scope. A value that matches none of the three, for example
one that contains an asterisk anywhere other than as a complete final
segment following a dot, is invalid. Thus crm.read is a literal
scope, crm.* is a wildcard scope, User.Read and openid are opaque
scopes, and the bare value *, the partial-segment form crm.re*, and
the non-terminal form crm.*.read are invalid. A producer MUST NOT
emit an invalid scope. A verifier that encounters one MUST reject
the Delegation Token as malformed before evaluating subsumption.
There is no case folding: User.Read and user.read are two different
scopes.
The covering relation between a parent scope and a child scope is:
* A parent literal scope covers only an identical child scope.
* A parent wildcard scope covers any child scope, literal or
wildcard, whose value begins with the parent value after removing
only the final * and retaining the dot. Therefore crm.* covers
"crm.read", "crm.x.y.z", and crm.x.*; it does not cover the bare
name "crm" or the adjacent namespace "crmx.read". Wildcard
coverage is segment-bounded and extends to any depth below the
named prefix, and a wildcard covers a narrower wildcard under its
prefix.
* A parent opaque scope covers only a byte-identical child scope.
No wildcard scope covers an opaque scope, and an opaque scope
covers no wildcard scope.
One consequence of classifying by bytes alone is stated here so that
deployments can plan for it: a scope string issued by an
authorization server that happens to match "literal-scope" is treated
as a literal scope, and a wildcard over its prefix covers it. A
deployment that needs such a scope to match exactly should not grant
a wildcard over its prefix; doing so also gives up wildcard coverage
for every other scope under that prefix. This document provides no
registry by which a verifier could tell a dotted provider string from
a structured literal, and does not add one.
This covering relation belongs to the "agent_delegation"
authorization detail type; see Section 4.4 for how the relation is
bound to the type.
Asor Expires 30 April 2027 [Page 9]
Internet-Draft Agent Delegation Chain October 2026
4.2. Constraint Vocabulary
The "constraints" member is an array of objects. Each object
contains a REQUIRED "key" member, a string identifying the
constrained dimension, and exactly one typed constraint value, whose
member name is the constraint type. A constraint object is closed:
its members are "key", that one type member, and any member the
type's definition adds ("order" for "rank"). A constraint object
carrying any other member is malformed, and a verifier MUST reject
the token. This document defines:
* "max" : a number. The value of the associated quantity in one
authorized action MUST NOT exceed it (e.g. {"key": "max_rows",
"max": 5000}). It is measured per action: nothing in this type
aggregates across actions, tokens, siblings, or a subtree.
* "max_lifetime" : a number. The sum of the associated quantity
over every action authorized under the token carrying it,
identified by "jti", MUST NOT exceed it (e.g. {"key": "max_calls",
"max_lifetime": 50}). It is measured per token lifetime. A re-
issued token (Section 5) is a new "jti" and starts a new total; an
issuer that needs a bound to span re-issuance issues the new token
with the bound reduced by the amount already consumed.
* "max_subtree" : a number. The sum of the associated quantity over
every action authorized under the token carrying it and under
every token descended from it MUST NOT exceed it. It is measured
per subtree. Enforcing it requires accounting across tokens; see
Section 9.4 for what an offline verifier can and cannot do with
it.
* "min" : a number. The value of the associated quantity in one
authorized action MUST NOT be less than it (e.g. {"key":
"tenure_years", "min": 2}). Where "max" carries a ceiling
tightened downward, "min" carries a floor tightened upward.
* "one_of" : an array. The associated value MUST be a member.
* "not_one_of" : an array. The associated value MUST NOT be a
member.
* "prefix" : a string. The associated value MUST have it as a
prefix.
* "rank" : a string naming a position in an ordered enumeration.
The constraint object additionally carries an "order" member: an
array of two or more distinct strings listing the enumeration from
least to most permissive, of which "rank" MUST be one (e.g.
Asor Expires 30 April 2027 [Page 10]
Internet-Draft Agent Delegation Chain October 2026
{"key": "egress", "rank": "internal", "order": ["none",
"internal", "any"]}). The associated value MUST be a member of
"order" whose position does not exceed that of "rank". The
ordering travels with the constraint so that a verifier needs no
registry entry per key; a constraint of type "rank" that lacks
"order", or whose "rank" is not a member of "order", is malformed.
The three measurement scopes -- per action, per token lifetime, per
subtree -- are distinct constraint types because they are enforced by
different machinery: a per-action bound is decided from the request
alone, a per-lifetime bound needs a running total held by the
component that authorizes actions under that token, and a per-subtree
bound needs a total that spans tokens. A producer MUST NOT emit a
cumulative bound under the "max" type. A per-action "max" on a
quantity that exists only as a running count, such as a count of
calls, bounds nothing, since each action contributes one; a producer
bounds a count with "max_lifetime" or "max_subtree". A verifier that
holds only the chain checks that a child's per-lifetime and per-
subtree bounds are no wider than its parent's (Section 4.3); whether
the spend is under the bound is checked only where the running total
is held, and an enforcement point that has no access to that total
denies (Section 6, step 8). The running total is supplied by the
component that holds it, through a channel separate from the
request's own parameters; a value the request asserts about its own
total is not a total.
Within one authorization detail object, the pair (key, type)
identifies a constraint. A detail MUST NOT carry two constraints
with the same key and the same type, and a verifier MUST reject a
token that does as malformed, rather than choosing one of them. Two
constraints with the same key and different types (for example a
"min" and a "max" on one quantity, forming a range) are permitted and
are evaluated independently.
The registry in Section 10 allows new constraint types. A verifier
that encounters an unknown constraint type MUST treat the action as
denied (fail-closed), never as unconstrained.
4.3. Subsumption Rules
An Authority C is subsumed by an Authority P (written C <= P) if and
only if all of the following hold:
1. Every scope in C's "agent_delegation" detail is covered by at
least one scope in P's "agent_delegation" detail according to
Section 4.1, and
Asor Expires 30 April 2027 [Page 11]
Internet-Draft Agent Delegation Chain October 2026
2. for every constraint (key, type) present in P, a constraint with
the same key and the same type is present in C whose admissible
set is a subset of P's: for "max", "max_lifetime", and
"max_subtree", C.value <= P.value; for "min", C.value >= P.value;
for "one_of", C's array is a subset of P's; for "not_one_of", C's
array is a superset of P's; for "prefix", C's string begins with
P's; for "rank", C's "order" is identical to P's, element for
element, and the position of C's "rank" in it does not exceed the
position of P's, and
3. a constraint (key, type) present in P MUST NOT be absent in C
(absence means unbounded, which is not a subset), and
4. C.exp <= P.exp (monotonic expiry), and
5. C.del_max_depth <= P.del_max_depth.
No inference is made across constraint types: a "max_lifetime" in C
does not satisfy a "max" in P, and a "max" in C does not satisfy a
"max_lifetime" in P, whatever their values. A verifier that does not
implement the type of a constraint present in P cannot evaluate rule
2 for it; it MUST treat the chain as not subsumed unless C carries a
constraint with the same key and type whose JCS serialization
[RFC8785] is byte-identical to P's, and even then the action is
denied at step 8 of Section 6 under the fail-closed rule of
Section 4.2.
Attenuation is the construction of C as the greatest lower bound
(meet) of P and a request R under these rules. Because the meet can
only narrow, C <= P holds by construction for every R.
4.4. Authorization Detail Types and the Verifier
[RFC9396] does not maintain a registry of authorization detail type
values; its Section 2.1 recommends that an API designer use a
collision-resistant namespace under the designer's control, such as a
URI. The type value "agent_delegation" is the one this document and
its test vectors use; whether a later revision moves it to a URI-form
value under such a namespace is an open question, and the wire value
is unchanged by this revision.
The covering relation a verifier applies at step 4 of Section 6 is
specified per authorization detail type. For "agent_delegation" it
is the relation in Section 4.1 together with the constraint rules of
Section 4.3. Another authorization detail type, if defined,
specifies its own relation, and that relation is what a verifier
applies to details of that type. The type selects the relation.
Asor Expires 30 April 2027 [Page 12]
Internet-Draft Agent Delegation Chain October 2026
A verifier MUST evaluate every authorization detail object in every
DT_i, or reject the token. A detail whose type the verifier does not
implement is one it cannot evaluate, and the token MUST be rejected
as malformed; a verifier that skips a detail it does not understand
has reported success on a token it did not read. The verifier
classifies detail types when it parses a token, before step 1 of
Section 6, so that DT_0 is subject to the rule as every other token
is. Under this revision the only type a token may carry is
"agent_delegation", and it may carry exactly one detail (Section 4);
a later revision may define chains whose tokens carry details of
several types, and the per-type binding of the covering relation
stated above is what such a definition would build on. Such a
definition would also need a rule for a child that adds a type its
parent did not carry, because a verifier cannot tell from the child
alone whether the addition narrowed or widened what the parent
granted. The rule recorded here for that revision, proposed by
Kieran Sweeney, is that a child that adds a type its parent did not
carry is treated as widening unless that type's definition states
otherwise. Under this revision the rule is not needed: the added
type is not "agent_delegation", so the token is malformed under the
rule above, and the vector "reject_child_adds_detail_type" in
Appendix B pins that outcome. A resource server SHOULD declare the
types it implements in the "authorization_details_types_supported"
member of its protected resource metadata ([RFC9728], Section 2), so
that an issuer can learn which chains it will accept.
[I-D.jackson-wimse-evaluation] states the same process-every-entry-
or-refuse rule from the verifier's side; the requirement here stands
on its own.
Which chains a verifier accepts across deployments is a trust
decision the verifier already makes by the root keys it holds
(Section 6, step 1); two verifiers that both implement
"agent_delegation" apply the same covering relation to the same
chain.
4.5. Open Issue: Scope Vocabulary
Subsumption is syntactic. Two deployments that both implement
"agent_delegation", and attach different meanings to the same scope
verbs, both verify the same chain clean and read it differently,
because nothing in the token says what "crm.read" permits. A profile
or registry of common operation verbs would close that gap. This
document states the limit and supplies neither.
Asor Expires 30 April 2027 [Page 13]
Internet-Draft Agent Delegation Chain October 2026
A companion document that does supply one is expected to take the
result of the native verification in Section 6 as an input rather
than re-implement it; to map a scope family to an action definition
explicitly; and, where a mapping is ambiguous, to refuse rather than
resolve. A companion document is cited from this one when it is an
Internet-Draft, so that every reader can cite it by a stable name.
5. Chain Linkage
Each child token commits to its parent by "par_hash" (Section 3).
This binds the child to the parent's exact serialized bytes, so a
child cannot be re-parented onto a different (e.g. broader) token:
doing so changes the parent's Signing Input and thus its SHA-256
digest, which no longer matches the child's "par_hash". The digest
is over the already-serialized JWS Signing Input; the protected
header and payload that form that input are JCS [RFC8785] as required
by Section 3.
The commitment is to a parent token instance, not to a parent
identity. A child's chain carries the parent instance the child
commits to. When a parent is re-issued -- for example refreshed
before expiry with a new "jti", "iat", and "exp" -- the re-issued
token is a different token, outside the chain of any child issued
under the previous instance. Re-issuing a parent therefore does not
invalidate its existing children: they continue to verify with the
instance they were issued under until that instance expires or a
token in their chain is revoked (Section 8), and a child presented
together with a re-issued parent instead of the instance it commits
to is denied at step 2 of Section 6. The operational consequence for
the refresh rate is in Section 9.5. A parent identity that survives
re-issuance is not defined by this document.
6. Offline Verification Algorithm
An Enforcement Point presented with a Delegation Chain DT_0 ... DT_n
and an attempted action A, and holding the trusted root public
key(s), MUST perform the following, denying on the first failure:
1. Verify the JWS signature of every DT_i using a fully-specified
algorithm [RFC9864]. The verifier MUST hold a local list of
accepted algorithms, and MUST deny the chain if the "alg" of any
DT_i is not on that list, even where the signature verifies. The
verifier MUST take the algorithm from its own configuration for
the key, and MUST deny if the "alg" header names a different one.
DT_0 MUST verify under a trusted root key.
Asor Expires 30 April 2027 [Page 14]
Internet-Draft Agent Delegation Chain October 2026
2. For each i > 0, compute SHA-256 of DT_{i-1}'s JWS Signing Input
and compare, in constant time, to DT_i's "par_hash". Any
mismatch: deny.
3. Check chain shape, depth first. Depth: DT_0.del_depth == 0;
DT_i.del_depth == i; n < DT_0.del_max_depth. Then principal:
DT_0.sub is a non-empty string, and for every i, DT_i.sub is
identical to DT_0.sub. Otherwise deny.
4. For each i > 0, verify DT_i.Authority <= DT_{i-1}.Authority under
rules 1, 2, 3, and 5 of Section 4.3. A token carrying a second
detail, or a detail of a type other than "agent_delegation", was
rejected as malformed when it was parsed (Section 4.4). Any
violation: deny.
5. Check time: for every i, nbf (if present) <= now < exp, and exp
is monotonic non-increasing along the chain (rule 4 of
Section 4.3). Otherwise deny.
6. Verify holder binding: the presenter proves possession of the key
in DT_n.cnf via a valid DPoP proof [RFC9449] bound to this
request. Otherwise deny.
7. Check revocation: consult the Token Status List
[I-D.ietf-oauth-status-list] reference in each DT_i (if present)
against a cached list. A cached status answer is trusted for its
time to live, so the window in which a revoked token is still
honored is that time to live and no longer. A status reference
that is present but whose list cannot be fetched, or whose cached
answer has outlived its time to live and cannot be refreshed, is
UNKNOWN, and the verifier MUST deny: unknown is not not-revoked.
If any DT_i is revoked, deny (and, by local policy, treat the
whole subtree as revoked). A token issued with no status
reference is a choice made at issuance (Section 8) and is not
denied on that account.
8. Authorize A against DT_n: confirm that the Enforcement Point is
identified by DT_n's "aud" as [RFC9068] Section 4 requires; then
check A against DT_n.Authority: its scope, every per-action
constraint ("max", "min", "one_of", "not_one_of", "prefix",
"rank"), and every cumulative constraint ("max_lifetime",
"max_subtree"). A cumulative constraint is checked where the
running total it is measured over is held: by the Enforcement
Point itself, or by a component that holds that total and
authorizes A on the Enforcement Point's behalf (Section 9.4).
The total reaches the check through a channel separate from the
request's own parameters, never from the request: a cumulative
constraint is evaluated against that total only, and a per-action
Asor Expires 30 April 2027 [Page 15]
Internet-Draft Agent Delegation Chain October 2026
constraint against the request only, so a name the two share
cannot let one stand in for the other. An Enforcement Point that
neither holds the running total for a cumulative constraint DT_n
carries nor has A authorized by a component that does MUST deny.
Permit only if A is within DT_n.Authority on every count.
The algorithm is deterministic, side-effect free, and requires no
network call except the (cacheable, offline-checkable) status list of
step 7. The one exception is the cumulative-constraint check of step
8, which belongs to the component holding the running total and lies
outside that guarantee. The order of steps 1 to 5 is the order in
which a chain presented without an action can be checked
(Section 6.1); steps 6 and 8 need the request, and step 7 needs the
status list.
6.1. What Verification Establishes
A Verifier is not always an Enforcement Point. An auditor re-
checking a recorded chain, an issuer validating a parent before
minting a child, or a component that holds a chain but no request,
can run steps 1 to 5 and, if a status list is available, step 7.
Table 1 states what such a Verifier may and may not conclude.
+========================+=============+========================+
| Property | Chain alone | With the request |
| | (steps 1-5, | (steps 6, 8) |
| | 7) | |
+========================+=============+========================+
| Every token is well- | yes | yes |
| formed, JCS-canonical, | | |
| and signed under an | | |
| accepted algorithm | | |
+------------------------+-------------+------------------------+
| DT_0 is signed under a | yes | yes |
| trusted root key | | |
+------------------------+-------------+------------------------+
| Each child commits to | yes | yes |
| the parent instance | | |
| presented with it | | |
+------------------------+-------------+------------------------+
| Depth is bounded and | yes | yes |
| the Principal is | | |
| unchanged along the | | |
| chain | | |
+------------------------+-------------+------------------------+
| Each hop's Authority | yes | yes |
| is a subset of its | | |
| parent's | | |
Asor Expires 30 April 2027 [Page 16]
Internet-Draft Agent Delegation Chain October 2026
+------------------------+-------------+------------------------+
| Every token is within | yes | yes |
| its validity window at | | |
| the instant checked | | |
+------------------------+-------------+------------------------+
| No token in the chain | yes, if the | yes, if the list is |
| is revoked, within the | list is | reachable |
| status list's time to | reachable | |
| live | | |
+------------------------+-------------+------------------------+
| The presenter holds | no | yes |
| the key DT_n is bound | | |
| to | | |
+------------------------+-------------+------------------------+
| A specific action is | no | yes |
| permitted | | |
+------------------------+-------------+------------------------+
| A per-lifetime total | no | only where the total |
| is within bound | | is held; otherwise |
| | | step 8 denies |
+------------------------+-------------+------------------------+
| A per-subtree total is | no | only where the total |
| within bound | | is held (Section 9.4); |
| | | otherwise step 8 |
| | | denies |
+------------------------+-------------+------------------------+
| The Principal still | no | no |
| holds the authority | | |
| granted at DT_0, at | | |
| the instant checked | | |
+------------------------+-------------+------------------------+
Table 1: What a Verifier may conclude, by the steps it performed
The last row records a second limit beside the one stated in
Section 9.7: nothing in a chain says whether the Principal named in
"sub" still holds the authority DT_0 granted. A Principal who has
left, lost the role, or had the underlying grant withdrawn leaves
every unexpired, unrevoked chain verifying clean, because a status
list revokes tokens and nothing in the chain revokes the Principal.
Step 8 permits an action within DT_n's Authority without establishing
that standing; a deployment that must know it before honoring an
action under that grant establishes it outside the chain. A server
in the call path that holds the Principal's grant itself, for example
a credential the Principal deposited with it, can learn at use time
that the grant was withdrawn, when the upstream service refuses the
credential; how soon that happens depends on the upstream service's
revocation and caching, and a successful call does not establish the
Asor Expires 30 April 2027 [Page 17]
Internet-Draft Agent Delegation Chain October 2026
Principal's standing beyond that grant. That covers a withdrawn
grant, not a role lost inside the Principal's own organization. This
is the division of labor Section 8 and Section 9.4 already state for
revocation and for aggregate budgets: the chain is the offline
carrier of what a chain can prove, and what it cannot prove is
checked by machinery outside it. A deployment that must know
standing checks it at root issuance, where Section 9.7 places the
policy decision, and, where the gap after minting is unacceptable,
again at exercise by an online server in the call path. Section 8
describes an online Delegation Server that evaluates delegation-tree
state for synchronous revocation; what else such a server checks is
left to the deployment.
The "subset" row holds for the constraint types the Verifier
implements. A constraint type it does not implement fails closed
under the rule in Section 4.3, so it can turn a "yes" into a "no" and
never the reverse.
A Verifier that has not performed step 6 has established that the
chain is valid, not that the party presenting it is its holder, and
MUST NOT report the chain as authorizing anything. A Verifier that
has not performed step 8 has established the leaf Authority as a set
and MUST NOT report any action as permitted. Such a Verifier SHOULD
report its result as the chain's validity together with the steps it
did not perform.
6.2. Verification Outcomes
Independent implementations are compared by their outcomes on shared
test vectors (Appendix B), and the comparison is only as good as the
agreement on how a denial is named. A verifier SHOULD report a
denial under the name that Table 2 gives for the check that failed,
which is the vocabulary the test vectors declare; since the algorithm
denies on the first failure, one denial carries one name. A verifier
MAY add detail of its own beside the name. The names are not carried
in any token and have no effect on the wire.
+=======================+=======+================================+
| Name | Step | Meaning |
+=======================+=======+================================+
| malformed | parse | a token is not three base64url |
| | | parts, a claim this document |
| | | requires is absent or of the |
| | | wrong shape, an integer's |
| | | magnitude exceeds 2^53-1, a |
| | | scope is invalid, a constraint |
| | | is malformed or repeated, a |
| | | detail carries an unknown |
Asor Expires 30 April 2027 [Page 18]
Internet-Draft Agent Delegation Chain October 2026
| | | member, a token carries more |
| | | than one detail, or a detail |
| | | type is not "agent_delegation" |
+-----------------------+-------+--------------------------------+
| non_canonical | parse | a decoded header or payload is |
| | | not the JCS serialization of |
| | | what it parses to |
+-----------------------+-------+--------------------------------+
| duplicate_member | parse | a JSON object repeats a member |
| | | name |
+-----------------------+-------+--------------------------------+
| non_finite | parse | a number is NaN or an |
| | | infinity, which JSON and JCS |
| | | do not represent |
+-----------------------+-------+--------------------------------+
| signature_invalid | 1 | a signature does not verify, |
| | | the algorithm is not on the |
| | | verifier's list, the algorithm |
| | | differs from the one |
| | | configured for the key, or |
| | | DT_0 is not under a trusted |
| | | root key |
+-----------------------+-------+--------------------------------+
| par_hash_mismatch | 2 | a child's commitment does not |
| | | match the parent presented |
| | | with it |
+-----------------------+-------+--------------------------------+
| depth_invalid | 3 | a del_depth is out of sequence |
| | | or the chain exceeds |
| | | del_max_depth |
+-----------------------+-------+--------------------------------+
| principal_altered | 3 | a token's "sub" differs from |
| | | DT_0's |
+-----------------------+-------+--------------------------------+
| not_narrower | 4 | a child's Authority is not |
| | | subsumed by its parent's under |
| | | rules 1, 2, 3, or 5 |
+-----------------------+-------+--------------------------------+
| expired | 5 | a token is outside its |
| | | validity window, or its expiry |
| | | exceeds its parent's (rule 4) |
+-----------------------+-------+--------------------------------+
| holder_binding_failed | 6 | the proof of possession is |
| | | absent or invalid for this |
| | | request |
+-----------------------+-------+--------------------------------+
| revoked | 7 | a token in the chain is |
| | | revoked |
Asor Expires 30 April 2027 [Page 19]
Internet-Draft Agent Delegation Chain October 2026
+-----------------------+-------+--------------------------------+
| status_unknown | 7 | a status reference is present |
| | | and its current status cannot |
| | | be established |
+-----------------------+-------+--------------------------------+
| audience_mismatch | 8 | DT_n's "aud" does not identify |
| | | the Enforcement Point |
+-----------------------+-------+--------------------------------+
| scope_not_granted | 8 | the action's scope is not |
| | | covered by DT_n's scopes |
+-----------------------+-------+--------------------------------+
| ceiling_exceeded | 8 | the action violates a |
| | | constraint of DT_n |
+-----------------------+-------+--------------------------------+
| unknown_constraint | 8 | DT_n carries a constraint of a |
| | | type the verifier does not |
| | | implement |
+-----------------------+-------+--------------------------------+
Table 2: Verification outcome names
6.3. Several Chains Reaching One Agent
This document defines the verification of one chain. An agent may
hold Delegation Tokens issued along more than one path from one or
more roots, and so hold more than one chain. For each request the
presenter presents one chain, the Enforcement Point verifies that
chain alone, and the action is permitted only if that chain permits
it. An Enforcement Point MUST NOT combine the Authority of tokens
from different chains, and a chain that fails verification has no
effect on the evaluation of another chain the same agent presents. A
presenter holding several valid chains chooses which to present; one
valid chain that permits the action suffices.
[I-D.jackson-wimse-evaluation] treats the same situation from the
verifier's side, in its rule that each delegation path is evaluated
independently and fails closed on its own; this document cites that
rule informatively and does not depend on it.
6.4. Open Issue: Trust-Anchor Provenance
Step 1 assumes the verifier already holds the trusted root key or
keys. This document says nothing about how a verifier comes to hold
that key, how the key is bound to the party it is trusted as, or
under which algorithm that binding was made; the algorithm rule of
step 1 reaches every token in the chain and stops at the root key. A
chain can be post-quantum at every hop and still rest on a root key
whose provenance the verifier cannot check. That is a property of
every delegation chain design, not of this one, and the author's view
Asor Expires 30 April 2027 [Page 20]
Internet-Draft Agent Delegation Chain October 2026
is that it belongs to the working group rather than to this document.
It is recorded here as open and is not solved here.
Two gaps follow from this, and they do not behave alike. The binding
gap is that a verifier provisioned only with a root key has nothing
in the chain that shows how that key is bound to the party it is
trusted as or under which algorithm. The recording gap is that a
later reader cannot reconstruct what the chain rested on. The
binding gap is a limit of verifying from configured state, as the
revocation window of Section 9.5 is: binding evidence the verifier
already holds can be inspected offline, and a verifier that is online
at the moment of use may be able to obtain current evidence from an
authenticated source. Network access alone establishes nothing.
This document states the limit, as Section 9.5 states that window. A
deployment that cannot bear it can use the online half that Section 8
names for synchronous revocation; Section 8 describes that half as
evaluating delegation-tree state, and what it inspects beyond that is
left to the deployment. The recording gap is not relieved by being
online: a verifier that writes nothing down leaves a later reader no
better off. A record of what the verifier held belongs beside the
retained record, not in the chain. Section 4.7 of
[I-D.gilda-audit-agent-audit-record] defines a retention entry kept
beside a record. The entry's validationData carries what a verifier
needs to validate the record's envelope signature and its anchors
offline. For a record that carries the optional
delegation.rootDigest (Section 5.2 of that document), it also carries
the certification path or key set of the chain's root key as the
chain verifier held it at decision time. Retaining that material and
verifying its digest against delegation.rootDigest addresses the
recording gap for the root key; Section 4.6 of that document requires
a verifier without the digest or the retained material to report the
root as not established. Recording that material does not by itself
establish the root key's binding to the party it is trusted as, or
show how the verifier came to hold it. This document defines no
record. No trust-anchor topology is mandated here; mandating one
would address the binding gap only by forcing a deployment model on
every deployment, which is worse than stating the limit.
7. Holder Binding
Every Delegation Token is sender-constrained by a "cnf" claim
[RFC7800] carrying the JWK thumbprint of the holder's key, proven per
request with DPoP [RFC9449]. This revision specifies DPoP holder
binding only; a profile for mTLS-bound tokens [RFC8705] is left to a
later revision. A captured token is therefore unusable without its
bound private key, which mitigates replay of intermediate tokens.
The "cnf" claim is present in every token of a chain, and a Verifier
that sees no request (Section 6.1) checks its presence and shape but
Asor Expires 30 April 2027 [Page 21]
Internet-Draft Agent Delegation Chain October 2026
cannot perform step 6.
8. Revocation
Delegation Tokens are RECOMMENDED to be short-lived (seconds to
minutes for leaf and execution tokens), so that expiry is the common
revocation path. For earlier revocation of longer-lived delegations,
each token MAY carry a Token Status List [I-D.ietf-oauth-status-list]
reference; revoking a token's status entry, and by local policy the
entries of its descendants, revokes a delegation or a whole sub-chain
while preserving offline verification (the status list is itself
cacheable and offline-checkable). An online revocation endpoint
[RFC7009] MAY additionally be offered.
Whether a token carries a status reference is decided at issuance. A
token issued without one can be revoked only by expiry. A token
issued with one is subject to step 7 of Section 6 as stated there: a
cached answer is trusted for its time to live and no longer, and an
answer that cannot be obtained or refreshed is unknown, which denies.
A deployment chooses between the two at issuance with that
consequence in view.
Short lifetimes mean re-issuance. A parent that is re-issued is a
new token instance (Section 5); its existing children are not
invalidated by the re-issuance, and a deployment that wants them
invalidated revokes the previous instance. The rate at which this
happens is an operational property that Section 9.5 states.
Deployments that require synchronous cascading revocation MAY issue
and exercise Delegation Tokens through an online Delegation Server as
specified by [I-D.sweeney-wimse-credential-delegation]. The server
can evaluate current delegation-tree state and refuse a revoked root
or descendant immediately. This online bridge complements, and does
not replace, the offline verification algorithm in Section 6: an
Enforcement Point that receives a chain MUST still verify its
signatures, linkage, attenuation, depth, principal, and expiry.
9. Security Considerations
9.1. Parent tokens remain valid after attenuation
Attenuation produces a new child token but does not, by itself,
invalidate the parent. A party holding the parent still holds the
parent's (broader) authority. This is mitigated by three mechanisms
that MUST be considered together: (a) tokens are short-lived and
holder-bound (Section 7), so a leaked parent is both time-boxed and
non-replayable without its key; (b) the "par_hash" byte-commitment
(Section 5) prevents splicing a child onto a different parent; and
Asor Expires 30 April 2027 [Page 22]
Internet-Draft Agent Delegation Chain October 2026
(c) status-list revocation (Section 8) allows early invalidation of a
parent and its subtree. Deployments that require immediate parent
invalidation on delegation MUST use short TTLs and status lists
accordingly.
9.2. Chain splicing
Without the byte-commitment, an attacker could present a valid child
together with a broader token as its purported parent. Step 2 of
Section 6 prevents this: the child's "par_hash" digests the parent's
exact Signing Input, so only the intended parent verifies. The same
check is what denies a child presented with a re-issued parent rather
than the instance it was issued under (Section 5).
9.3. Confused deputy and over-broad delegation
Because each hop's authority is the meet of parent and request
(Section 4.3), a child cannot be induced (e.g. by prompt injection)
to exercise authority the parent lacked. The principal invariance
check (step 3 of Section 6) adds that a child cannot be induced to
act under a different grant than its parent: a token that names
another Principal is not a member of the chain.
9.4. Unbounded depth, fan-out, and aggregate budgets
"del_max_depth" (checked in step 3) bounds chain length; deployments
SHOULD set it low (e.g. 5). Fan-out (a parent delegating to many
children) is not limited by the token format and MUST be bounded by
the issuing infrastructure if required.
Quantity constraints compose across siblings, and subsumption is
checked per edge. A "max" constraint bounds one authorized action
and nothing else (Section 4.2). A parent holding {"key":
"max_spend", "max": 100} can mint any number of children each
carrying max_spend 100; every parent-child edge satisfies C <= P, and
a subtree of N children can spend N x 100. The same holds at a
single enforcement point and across several: against a root ceiling
of 100, two valid children can each authorize 60 at two different
gateways; both chains verify, each gateway sees a request within
bound, and the combined spend is 120. Individually permitted
delegations compose into an outcome nobody permitted. The
"max_subtree" type names that total, and a chain-only verifier checks
only that a child's "max_subtree" is no wider than its parent's;
verification is side-effect free by design, so a signed ceiling names
a limit while nothing in verifying it reserves against that limit or
sees another gateway's balance. A signed ceiling alone provides none
of the protection an aggregate budget needs.
Asor Expires 30 April 2027 [Page 23]
Internet-Draft Agent Delegation Chain October 2026
An aggregate budget over a consequential resource therefore needs
machinery outside the token, and that machinery has two separable
parts. Allocation -- deciding how much of a parent's budget each
child may consume -- requires coordination: an allocator that splits
a budget at delegation time only keeps the total under bound if it is
a single writer, since two issuers allocating offline from the same
budget can each allocate the same units. Spending afterwards does
not require coordination once allocations are disjoint: each
enforcement point debits its own durable balance for the allocation
it holds and contacts no shared service per action. Two deployment
shapes follow, and a deployment that enforces aggregate budgets uses
one of them:
* Shared accounting: one ledger, consulted by every enforcement
point, that checks and debits atomically at authorization time. A
ledger that is read at authorization and debited afterwards, or
debited by more than one writer without coordination, does not
close the hole; the check and the debit are one operation or the
budget is not enforced. An online Delegation Server through which
every action is exercised, as in
[I-D.sweeney-wimse-credential-delegation], is one place such
accounting can be held.
* Coordinated allocation with local enforcement: a single-writer
allocator reserves disjoint allocations for the children (for
example 60 units to the child acting at gateway A and 40 to the
child acting at gateway B, leaving none at the parent, since
allocating to a child reduces what remains available to the
parent), and each enforcement point enforces its own allocation
locally against a durable balance. This path has to protect
against three hazards that a signed ceiling does not: duplicate
allocation of the same units to two children; local rollback,
where an enforcement point loses or reverts a debit it has already
honored; and premature reuse of allocated units before the action
that consumed them is settled.
Either way, the division is the one this document is built on: the
offline chain bounds each action and produces the audit trail; the
online half holds the aggregates.
9.5. Offline verification vs. revocation latency
Offline verification means an enforcement point may honor a token
that has been revoked but whose status-list update it has not yet
fetched. Deployments trade this window against TTL: shorter TTLs
bound the exposure, and step 7 of Section 6 fixes the window at the
cached answer's time to live. This is the standard status-list
trade-off and MUST be documented for each deployment.
Asor Expires 30 April 2027 [Page 24]
Internet-Draft Agent Delegation Chain October 2026
The lifetimes Section 8 recommends have a second cost, which is on
the issuing side rather than the verifying side. A token that lives
for seconds to minutes and is still needed must be re-issued, so a
platform with many live agent instances sustains a refresh rate
proportional to the number of live instances, continuously, not only
at startup. That rate is a property of the deployment and a
deployment MUST size its authorization server for it, and for the
resynchronisation case in which many instances refresh at once after
an outage of the issuer or of the network between them. Offline
verification is preserved under these lifetimes; offline operation is
not, because an agent whose issuer is unreachable stops receiving
tokens when its current ones expire.
The refresh rate counts every token in a chain, not only the roots,
and grows with fan-out. Rule 4 of Section 4.3 and step 5 of
Section 6 cap a child's "exp" at its parent's when the child is
issued, so at the recommended lifetimes every child that keeps
working is re-issued at least once per parent lifetime, whichever
instance of the parent it commits to (Section 5). A deployment that
revokes the previous parent instance at refresh adds a burst on top
of that rate: every child of that instance at once. Both the
sustained rate and the burst belong in the sizing above, and the fan-
out bound of Section 9.4 is what bounds them.
9.6. Why not macaroons; algorithm agility
Macaroons [Macaroons] verify with the root secret, precluding public
offline verification at an untrusted edge; this document uses public-
key signatures. Algorithms are fully specified [RFC9864] and agile
via the JOSE "alg" registry, with a migration path to ML-DSA
[RFC9964]. The algorithm list of step 1 in Section 6 is the agility
mechanism on the verifying side. A deployment that retires an
algorithm, for example a quantum-vulnerable one after a transition
date, removes it from the verifier's list, and chains that still use
it are then denied whatever their remaining lifetime. Because every
hop's "alg" sits in a protected header that the child's "par_hash"
covers, a verifier holding the full chain sees every hop's algorithm,
and a parent whose algorithm was swapped after the fact no longer
matches its child's commitment.
9.7. Root issuance is the policy decision point
DT_0's Authority is asserted by whoever holds the root key. Every
guarantee in this document begins downstream of that minting: each
child is a deterministic attenuation of DT_0, and verification can
establish that no hop exceeded the root, never that the root was
right. Approval policy therefore belongs at root issuance. A
deployment that requires a human decision before an agent may act
Asor Expires 30 April 2027 [Page 25]
Internet-Draft Agent Delegation Chain October 2026
with consequential authority places that decision where DT_0 is
minted, not at a later hop, because no later hop can widen what DT_0
granted and no verification step can tighten it. The Principal named
in DT_0's "sub" is the party that decision is taken on behalf of, and
the "client_id" of each hop records which agent acted under it.
10. IANA Considerations
This document does not request registration of "del_depth",
"del_max_depth", or "par_hash".
[I-D.niyikiza-oauth-attenuating-agent-tokens] requests registration
of the same three names in the JSON Web Token Claims registry, and
each name should have a single entry. That document defines
"del_depth" and "par_hash" as Section 3 does. It defines
"del_max_depth" differently: there the claim is required in every
token and a leaf's "del_depth" may equal the root's "del_max_depth",
while step 3 of Section 6 here requires the leaf's "del_depth" to be
less than DT_0.del_max_depth. Consequently, the same depth values
can pass the depth checks in that document and fail step 3 of
Section 6 here. The claims "sub", "client_id", "aud", and "cnf" are
already registered and are used with their registered meanings as
profiled in Section 3.
This document requests a new "Agent Delegation Constraint Types"
registry with the following initial entries, each recorded with its
measurement scope: "max" (per action), "max_lifetime" (per token
lifetime), "max_subtree" (per subtree), "min" (per action), "one_of"
(per action), "not_one_of" (per action), "prefix" (per action), and
"rank" (per action). The registration policy is Specification
Required; a registration states the type's value shape, its
measurement scope, and its subsumption rule in the form of
Section 4.3. Unknown types fail closed per Section 4.2.
This document does not request registration of an
"authorization_details" type value. [RFC9396] maintains no registry
of type values, and recommends a collision-resistant namespace under
the designer's control; see Section 4.4.
11. Implementation Status
This section records the status of known implementations of this
document at the time of its posting, as described in [RFC7942]. The
description of implementations here is intended to assist the IETF in
its decision processes in progressing drafts to RFCs. It is not an
endorsement of any implementation, and the listing is not a claim
that any implementation conforms to this revision in full. Please
note that this section is to be removed before this document is
published as an RFC.
Asor Expires 30 April 2027 [Page 26]
Internet-Draft Agent Delegation Chain October 2026
Two reference implementations are maintained by the author under the
Apache License 2.0: "attenu-guard", in Python, which mints Delegation
Tokens and runs the verification algorithm of Section 6, and "attenu-
guard-ts", in TypeScript, which runs the verification algorithm and
mints nothing. At the time of posting, both released libraries
(attenu-guard 0.22.0 and attenu-guard-ts 0.16.0) implement this
revision as an opt-in profile, the one they introduced for the -02,
beside the -01 profile, which remains their default: the claim rules
of Section 3 at parse, the accepted-algorithm list of step 1,
principal invariance, the three-form scope grammar, the two
cumulative constraint types with their totals supplied through a
channel separate from the request, the "order" member of "rank", one
constraint per (key, type), the closed detail and constraint objects,
and the audience check of step 8, under a single-signer trust model.
Both check the presence and shape of "cnf" and perform neither step 6
(holder binding) nor step 7 (status list), which both document as not
performed. Their built-in Ed25519 signer and verifier still use the
polymorphic JOSE identifier "EdDSA" rather than the fully-specified
"Ed25519" of [RFC9864] that Section 3 requires; the vectors use a
test-only HS256 signer and do not exercise it. The vector set of
Appendix B for this revision has thirty-six files; the Python library
generates and scores it on every test run, and the TypeScript library
vendors it byte for byte as test fixtures and scores it in its test
suite. The -01 set's twenty files are unchanged in the Python
package and in both source repositories.
Two implementations independent of the author's code have run the
twenty test vectors of the -01 and published their results, as
reported by their authors: the conformance harness of the Cred
delegation protocol, whose published result of 2026-10-07 reports 20
of 20, with no failures and no declared gaps, at a pinned commit of
the Cred SDK; and a standalone Node.js verifier that imports no code
from either reference implementation, which reported 20 of 20 with
verdicts and declared reasons both matching, under the boundary its
author states: the vectors' HS256 single-signer, public-test-key
profile, and steps 1 to 5 only. Neither result is reproduced here.
The Cred harness has also published a run of 2026-10-20 against the
thirty-five vectors of the -02, all of which this revision's set
retains unchanged; as its author reports it, at a pinned commit of
the Cred SDK, it records 20 passes, 5 failures, and 10 declared gaps.
No run against all thirty-six vectors has been reported.
12. References
12.1. Normative References
Asor Expires 30 April 2027 [Page 27]
Internet-Draft Agent Delegation Chain October 2026
[I-D.ietf-oauth-status-list]
Looker, T., Bastian, P., and C. Bormann, "Token Status
List (TSL)", Work in Progress, Internet-Draft, draft-ietf-
oauth-status-list-21, 21 June 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-oauth-
status-list-21>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", STD 68, RFC 5234,
DOI 10.17487/RFC5234, January 2008,
<https://www.rfc-editor.org/rfc/rfc5234>.
[RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
RFC 6749, DOI 10.17487/RFC6749, October 2012,
<https://www.rfc-editor.org/rfc/rfc6749>.
[RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web
Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
2015, <https://www.rfc-editor.org/rfc/rfc7515>.
[RFC7519] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
(JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
<https://www.rfc-editor.org/rfc/rfc7519>.
[RFC7800] Jones, M., Bradley, J., and H. Tschofenig, "Proof-of-
Possession Key Semantics for JSON Web Tokens (JWTs)",
RFC 7800, DOI 10.17487/RFC7800, April 2016,
<https://www.rfc-editor.org/rfc/rfc7800>.
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
Signature Algorithm (EdDSA)", RFC 8032,
DOI 10.17487/RFC8032, January 2017,
<https://www.rfc-editor.org/rfc/rfc8032>.
[RFC8037] Liusvaara, I., "CFRG Elliptic Curve Diffie-Hellman (ECDH)
and Signatures in JSON Object Signing and Encryption
(JOSE)", RFC 8037, DOI 10.17487/RFC8037, January 2017,
<https://www.rfc-editor.org/rfc/rfc8037>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
Asor Expires 30 April 2027 [Page 28]
Internet-Draft Agent Delegation Chain October 2026
[RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON
Canonicalization Scheme (JCS)", RFC 8785,
DOI 10.17487/RFC8785, June 2020,
<https://www.rfc-editor.org/rfc/rfc8785>.
[RFC9068] Bertocci, V., "JSON Web Token (JWT) Profile for OAuth 2.0
Access Tokens", RFC 9068, DOI 10.17487/RFC9068, October
2021, <https://www.rfc-editor.org/rfc/rfc9068>.
[RFC9396] Lodderstedt, T., Richer, J., and B. Campbell, "OAuth 2.0
Rich Authorization Requests", RFC 9396,
DOI 10.17487/RFC9396, May 2023,
<https://www.rfc-editor.org/rfc/rfc9396>.
[RFC9449] Fett, D., Campbell, B., Bradley, J., Lodderstedt, T.,
Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of
Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449,
September 2023, <https://www.rfc-editor.org/rfc/rfc9449>.
[RFC9728] Jones, M.B., Hunt, P., and A. Parecki, "OAuth 2.0
Protected Resource Metadata", RFC 9728,
DOI 10.17487/RFC9728, April 2025,
<https://www.rfc-editor.org/rfc/rfc9728>.
[RFC9864] Jones, M.B. and O. Steele, "Fully-Specified Algorithms for
JSON Object Signing and Encryption (JOSE) and CBOR Object
Signing and Encryption (COSE)", RFC 9864,
DOI 10.17487/RFC9864, October 2025,
<https://www.rfc-editor.org/rfc/rfc9864>.
12.2. Informative References
[Biscuit] "Biscuit Authorization Token Specification, v3", n.d.,
<https://doc.biscuitsec.org/reference/
specifications.html>.
[I-D.coetzee-oauth-spt-txn-tokens]
Coetzee, R. J., "Transaction-Bound Authorization Tokens
for Software and AI Agents (SPT-Txn)", Work in Progress,
Internet-Draft, draft-coetzee-oauth-spt-txn-tokens-03, 19
July 2026, <https://datatracker.ietf.org/doc/html/draft-
coetzee-oauth-spt-txn-tokens-03>.
Asor Expires 30 April 2027 [Page 29]
Internet-Draft Agent Delegation Chain October 2026
[I-D.gilda-audit-agent-audit-record]
Gilda, S., "An Audit Record Format for AI Agent
Authorization Decisions", Work in Progress, Internet-
Draft, draft-gilda-audit-agent-audit-record-02, 27 October
2026, <https://datatracker.ietf.org/doc/html/draft-gilda-
audit-agent-audit-record-02>.
[I-D.hamr-oauth-agent-delegation]
Hassan, A., "An Attenuated Delegation Profile for
Automated Agents", Work in Progress, Internet-Draft,
draft-hamr-oauth-agent-delegation-03, 22 October 2026,
<https://datatracker.ietf.org/doc/html/draft-hamr-oauth-
agent-delegation-03>.
[I-D.ietf-oauth-identity-chaining]
Schwenkschuster, A., Kasselman, P., Burgin, K., Jenkins,
M. J., Campbell, B., and A. Parecki, "OAuth Identity and
Authorization Chaining Across Domains", Work in Progress,
Internet-Draft, draft-ietf-oauth-identity-chaining-17, 19
July 2026, <https://datatracker.ietf.org/doc/html/draft-
ietf-oauth-identity-chaining-17>.
[I-D.ietf-wimse-aims]
Kasselman, P., Lombardo, J., Rosomakho, Y., Campbell, B.,
Steele, N., and A. Parecki, "AI Identity Management
System", Work in Progress, Internet-Draft, draft-ietf-
wimse-aims-00, 15 September 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-wimse-
aims-00>.
[I-D.ietf-wimse-identifier]
Rosomakho, Y. and J. A. Salowey, "Workload Identifier",
Work in Progress, Internet-Draft, draft-ietf-wimse-
identifier-04, 23 October 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-wimse-
identifier-04>.
[I-D.jackson-wimse-evaluation]
Jackson, W., "Verifier-Side Evaluation Semantics for
Delegated Authority Chains", Work in Progress, Internet-
Draft, draft-jackson-wimse-evaluation-04, 10 October 2026,
<https://datatracker.ietf.org/doc/html/draft-jackson-
wimse-evaluation-04>.
Asor Expires 30 April 2027 [Page 30]
Internet-Draft Agent Delegation Chain October 2026
[I-D.mcguinness-oauth-actor-profile]
McGuinness, K., "OAuth Actor Profile for Delegation", Work
in Progress, Internet-Draft, draft-mcguinness-oauth-actor-
profile-01, 8 October 2026,
<https://datatracker.ietf.org/doc/html/draft-mcguinness-
oauth-actor-profile-01>.
[I-D.mw-oauth-actor-chain]
Prasad, A., Krishnan, R., Lopez, D., Addepalli, S., and S.
Krishnan, "OAuth Actor Chain: Protocol and
Interoperability", Work in Progress, Internet-Draft,
draft-mw-oauth-actor-chain-02, 13 October 2026,
<https://datatracker.ietf.org/doc/html/draft-mw-oauth-
actor-chain-02>.
[I-D.niyikiza-oauth-attenuating-agent-tokens]
Aimable, N., "Attenuating Authorization Tokens for Agentic
Delegation Chains", Work in Progress, Internet-Draft,
draft-niyikiza-oauth-attenuating-agent-tokens-02, 26
October 2026, <https://datatracker.ietf.org/doc/html/
draft-niyikiza-oauth-attenuating-agent-tokens-02>.
[I-D.reece-wimse-cross-org-delegation]
Reece, M., "Cross-Organizational Delegation for Workload
and Agent Identity: Problem Statement and Requirements",
Work in Progress, Internet-Draft, draft-reece-wimse-cross-
org-delegation-02, 31 August 2026,
<https://datatracker.ietf.org/doc/html/draft-reece-wimse-
cross-org-delegation-02>.
[I-D.sweeney-wimse-credential-delegation]
Sweeney, K., "Credential Delegation Protocol for AI Agents
in Multi-System Environments", Work in Progress, Internet-
Draft, draft-sweeney-wimse-credential-delegation-01, 13
October 2026, <https://datatracker.ietf.org/doc/html/
draft-sweeney-wimse-credential-delegation-01>.
[Macaroons]
"Macaroons: Cookies with Contextual Caveats for
Decentralized Authorization in the Cloud", NDSS 2014 ,
2014.
[RFC2693] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas,
B., and T. Ylonen, "SPKI Certificate Theory", RFC 2693,
DOI 10.17487/RFC2693, September 1999,
<https://www.rfc-editor.org/rfc/rfc2693>.
Asor Expires 30 April 2027 [Page 31]
Internet-Draft Agent Delegation Chain October 2026
[RFC7009] Lodderstedt, T., Ed., Dronia, S., and M. Scurtescu, "OAuth
2.0 Token Revocation", RFC 7009, DOI 10.17487/RFC7009,
August 2013, <https://www.rfc-editor.org/rfc/rfc7009>.
[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,
<https://www.rfc-editor.org/rfc/rfc7942>.
[RFC8693] Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J.,
and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693,
DOI 10.17487/RFC8693, January 2020,
<https://www.rfc-editor.org/rfc/rfc8693>.
[RFC8705] Campbell, B., Bradley, J., Sakimura, N., and T.
Lodderstedt, "OAuth 2.0 Mutual-TLS Client Authentication
and Certificate-Bound Access Tokens", RFC 8705,
DOI 10.17487/RFC8705, February 2020,
<https://www.rfc-editor.org/rfc/rfc8705>.
[RFC9964] Prorock, M. and O. Steele, "ML-DSA for JSON Object Signing
and Encryption (JOSE) and CBOR Object Signing and
Encryption (COSE)", RFC 9964, DOI 10.17487/RFC9964, May
2026, <https://www.rfc-editor.org/rfc/rfc9964>.
Appendix A. Acknowledgments
This work builds directly on, and seeks convergence with,
[I-D.niyikiza-oauth-attenuating-agent-tokens],
[I-D.coetzee-oauth-spt-txn-tokens],
[I-D.sweeney-wimse-credential-delegation], [I-D.ietf-wimse-aims], and
the requirements of [I-D.reece-wimse-cross-org-delegation]. The
capability-token lineage of [Macaroons], [Biscuit], and [RFC2693] is
gratefully acknowledged. The "min" constraint type was added after
Amr Hassan, author of [I-D.hamr-oauth-agent-delegation], observed
that -00 had no comparator for a floor tightened upward; the
duration-typed "tenureMin" axis of that document is the motivating
example.
The following contributions were made in review of the -01 and the
-02. Naming a contributor records where their contribution landed;
it does not imply that they endorse this document.
Wes Jackson: the binding of the chain to an accountable Principal in
"sub", distinct from the holder key, and the naming of the Acting
Agent at each hop in "client_id" (Section 3, Section 3.1); the
observation that quantity constraints compose across siblings while
subsumption is checked per edge, that a per-action "max" therefore
Asor Expires 30 April 2027 [Page 32]
Internet-Draft Agent Delegation Chain October 2026
imposes no aggregate budget, and that per-action, per-lifetime, and
per-subtree limits are enforced by different machinery and belong in
distinct registered types (Section 4.2, Section 9.4); the atomic
check-and-debit requirement on shared accounting and the single-
writer constraint on delegation-time allocation (Section 9.4); root
issuance as the policy decision point (Section 9.7); the scope-
vocabulary limit (Section 4.5); the questions that led to the
process-every-detail rule and the per-type interoperability statement
(Section 4.4); and the per-path evaluation rule answered in
Section 6.3.
Iman Schrock: the two-gateway example in which two verified chains
overspend a root ceiling, the distinction between allocation, which
needs coordination, and spending within disjoint allocations, which
does not, the two deployment shapes and the three hazards of the
allocation path (Section 9.4), the compatibility point that led the
scope grammar to keep structured literals as their own form, and the
request to state the residual ambiguity of that grammar beside it
(Section 4.1); and that one "agent_delegation" detail is enough for
the EMILIA CAID companion experiment, as a use-case answer on its
-01-pinned packet (Section 4.4).
Girish Konda: the sustained refresh rate implied by the recommended
lifetimes and the sizing it requires of the authorization server, and
the requirement that a verifier tell a fresh status answer from a
stale one (Section 9.5, Section 6 step 7).
Jijie Wei: the question of what "par_hash" commits to when a parent
is re-issued, answered in Section 5, and the counting of child re-
issuance in the refresh rate (Section 9.5).
Kieran Sweeney: the proposal to admit scope strings issued by OAuth
providers, which became the opaque scope form, and the vectors that
exercise it (Section 4.1, Appendix B); the rule for a child that adds
a detail type its parent did not carry, recorded in Section 4.4 for a
later revision; the observation that a server holding the Principal's
deposited grant can learn at use time that it was withdrawn
(Section 6.1); and, proposed on the list on 23 October 2026, the
statement of a limit of offline verification with deployments that
cannot bear it pointed at the online half and the warning against
mandating an anchor topology (Section 6.4), and the naming of where
standing is established (Section 6.1).
Cliff Singletary: the row of Table 1 stating that neither the chain
nor the request establishes that the Principal still holds the
authority granted at DT_0 at the instant checked (Section 6.1).
Asor Expires 30 April 2027 [Page 33]
Internet-Draft Agent Delegation Chain October 2026
Sankalp Gilda: the correction, on the list on 24 October 2026, that
the audit record draft continues as
[I-D.gilda-audit-agent-audit-record], which Section 6.4 now cites at
its Section 4.7.
Venkata Karunakar Uppalapati: the rule that a verifier rejects a
chain carrying an algorithm outside its local policy even where the
signature verifies, now step 1 of Section 6 and the agility text in
Section 9, the trust-anchor provenance gap recorded in Section 6.4,
and the distinction there between the binding gap, which an online
verifier with an authenticated source of binding evidence may
relieve, and the recording gap, which being online does not.
Niki Aimable Niyikiza: the comparison of the -01 vectors with those
of [I-D.niyikiza-oauth-attenuating-agent-tokens], which found the
difference in "del_max_depth", and the proposal that the three shared
claim names have one registration (Section 10).
Appendix B. Reference Implementation and Test Vectors
A permissively licensed reference implementation (the "attenu-guard"
library) and a set of offline-verification test vectors (chains that
MUST verify and adversarial chains that MUST be rejected, each with
the outcome name of Section 6.2 it is expected to produce) are
published with this draft. They are intended for interoperability
testing across independent implementations.
The twenty vector files published with the -01 are unchanged by this
revision and remain available under their -01 names: independent
implementations have vendored them, and a byte-stable set is worth
more than a corrected one. They do not conform to this revision:
their tokens carry no "cnf" and no "client_id", and their "aud" is
null. The vector set published with this revision is a second,
separately named set. It carries "cnf", "client_id", and a well-
formed "aud" on every token, and adds vectors for: a chain in which a
child's "sub" differs from the root's (principal_altered); a child
presented with a re-issued parent rather than the instance it commits
to (par_hash_mismatch); a wildcard scope over an opaque child scope
and an opaque scope over a wildcard child, both not_narrower, and an
opaque scope covering a byte-identical child, which verifies,
contributed by Kieran Sweeney; a detail carrying two constraints with
the same key and type (malformed); a "rank" whose "order" differs
from its parent's (not_narrower); a "max_lifetime" under a parent
"max" of the same key (not_narrower, by the no-cross-type rule); a
token whose "alg" is not on the verifier's list (signature_invalid);
and a token carrying an authorization detail of a type the verifier
does not implement (malformed); and, added in the -03, a child that
adds a detail of a type its parent did not carry (malformed under
Asor Expires 30 April 2027 [Page 34]
Internet-Draft Agent Delegation Chain October 2026
this revision, see Section 4.4). The -01 set's ceiling widening,
parent splicing, non-monotonic expiry, and wildcard widening are re-
minted in the new set under this revision's claim layout. Its other
cases are not all re-minted, among them a chain longer than its
root's "del_max_depth" allows, the bare, non-final, and segment-
boundary wildcard cases, RFC 8785 number and string forms, non-finite
values, duplicate member names, and the informational "c14n" label;
they remain covered by the unchanged -01 set.
Appendix C. Changes Since -02
* Table 1 gains a row: whether the Principal still holds the
authority granted at DT_0 at the instant checked is established
neither by the chain nor by the request. A paragraph after the
table says that step 8 does not establish it, what a deployment
that needs it does, and where a server in the call path can learn
it. It also states the division of labor between the chain and
the online half, and where standing is checked.
* Section 6.4 gains a paragraph stating that the binding gap is a
limit of verifying from configured state, that the recording gap
is not relieved by online verification, and that no trust-anchor
topology is mandated. It cites Sections 4.6, 4.7 and 5.2 of
[I-D.gilda-audit-agent-audit-record] for the optional
delegation.rootDigest and the root material kept beside a record.
Retaining that material and verifying its digest addresses the
recording gap for the root key; recording it does not by itself
establish the key's binding to the party it is trusted as.
* Section 10 no longer requests registration of "del_depth",
"del_max_depth", and "par_hash";
[I-D.niyikiza-oauth-attenuating-agent-tokens] requests the same
names, and the section states where the two definitions of
"del_max_depth" differ.
* Step 5 of Section 6 requires now < exp, as the JWT "exp" claim
[RFC7519] does; the -02 text allowed now = exp.
* Section 7 no longer offers mTLS-bound tokens as an alternative to
DPoP; an mTLS profile is left to a later revision.
* Appendix B no longer says that the -01 set's coverage is re-minted
in the new set; the cases that are not remain in the -01 set.
Asor Expires 30 April 2027 [Page 35]
Internet-Draft Agent Delegation Chain October 2026
* Section 4.4 records, for a later revision that admits several
detail types, the rule that a child adding a type its parent did
not carry is treated as widening unless that type's definition
states otherwise. Under this revision the token is malformed, and
a vector pins that outcome.
* A new subsection of the Introduction (Section 1.2) states the
relationship to draft-mcguinness-oauth-actor-profile and draft-mw-
oauth-actor-chain.
* The vector set of Appendix B has thirty-six files.
Appendix D. Changes Since -01
* "sub" is defined as the Principal, identical at every hop;
"client_id" is added to the required claims as the Acting Agent at
each hop; and step 3 of the verification algorithm denies a chain
in which any token's "sub" differs from the root's. A new
subsection explains the split.
* "aud" is required to be a string or non-empty array of strings;
null is malformed. The audience check of RFC 9068 Section 4 is
applied to the leaf token in step 8.
* Step 1 requires a verifier-held list of accepted algorithms,
denies any token whose "alg" is not on it even where the signature
verifies, and takes the algorithm from the verifier's
configuration for the key rather than from the header. The
algorithm agility text says how an algorithm is retired.
* The scope grammar gains a third form, "opaque-scope", the RFC 6749
scope token without the asterisk, so that provider-issued scope
strings can be carried; classification is by bytes alone in a
stated order; an opaque scope covers only a byte-identical child
and no wildcard covers it; the residual ambiguity for dotted
provider strings is stated beside the grammar.
* Two constraint types are added, "max_lifetime" and "max_subtree",
so that per-action, per-lifetime, and per-subtree bounds are
distinct registered types; "max" is defined as per action only; no
inference is made across types; a chain-only verifier checks only
that a child's cumulative bounds are no wider than its parent's.
* The "rank" type carries its ordering on the wire in an "order"
member, and a child's ordering must be identical to its parent's.
* A detail may not carry two constraints with the same key and type;
a verifier rejects a token that does.
Asor Expires 30 April 2027 [Page 36]
Internet-Draft Agent Delegation Chain October 2026
* Three closure rules are stated as MUSTs: a token carries exactly
one "agent_delegation" detail; that detail carries no members
other than "type", "scopes", and "constraints"; and a constraint
object carries no members other than "key", its type member, and
the members its type defines. A token that breaks any of them is
malformed.
* The covering relation is bound to the authorization detail type; a
verifier must evaluate every detail or reject the token, and an
unimplemented type is a rejection; under this revision a token
carries exactly one detail, of type "agent_delegation", and chains
carrying several types are left to a later revision; a resource
server is pointed to RFC 9728 to declare the types it supports.
* The IANA request for an "authorization_details" type value is
withdrawn, since RFC 9396 keeps no such registry; whether the type
value becomes a URI is recorded as open.
* The scope-vocabulary limit is recorded as an open issue in its own
subsection, with the interface a companion document is expected to
meet and the rule under which such a document is cited.
* The chain linkage section states that "par_hash" commits to a
parent token instance, and what that means for re-issued parents
and their children.
* Step 8 denies an action under a cumulative constraint when no
component holds the running total it is measured over.
* An integer whose magnitude exceeds 2^53-1 is malformed.
* The revision states that it defines no transition mode for chains
shaped by the -01.
* Step 7 states that a cached status answer is trusted for its time
to live, that an unobtainable or unrefreshable status is unknown
and denies, and that a token issued without a status reference is
a choice made at issuance.
* A table states what a verifier that sees no request may and may
not conclude, and a table names the verification outcomes the test
vectors use.
* Several chains reaching one agent are addressed: each chain is
verified alone and never combined with another.
* Trust-anchor provenance is recorded as an open issue.
Asor Expires 30 April 2027 [Page 37]
Internet-Draft Agent Delegation Chain October 2026
* The fan-out security consideration gains the sibling and two-
gateway examples, the allocation/spending distinction, the two
deployment shapes for aggregate budgets, and the three hazards of
the allocation path.
* The revocation-latency security consideration gains the sustained
refresh rate, the resynchronisation case, the sizing requirement,
the counting of child re-issuance, and the revoke-at-refresh
burst.
* Root issuance is stated as the policy decision point in a new
security consideration.
* draft-klrc-aiagent-auth, now replaced, is re-pointed to draft-
ietf-wimse-aims in the introduction and the acknowledgments;
draft-jackson-wimse-evaluation, draft-ietf-wimse-identifier, RFC
6749, RFC 7942, and RFC 9728 are added as references.
* An Implementation Status section is added.
* The test-vector appendix records that the -01 set stays byte-
stable and does not conform to this revision, and describes the
second set that does.
* Step 8 and the constraint vocabulary state that a running total
reaches a cumulative constraint through a channel separate from
the request, that cumulative and per-action constraints are
evaluated against different inputs, and that a per-action "max" on
a running count bounds nothing.
Author's Address
Rafael Asor
Attenu
Email: rafael.asor@gmail.com
URI: https://attenu.io/
Asor Expires 30 April 2027 [Page 38]