| Internet-Draft | Agent Mandates | October 2026 |
| Hulea | Expires 27 April 2027 | [Page] |
This document defines how a relying party in one administrative domain validates the mandate under which a software agent, including an AI agent, acts for a principal in another domain. Its distinctive element is evidence of the delegator's authority: a statement from an authority source about which permissions the person or entity granting the mandate may delegate to agents, kept separate from the statement that the mandate was granted. The document specifies the mandate format with precisely defined limit semantics, a deterministic validation procedure driven by an explicit validation profile and kept separate from the relying party's authorization decision, the attribution of every validated claim to the issuer and role that asserted it, rules for enforcing the mandate after token exchange, and the boundary between this protocol and a trust framework. It reuses JSON Web Tokens, OAuth 2.0 Token Exchange, Rich Authorization Requests, WIMSE workload credentials and HTTP Message Signatures, Token Status Lists, and Entity Attestation Tokens.¶
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 27 April 2027.¶
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.¶
Software agents increasingly act on behalf of people and organizations in systems those people and organizations do not operate. A treasury agent run by a company initiates a payment at the company's bank. An agent run by a broker submits an instruction to a custodian. In each case the relying party has to decide whether to accept an action from an agent configured, authorized, and operated in another administrative domain.¶
Most building blocks exist. OAuth 2.0 Token Exchange [RFC8693] exchanges security tokens, including across security domains, and distinguishes the subject on whose behalf a request is made from the actor that makes it. Rich Authorization Requests [RFC9396] express fine-grained permissions. WIMSE workload credentials [I-D.ietf-wimse-workload-creds] bind a workload identifier to a key. Work on agents is advancing quickly: [I-D.ietf-wimse-aims] describes how existing standards apply to agent authentication and authorization, [I-D.asor-wimse-agent-delegation-chain] and [I-D.hamr-oauth-agent-delegation] define attenuated delegation chains, and [I-D.reece-wimse-cross-org-delegation] and [I-D.yossif-agent-mandate-problem] state requirements for cross-organization delegation and for verifiable mandates (Appendix C).¶
What is not yet defined is evidence that the party at the root of a mandate was entitled to grant it. A chain that only narrows proves that no hop exceeded its parent. It does not prove that the root was within the delegator's own authority, for example within the powers of a company's legal representative. This document adds that evidence, validates it together with the mandate under explicit rules, and keeps each claim attributed to the issuer that made it.¶
Interoperable mandate semantics. Independent implementations understand and check the same things: the structure of the mandate, the semantics of its limits, the delegation chain, the binding to a key, and revocation status (Section 4, Section 4.5).¶
Validation separate from authorization. Given the same inputs, including the same validation profile, two conforming Validators produce the same Validation Result. The relying party then applies its own policy (Section 9, Section 10.1).¶
Attribution of claims to issuers. The delegator's authority, the grant of the mandate, the operator's statement about the agent instance, and the state of the runtime come from different issuers. A relying party can tell exactly who asserted what (Section 11).¶
A clear boundary with the trust framework. This document defines how evidence is expressed and verified. Which issuers are accepted, what assurance levels mean, and which obligations issuers assume belong to a trust framework (Section 12).¶
This document does not:¶
determine whether an agent's reasoning or output is correct, or whether an action reflects the principal's present intent;¶
define a trust framework, assurance levels, or the legal effect of a mandate;¶
define how a delegator is shown a mandate or consents to it;¶
replace the relying party's authorization policy.¶
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.¶
The natural or legal person on whose behalf an agent acts.¶
The party that grants a root mandate: the principal itself, or a party holding authority to act for the principal.¶
A party that asserts that a delegator holds authority to act for a principal, for example a register of legal representatives.¶
The organization that runs an agent instance and controls its keys.¶
A running workload, identified by a workload identifier [I-D.ietf-wimse-arch], that holds a private key.¶
The entity that signs a root Mandate Assertion on the delegator's instruction. It may be the delegator itself.¶
A signed JWT expressing a mandate (Section 4). A root Mandate Assertion is signed by a Mandate Issuer; a sub-delegated one by the agent instance holding the parent mandate.¶
A signed JWT or SD-JWT [RFC9901] issued by an Authority Source (Section 5).¶
The artifacts an agent instance presents to a relying party (Section 7).¶
The entity in another administrative domain that receives the action request. In this document the RP's authorization server hosts the Validator and issues access tokens.¶
The RP component that executes the Mandate Validation Procedure.¶
A versioned document that fixes every rule the Validator applies beyond this specification (Section 8).¶
The set of rules, identified by a URI, under which issuers are accepted and evidence is interpreted (Section 12).¶
A condition that the Validator cannot evaluate from its inputs and that the RP has to discharge before it allows the action.¶
A named cumulative limit shared by all actions under the same root mandate that refer to it (Section 9.5).¶
+-----------+ Authority +-----------+
| Authority |------------->| Delegator |
| Source | Assertion +-----+-----+
+-----------+ | instructs
v
+-----------+
| Mandate |
| Issuer |
+-----+-----+
+-----------+ Workload | Mandate Assertion
| Operator |------------->+-----v-----+
+-----------+ Identity | Agent |
Token | Instance |
+-----------+ Attestation | |
| Verifier |------------->| |
+-----------+ Result +-----+-----+
| Mandate Presentation,
| signed HTTP request
v
+-----------+ Validation +-----------+
| Validator |------------->| RP |
+-----------+ Result | Policy |
+-----------+
An Authority Source issues an Authority Assertion stating that the delegator may act for the principal within stated powers.¶
A Mandate Issuer, on the delegator's instruction, issues a root Mandate Assertion bound to the agent instance's key and referencing the Authority Assertion.¶
The operator issues the agent instance a Workload Identity Token (WIT) [I-D.ietf-wimse-workload-creds] for the same key. A RATS Verifier [RFC9334] MAY issue an attestation result.¶
The agent instance sends a token exchange request carrying the evidence and the requested action, signed with its key (Section 7).¶
The Validator executes the Mandate Validation Procedure under a Validation Profile. The RP applies its policy, discharges Obligations, and issues a single-use access token (Section 10).¶
An agent instance MAY delegate a narrower mandate to another agent instance (Section 4.8).¶
A Mandate Assertion is a JWT [RFC7519] signed as a JWS [RFC7515].
The JOSE header typ value MUST be mandate+jwt. Implementations MUST
follow [RFC8725]. The algorithm MUST be one permitted by the
Validation Profile.¶
REQUIRED. Identifier of the Mandate Issuer, or, for a sub-delegated mandate, the workload identifier of the delegating agent instance.¶
REQUIRED. Workload identifier of the agent instance that holds the mandate.¶
REQUIRED. Unique identifier of the assertion.¶
REQUIRED. Confirmation claim [RFC7800] containing a jkt member,
the JWK SHA-256 thumbprint [RFC7638] of the holder's public key.¶
REQUIRED. A Party Identifier (Section 4.2) for the principal.¶
REQUIRED. A Party Identifier for the delegator. In a sub-delegated mandate, a Party Identifier for the delegating agent instance.¶
In a root mandate, REQUIRED unless delegator equals principal;
an array of Artifact References (Section 4.3) to Authority
Assertions. MUST NOT appear in a sub-delegated mandate.¶
REQUIRED. A non-empty array of Permission objects (Section 4.4).¶
REQUIRED in a sub-delegated mandate; MUST NOT appear in a root mandate. An Artifact Reference to the parent Mandate Assertion.¶
OPTIONAL. Non-negative integer: the number of further sub-delegations permitted below this mandate. Default 0.¶
OPTIONAL. Array of RP identifiers to which the mandate may be presented.¶
OPTIONAL. Status reference as defined in [I-D.ietf-oauth-status-list]. The Validation Profile states when it is required.¶
REQUIRED. URI of the Trust Framework under which the assertion was issued.¶
OPTIONAL. Assurance level asserted by the issuer. Its meaning is defined by the Trust Framework; the Validator reports it and does not interpret it.¶
A Party Identifier is a JSON object with two REQUIRED string members:
id, and scheme, a URI naming the identifier scheme. Two Party
Identifiers are equal if and only if both members are equal as
sequences of Unicode code points.¶
An Artifact Reference is a JSON object with a REQUIRED member dig,
the base64url-encoded SHA-256 digest of the ASCII bytes of the
referenced artifact's compact JWS serialization. For an SD-JWT, the
digest is computed over the issuer-signed JWT only. The OPTIONAL
members iss and jti are hints for locating the artifact; they play
no part in matching. A reference matches an artifact if and only if
the digests are equal.¶
A Permission object has the structure of an authorization details
object [RFC9396]: a REQUIRED type member and type-specific members,
including the common members locations, actions, datatypes,
identifier, and privileges. It MAY also contain constraints, an
array of Constraint objects (Section 4.5).¶
[RFC9396] does not define a general way to compare two authorization details objects, because the meaning of their members depends on the API. This document therefore applies its matching and attenuation rules only to types listed in the Validation Profile, each with a Type Profile (Section 8.1). A request of an unlisted type does not match.¶
Let the constrained members of P be the first reference tokens of the
ptr values of P's constraints. A requested authorization detail R
matches a Permission P at validation time T if and only if:¶
R.type equals P.type, and the type is listed in the Validation Profile.¶
For each of locations, actions, datatypes, and privileges
present in P, R contains the member and every element of R's array
is identical (Section 4.6) to an element of P's array.¶
Every other member of P except constraints is present in R with an
identical value.¶
Every top-level member of R is admitted by P: type, one of
locations, actions, datatypes, and privileges, a member of P,
a constrained member of P, or an admitted member of the Type Profile
(Section 8.1).¶
Every stateless constraint in P is satisfied by R at time T.¶
For every stateful constraint in P, the pointer resolves in R to a value of the type the predicate requires.¶
A Permission without one of locations, actions, datatypes, and
privileges places no restriction on that dimension. Likewise, an
admitted member of the Type Profile that P neither contains nor
constrains may take any value. Rule 4 prevents a request from carrying
any other member, which the mandate did not anticipate and which could
change the meaning of the action.¶
These rules, and those in Section 4.7, are fixed by this document. A Type Profile chooses which members are admitted; it cannot replace the comparison rules. Identity comparison and a registered set of predicates keep the result the same across implementations.¶
A Constraint object has the members pred (REQUIRED), ptr (a JSON
Pointer [RFC6901] evaluated against the requested authorization
detail; REQUIRED except for window), and value (REQUIRED). The
sum_max predicate also has the REQUIRED members period and
budget.¶
Amounts are decimal strings matching the ABNF below, compared as exact decimal numbers. JSON numbers MUST NOT be used for amounts.¶
decimal = ["-"] nonneg
nonneg = ("0" / (%x31-39 *DIGIT)) ["." 1*DIGIT]
¶
period is an integer number of seconds, at least 1 and at most the
maximum set by the Validation Profile. budget is a string.¶
If a pointer does not resolve, or resolves to a value of the wrong type, the constraint is not satisfied.¶
| pred | Kind | Satisfied when |
|---|---|---|
| eq | stateless | resolved value is identical to value
|
| in | stateless | resolved value is identical to an element of value
|
| max | stateless | resolved decimal is less than or equal to value
|
| min | stateless | resolved decimal is greater than or equal to value
|
| window | stateless |
value.nbf <= T < value.exp (no ptr) |
| sum_max | stateful | resolved value matches nonneg; produces an Obligation |
| cosign_above | stateful | produces an Obligation if resolved decimal exceeds value
|
For sum_max, value MUST match nonneg, and a negative resolved
value does not satisfy the constraint. All sum_max constraints with
the same budget in one Permission MUST have the same ptr, so that
an action contributes a single, well-defined amount to each budget; a
Permission that violates this makes its artifact malformed. Several
sum_max constraints may still share a budget and pointer with
different periods, for example a daily and a monthly limit on the same
amount. Refunds, reversals, and other
negative contributions are outside the scope of sum_max and need a
separately defined predicate.¶
A predicate not listed as supported in the Validation Profile makes the Permission not match.¶
Two JSON values are identical if they have the same type and: strings are equal as sequences of Unicode code points; booleans are identical only if both are true or both are false; null is identical to null; arrays have the same length and identical elements in order; objects have the same member names and identical member values. JSON numbers SHOULD NOT be used in Permission members or constraint values; when used, they are identical only if their textual representations are identical.¶
Attenuation is used for sub-delegation (Section 4.8) and for checking a root mandate against the delegator's powers (Section 9.4). A child Permission C is attenuated with respect to a parent Permission P if and only if:¶
C.type equals P.type.¶
For each of locations, actions, datatypes, and privileges
present in P, C contains the member and C's array contains only
elements identical to elements of P's array.¶
Every other member of P except constraints is present in C with
an identical value.¶
Every top-level member of C other than type and constraints is
admitted by P, in the sense of rule 4 of Section 4.4.¶
Every constrained member of C is admitted by P. A constraint in C can therefore only narrow the values of a member that P already admits; it cannot admit a member that P rejects.¶
For every constraint in P, C contains a constraint with the same
ptr that is at least as strict, per Table 2.¶
Together these rules ensure that every request matching C also matches P.¶
| Parent pred | Child constraint is at least as strict when |
|---|---|
| eq |
eq with identical value
|
| in |
in with value a subset, or eq with value an element |
| max |
max with value less than or equal |
| min |
min with value greater than or equal |
| window |
window with nbf not earlier and exp not later |
| sum_max |
sum_max with identical budget, value less than or equal, period greater than or equal |
| cosign_above |
cosign_above with value less than or equal |
The sum_max rule is sound because contributions are non-negative and
the budget is shared (Section 9.5): the sum over the parent's
period is at most the sum over the longer child period, which the
child's constraint keeps at or below a value no greater than the
parent's.¶
A set of child Permissions is attenuated with respect to a set of parent Permissions if every child Permission is attenuated with respect to at least one parent Permission.¶
An agent instance whose mandate has max_depth of at least 1 MAY issue
a sub-delegated Mandate Assertion. The sub-delegated assertion:¶
is signed with the private key whose thumbprint is the parent's
cnf.jkt, and carries the corresponding public key in the jwk
member of its protected JOSE header;¶
has iss equal to the parent's sub;¶
has principal and tf equal to the parent's;¶
has exp not later than the parent's;¶
has max_depth at most the parent's max_depth minus 1;¶
has aud, if the parent has aud, containing only elements of the
parent's aud;¶
has perms attenuated with respect to the parent's perms.¶
The key in the jwk header is not a trust anchor. It is accepted only
because the already verified parent mandate binds its thumbprint.¶
The agent instance presents a WIT [I-D.ietf-wimse-workload-creds]
issued by its operator. Under this profile the WIT MUST contain iss.
The WIT sub MUST equal the leaf mandate's sub, and the JWK SHA-256
thumbprint of the WIT's cnf.jwk MUST equal the leaf mandate's
cnf.jkt. The WIT is referenced by digest; it carries no tf, and its
issuer is checked against operator anchors accepted for the
framework context (Section 9).¶
The WIT asserts that the operator runs an agent instance with this identifier and key. It asserts nothing about the model, configuration, or behavior of the instance.¶
An agent instance MAY present an attestation result from a RATS
Verifier [RFC9334], encoded as a JWT-based EAT [RFC9711] with typ
value eat+jwt and the claims iss, iat, exp, eat_profile, and
cnf with a jkt member. The eat_profile value MUST be one accepted
by the Validation Profile, which also fixes the meaning of the result.
The cnf.jkt MUST equal the leaf mandate's cnf.jkt.¶
An attestation result describes the Verifier's appraisal of evidence at the time the evidence was produced, not the state of the instance afterwards [RFC9334]. When the instance obtains model output from a remote service, the result covers the remote model only if the appraised evidence covered it.¶
An agent instance MAY present an Exposure Statement: a JWT with typ
value agent-exposure+jwt, signed by a control component that observes
the instance's session (the observer), not by the agent instance. It
contains:¶
iss, jti, iat, exp, and sub (the agent instance);¶
aud: the identifier of the single RP to which the statement may be
presented;¶
cnf with a jkt member equal to the leaf mandate's cnf.jkt;¶
sid: an identifier, assigned by the observer, of the session it
observed;¶
nonce: the value of the nonce parameter of the HTTP Message
Signature of the request it accompanies (Section 7.2);¶
ad_hash: the base64url-encoded SHA-256 digest of the bytes of the
authorization_details parameter value of that request, as sent;¶
exposure: an array of exposure event types from Section 15.6
that the observer recorded in session sid up to iat, sorted by
code point, without duplicates.¶
The agent instance obtains the statement from the observer for one specific request to one RP, supplying the RP identifier and the signature nonce it will use. The statement is single-use:¶
aud restricts it to one RP, so the same statement cannot be
presented at a second RP;¶
the RP's authorization server consumes it, as described below, only after the Validator has accepted it for this presentation.¶
The authorization server proceeds in this order:¶
It verifies the HTTP Message Signature and runs the Validator.¶
If the outcome is invalid, it rejects the request. No Exposure
Statement is consumed.¶
Otherwise, it takes the deduplicated set of pairs (iss, jti) of
the Exposure Statements listed in the result's evidence, and only
those. In one atomic operation, if any pair in the set is already
recorded, it rejects the request and records none of them;
otherwise it records all of them, each with the statement's
verified exp.¶
It then applies its policy and continues with authorization.¶
A presentation that is invalid, and a statement the Validator
rejected, therefore never change the record. A forged statement that
copies a legitimate iss and jti, or an authentic statement
presented with another key or nonce, cannot consume the legitimate
one. Each record MUST be kept until the recorded exp plus
max_clock_skew, independently of how long signature nonces are
kept. A statement is consumed once recorded, even if the RP's policy
later refuses the action. Consumption is tracked outside the
Validator, which remains a deterministic function of its inputs. The
statement describes the session the observer attributes to that
request. exp minus iat MUST NOT exceed the Validation Profile's
maximum for Exposure Statements. An empty exposure array means that
no registered event was observed, not that the session was free of
manipulation.¶
The observer MAY be run by the operator, but its signing key MUST NOT
be accessible to the agent instance. Each exposure_observer trust
anchor lists the WIT issuers whose sessions it may observe.¶
This document profiles OAuth 2.0 Token Exchange [RFC8693]. The agent instance is the client of the RP's authorization server.¶
The request contains:¶
subject_token: the leaf Mandate Assertion;¶
subject_token_type: urn:ietf:params:oauth:token-type:agent-mandate;¶
actor_token: the agent instance's WIT;¶
actor_token_type: urn:ietf:params:oauth:token-type:jwt;¶
authorization_details: an array containing exactly one
authorization details object [RFC9396], the requested action. This
version authorizes one action per request and per token;¶
mandate_evidence: a JSON array of strings, each the compact
serialization of a parent Mandate Assertion, an Authority Assertion,
an attestation result, or an Exposure Statement. REQUIRED when the
leaf is sub-delegated or references an Authority Assertion.¶
The client MUST sign the request with HTTP Message Signatures
[RFC9421] as profiled for workloads by
[I-D.ietf-wimse-http-signature], using the key confirmed by the WIT.
The signature MUST cover at least @method, @target-uri, the
Content-Digest header field [RFC9530], and the
Workload-Identity-Token header field, and MUST carry the created,
expires, and nonce parameters. The Workload-Identity-Token header
field MUST carry the same WIT as actor_token. expires minus
created MUST NOT exceed the Validation Profile's max_pop_window.¶
Because the request body carries the mandate, the evidence, and the
requested authorization details, and Content-Digest covers the body,
the signature binds the key, the RP endpoint, the mandate, and the
requested action, and its parameters give freshness. The authorization
server MUST reject a nonce it has already accepted within the
signature's validity period. The Workload Proof Token
[I-D.ietf-wimse-wpt] is not used because it does not cover the
request body.¶
The PoP outcome given to the Validator (Section 9.1) is ok if and only
if all of these checks succeed; the verified nonce value is also
given to the Validator.¶
The Validation Profile is a JSON document fixing every rule that influences the Validation Result and is not fixed by this specification. It is identified by a URI and by the base64url-encoded SHA-256 digest of its bytes. It contains at least:¶
max_clock_skew, max_pop_window, max_token_lifetime, and
max_status_age, in seconds;¶
max_chain_length, the greatest number of Mandate Assertions in a
chain;¶
predicates: the supported constraint predicates;¶
status_values (optional): a mapping from Token Status List values
other than 0x00, 0x01, and 0x02 to valid, revoked, or
suspended;¶
types: the supported authorization details types, each with its
Type Profile included in full (Section 8.1);¶
eat_profiles: the accepted eat_profile values;¶
frameworks: one entry per accepted Trust Framework URI, with:¶
algs: permitted signature algorithms;¶
party_schemes: accepted Party Identifier schemes;¶
max_lifetime: per artifact type, the maximum of exp minus
iat, including max_period for sum_max and the maximum for
Exposure Statements;¶
status_required: the artifact types that MUST carry status;¶
authority_frameworks: the Trust Framework URIs whose Authority
Assertions are accepted for mandates under this framework. The
framework's own URI is accepted only if listed.¶
The Validation Profile reflects the Trust Framework rules that a machine can check. It does not contain the RP's authorization policy.¶
A Type Profile is part of the Validation Profile document, so the profile's digest fixes it; it MUST NOT refer to external content that influences validation. For an authorization details type it states:¶
a JSON Schema for requested authorization details of the type, included in full;¶
its admitted members: top-level members a request may carry without the Permission mentioning them, each of which is unrestricted unless a Permission contains or constrains it;¶
the meaning of each admitted member, so that "unrestricted" has a defined effect.¶
The schema applies to the requested authorization detail; a request
that does not conform gives request_malformed. Permissions are not
validated against it, because they may omit members a request needs. A
Permission member the schema forbids simply cannot be matched, since
matching requires the conforming request to carry it.¶
Schemas MUST use JSON Schema draft 2020-12 [JSON-SCHEMA-CORE]
[JSON-SCHEMA-VALIDATION] and MUST declare it with the $schema
keyword value https://json-schema.org/draft/2020-12/schema. A schema
MAY use only the Core, Applicator, and Validation vocabularies and the
Format-Annotation vocabulary; format is an annotation and never
causes a request to fail validation. $ref MUST resolve within the
same schema. A Validation Profile containing a schema that violates
these rules, or a keyword outside those vocabularies, is unusable: a
Validator MUST refuse to load it and MUST NOT validate under it.¶
The procedure takes exactly these inputs:¶
the Mandate Presentation;¶
the bytes of the authorization_details parameter and its parsed
value;¶
the validation time T;¶
the Validation Profile and its digest;¶
a Trust Anchor Set partitioned by role: mandate_issuer,
authority_source, operator, verifier, exposure_observer, and
status_issuer; each anchor lists its keys and the Trust Framework
URIs for which it is accepted; each exposure_observer anchor also
lists the WIT issuers it may observe, and each status_issuer anchor
lists the artifact issuers for which it may publish status;¶
a set of Status List Tokens [I-D.ietf-oauth-status-list];¶
the RP identifier;¶
the PoP outcome and the verified signature nonce (Section 7.2).¶
Two conforming Validators given identical inputs MUST produce identical Validation Results. A Validator MUST NOT consult any other input and MUST NOT apply local authorization policy. Status List Tokens are fetched before validation.¶
Required evidence is the leaf Mandate Assertion, its ancestors, the Authority Assertions referenced by the root, and the WIT. Optional evidence is attestation results and Exposure Statements. A problem with required evidence is an error. A problem with optional evidence, and the reason a Permission did not match a request, is a diagnostic. Only errors affect the outcome.¶
The Validator performs every step that can be performed and records every applicable code (Section 15.5); it does not stop at the first failure.¶
Chain and context. Starting from the leaf, follow parent
references through the artifacts in mandate_evidence. A reference
without a matching artifact gives chain_broken; more than
max_chain_length mandates gives chain_too_long. If a root is
reached, the framework context is the root's tf; if that URI is
not in the Validation Profile, framework_not_accepted. If no root
is reached, the framework context is undetermined, steps that need
it are skipped, the authority check is not evaluated, and chain
in the result lists the mandates that were recovered, starting with
the highest recovered ancestor.¶
Structure. Each required artifact parses, has the expected
typ, and contains its REQUIRED claims. Otherwise malformed.¶
Profile conformance. Under the framework context: algorithms are
permitted (alg_not_allowed); Party Identifier schemes are accepted
(scheme_not_accepted); exp minus iat does not exceed the
maximum for the artifact type (lifetime_exceeded); and every
artifact of a type in status_required carries status
(status_missing).¶
Signatures and keys. The root verifies under a mandate_issuer
anchor accepted for the framework context. Each sub-delegated
mandate carries a jwk header (key_missing), whose thumbprint
equals the parent's cnf.jkt (key_mismatch), and verifies with
it. Each Authority Assertion verifies under an authority_source
anchor accepted for the assertion's own tf. The WIT verifies under
an operator anchor accepted for the framework context. A failed
verification gives signature_invalid; a key trusted only for
another role gives role_mismatch.¶
Framework compatibility. Every mandate's tf equals the
framework context, and every Authority Assertion's tf is in the
context framework's authority_frameworks. Otherwise
framework_mismatch.¶
Time. For each required artifact, nbf (when present) is at
most T + max_clock_skew, and T is less than exp +
max_clock_skew. Otherwise not_yet_valid or expired.¶
Status. The applicable framework of an artifact is its own tf
for an Authority Assertion and the framework context for every other
artifact. For each required artifact with status, the eligible
Status List Tokens are those in the inputs whose subject is the
referenced status list URI, that verify under a status_issuer
anchor listing the artifact's issuer and accepted for the
artifact's applicable framework, and whose iat is at most
T + max_clock_skew, whose exp (when present) is later than T,
and for which T minus iat does not exceed max_status_age. If no
token is eligible, the code is status_unavailable. Otherwise, let
the candidates be the eligible tokens with the greatest iat. If
they give different status values for the index, the code is
status_unavailable. Otherwise the Validator selects one candidate:
the one with the latest exp, a token without exp counting as
latest, and among those the one whose digest is first in code point
order. The selection does not depend on the order of the inputs and
is reported in status_evidence. The selected status value gives
nothing if it is VALID (0x00), revoked if INVALID (0x01), and
suspended if SUSPENDED (0x02). Any other value, including
application-specific values, gives status_unavailable, unless the
Validation Profile's status_values maps it to one of these three.
A later token showing reactivation prevails over an earlier
suspension.¶
Links. Each sub-delegated mandate satisfies Section 4.8. Otherwise
depth_exceeded or not_attenuated.¶
Authority. See Section 9.4.¶
Binding. The WIT matches the leaf (Section 6.1) and the PoP
outcome is ok. Otherwise binding_mismatch or pop_failed.¶
Audience. For each mandate in the chain with aud, the RP
identifier is an element of aud. Otherwise audience_mismatch.¶
Action match. The authorization_details array contains
exactly one object, which conforms to its Type Profile schema.
Otherwise request_malformed. The alternatives are all Permissions
of the leaf that match it at time T (Section 4.4). If there are
none, action_not_permitted. For each Permission that does not
match, the diagnostic perm_not_matching is recorded with the
Permission's index.¶
Optional evidence. Each attestation result and Exposure
Statement is checked as required evidence would be in steps 2 to 4,
6, and 7, and against Section 6.2 or Section 6.3. An Exposure Statement
also needs aud equal to the RP identifier, nonce equal to the
verified signature nonce, ad_hash equal to the digest of the
authorization_details bytes, and an anchor listing the WIT's
issuer. Failures are diagnostics
(evidence_rejected), and the artifact is listed under rejected
rather than evidence.¶
The outcome is invalid if any error other than status_unavailable
was recorded; otherwise indeterminate if status_unavailable was
recorded; otherwise valid.¶
Each alternative carries the Obligations of its Permission's stateful constraints, in the order of the constraints. An Obligation is a JSON object:¶
sum_max: members type ("sum_max"), constraint (index in the
Permission), root (the root mandate jti), budget, period,
value, and amount (the resolved value of this request). Let A be
the authorization time (Section 10.2). The sum of the contributions
recorded under the same root and budget with a recording time t
such that A minus period < t <= A, plus amount, MUST NOT exceed
value. The contribution is recorded with time A.¶
cosign_above: members type ("cosign_above"), constraint,
value, and amount. If amount exceeds value, a second party
designated by the RP's policy MUST approve the specific action.¶
Alternatives are independent. Constraints in different Permissions
share accounting only when they name the same budget, which lets a
mandate issuer impose one limit across several Permissions. Because
sub-delegated sum_max constraints keep the parent's budget
(Table 2), actions taken under any mandate in a chain
count against the same budget.¶
The RP performs the check and records the contribution as one atomic operation at time A, so that concurrent requests cannot both pass against the same remaining budget, and a request validated earlier cannot use a window anchored at its validation time. Because each token authorizes one action, each token records exactly one contribution per budget. If the token expires unused, the RP MAY remove the contribution.¶
The Validation Result is a JSON object with the members:¶
outcome: valid, invalid, or indeterminate;¶
profile: the Validation Profile URI and digest;¶
time: T;¶
tf: the framework context, or null if undetermined;¶
chain: Artifact References for the mandates, root first;¶
errors and diagnostics: arrays of objects with the member code
and, where applicable, artifact (an Artifact Reference) and perm
(index);¶
authority: self, established, unknown, refuted, or
not_evaluated when no root was reached;¶
claims: attributed claims (Section 11), each with claim,
value, artifact, and role;¶
alternatives: an array of objects with perm (the leaf Permission
index) and obligations, sorted by perm;¶
evidence and rejected: Artifact References for the optional
evidence that was accepted or rejected;¶
status_evidence: for each artifact whose status was read from a
selected Status List Token, an object with artifact (an Artifact
Reference), token (the base64url-encoded SHA-256 digest of the
selected token), and required (true for required evidence, false
for optional evidence), sorted by artifact.dig.¶
claims contains only authenticated claims: claims of artifacts whose
signature and role verification in step 4, or step 13 for optional
evidence, succeeded. Claims of an artifact that failed verification
are omitted; the artifact remains identified through chain, errors,
or rejected. Subject to that rule, claims contains exactly the
following, and nothing else:¶
for each mandate in chain, in order: iss, sub, principal,
delegator, perms, and loa if present;¶
for each Authority Assertion that supports the root, in the order of
the root's authority array: iss, principal, delegator,
powers, max_depth, and loa if present;¶
for the WIT: iss and sub;¶
for each accepted attestation result, in evidence order: iss,
eat_profile, and iat;¶
for each accepted Exposure Statement, in evidence order: iss,
sid, exposure, and iat.¶
Within an artifact, claims appear in the order listed. errors and
diagnostics are sorted by code, then artifact.dig, then perm,
comparing strings by code point and placing absent members first;
duplicates are removed. evidence and rejected are sorted by dig.¶
The authorization time A is read from the RP's clock inside the atomic
operation that discharges Obligations and issues the token. A is not
earlier than T. At A, the RP MUST check again that A is earlier than
the exp of every mandate in the chain and of the supporting
Authority Assertion, plus max_clock_skew, and that every window
constraint of the selected alternative is satisfied at A; otherwise it
denies.¶
At A, the RP also checks whether each token listed in
status_evidence is still eligible: A minus its iat does not exceed
max_status_age, and its exp, when present, is later than A. The
treatment keeps the distinction between required and optional
evidence:¶
If a token for required evidence is no longer eligible, the RP MUST
either obtain fresh Status List Tokens and run the Mandate
Validation Procedure again with T = A, or treat the outcome as
indeterminate and apply its policy for that outcome.¶
If a token for optional evidence is no longer eligible, that evidence MUST NOT be relied on at A, and the RP applies its policy again without it. If the policy requires that evidence for the action, the RP denies or obtains fresh evidence and validates again.¶
The Validation Result computed at T is kept unchanged as a record of that validation; the checks at A are recorded with the authorization decision. A Validation Result therefore cannot carry a revocation check past the freshness the Validation Profile allows, however long the RP takes to decide, for example while waiting for a co-signature.¶
An access token issued under this profile:¶
MUST be sender-constrained to the key with the leaf's cnf.jkt;¶
MUST carry only the single authorization details object that was allowed;¶
MUST carry an act claim identifying the agent instance, and the
jti of the leaf and root mandates;¶
MUST have an exp no later than the earliest of: the exp of every
mandate in the chain and of the supporting Authority Assertion, the
exp of any window constraint in the selected alternative, and A
plus max_token_lifetime;¶
MUST authorize a single execution of the action; the resource server MUST reject a second use of the same token.¶
The bound on the token's exp ensures that the action cannot be
executed after a time window or a mandate has ended. A revocation after
issuance takes effect at the latest when the token expires; an RP that
needs it to take effect sooner validates again at execution.¶
Each artifact carries only the claims its issuer is in a position to make.¶
| Artifact | Issuer role | Asserts | Does not assert |
|---|---|---|---|
| Authority Assertion | Authority Source | delegator may delegate the stated powers for the principal, per the source's records | that any mandate was issued or intended |
| Root Mandate Assertion | Mandate Issuer | delegator granted the permissions to the key | that the delegator had authority |
| Sub-delegated Mandate Assertion | Delegating agent instance | further delegation within the parent's scope | anything beyond the parent |
| WIT | Operator | instance identifier bound to the key | model, configuration, behavior |
| Attestation result | Verifier | appraisal of runtime evidence at a point in time | later state; a remote model unless covered |
| Exposure Statement | Observer | exposure events recorded in the session attributed to one presentation, up to iat
|
absence of manipulation |
A Validator MUST report each claim with the artifact and role it came from, and MUST NOT treat a claim as established by an artifact whose role does not cover it. In particular, a Mandate Assertion alone never establishes the delegator's authority. Trust anchors are role-specific; an entity holding several roles SHOULD use a distinct key for each.¶
No artifact defined here asserts that the agent's reasoning is correct or that an action reflects the principal's present intent.¶
the formats of Mandate Assertions, Authority Assertions, and Exposure Statements, and the profiles of WIT and EAT;¶
the semantics of Permissions, constraint predicates, and attenuation;¶
the Validation Profile structure and the Mandate Validation Procedure, its codes, and its result;¶
the proof-of-possession profile and the rules for access tokens.¶
A Trust Framework is identified by the URI in tf. It MUST define:¶
the entities accepted for each role and how their anchors are distributed;¶
the Party Identifier schemes accepted;¶
the meaning of each loa value and the evidence it requires;¶
the permitted algorithms;¶
maximum lifetimes and when status is required;¶
values or bounds for the Validation Profile parameters;¶
requirements on Authority Sources, including the records they rely on, and which other frameworks' Authority Assertions are accepted;¶
the obligations and liability of issuers, including revocation and incident timelines;¶
retention of Validation Results and handling of disputes;¶
the authorization details types and their Type Profiles;¶
how a Mandate Issuer establishes that the instruction to issue a mandate came from the delegator named in it, for example by requiring the delegator's signature over the mandate content;¶
whether and how RPs share accounting for budgets.¶
The machine-checkable part of items 2 to 7 and 10 is expressed in the Validation Profile. The protocol verifies that the delegator holds authority and that the Mandate Issuer states that the delegator granted the mandate. It cannot verify the link between the two inside the delegator's organization; that link rests on the Mandate Issuer, under item 11.¶
A Trust Framework can be a bilateral agreement, a sector scheme, or a regulated scheme. This document takes no position on which.¶
Issuer compromise. Short lifetimes limit the use of a stolen credential but not an attacker who controls an issuer and can issue new artifacts. The exposure window depends on detection, withdrawal of trust in the issuer, and propagation of that decision. Transparency logs [RFC9162] make suspicious issuance visible but do not prevent it. Trust Frameworks need distrust procedures.¶
Replay. Mandates are bound to a key; each request is signed with
it, and the signature's nonce, time window, and body digest prevent
reuse of a request. Access tokens are single-use. aud restricts where
a mandate may be presented.¶
Broad mandates. The format can express narrow mandates but cannot force issuers to write them. Trust Frameworks and RPs can require specific constraints for specific action types.¶
Cumulative limits across RPs. An RP accounts only for actions it
has allowed. A mandate accepted by several RPs that do not share state
lets an agent, compromised or not, reach a budget at each RP. Mandates
with sum_max constraints SHOULD therefore carry an aud naming
exactly one RP, unless the Trust Framework defines shared accounting.
Without either, a budget is a per-RP limit, not a limit on the mandate.¶
Prompt injection and confused deputies. A valid mandate shows that an action is within delegated authority, not that the agent was not manipulated into requesting it. Exposure Statements, constrained agent outputs, and RP policy reduce but do not remove this risk.¶
Status availability. When status cannot be established, the
outcome is indeterminate and the RP denies by default. The Validation
Profile makes status mandatory where the Trust Framework requires it,
so an issuer cannot avoid revocation checks by omitting it.¶
Resource consumption. max_chain_length bounds chain processing.
Validators SHOULD bound the number and size of artifacts.¶
Exact comparison. Amounts are decimal strings, pointers are exact, identity is defined on code points, and result arrays have a defined order, so independent implementations reach the same result.¶
Long-term verifiability. Validation Results retained for disputes may need to be verifiable for years. This requires preserving validation data and renewing evidence [RFC4998], and migrating to new algorithms, including post-quantum algorithms, as Trust Frameworks permit them.¶
Remote models. Attestation results cover what the Verifier appraised, not a model served by a third party unless that party's evidence was appraised.¶
Mandate Presentations disclose the principal and delegator to the RP. Issuers SHOULD use pairwise or role identifiers where the Trust Framework permits, and Authority Sources SHOULD use SD-JWT [RFC9901] for personal attributes of the delegator that do not affect validation. Digests and identifiers can correlate presentations across RPs. The privacy considerations of [I-D.ietf-oauth-status-list] apply.¶
This document requests registration of application/mandate+jwt,
application/authority+jwt, application/authority+sd-jwt, and
application/agent-exposure+jwt. Templates to be provided.¶
This document requests registration of the claims principal,
delegator, authority, perms, parent, max_depth, tf, loa,
powers, ad_hash, and exposure in the "JSON Web Token Claims"
registry. The Exposure Statement reuses the registered sid and
nonce claims with the meaning defined in Section 6.3.¶
This document requests registration of the token type URI
urn:ietf:params:oauth:token-type:agent-mandate in the "OAuth URI"
registry and of the parameter mandate_evidence in the "OAuth
Parameters" registry.¶
This document requests a new registry, "Agent Mandate Constraint Predicates", with Specification Required policy. Each entry contains the predicate name, its kind, its satisfaction rule, its attenuation rule, the value types it accepts, and a reference. Initial contents are given in Table 1 and Table 2.¶
This document requests a new registry, "Agent Mandate Validation
Codes", with Specification Required policy. Each entry has a code and
a class, error or diagnostic. Initial errors: malformed,
chain_broken, chain_too_long, framework_not_accepted,
alg_not_allowed, scheme_not_accepted, lifetime_exceeded,
status_missing, key_missing, key_mismatch, signature_invalid,
role_mismatch, framework_mismatch, not_yet_valid, expired,
revoked, suspended, status_unavailable, depth_exceeded,
not_attenuated, authority_missing, authority_mismatch,
authority_insufficient, binding_mismatch, pop_failed,
audience_mismatch, request_malformed, action_not_permitted.
Initial diagnostics:
perm_not_matching, evidence_rejected.¶
This document requests a new registry, "Agent Exposure Event Types", with Specification Required policy. Initial values:¶
external_content: the session processed content retrieved from
outside the operator's domain that was not on an allow list;¶
unauthenticated_tool: the session invoked a tool or service whose
identity was not authenticated;¶
untrusted_agent_input: the session processed output from an agent
instance whose mandate was not validated.¶
A company's treasury agent holds a mandate from the company's financial director and delegates part of it to a reconciliation agent, which initiates a payment at the company's bank. Payloads are shown decoded and unsigned; identifiers are fictional; digests, keys, and some values are elided as "...". Signed vectors will accompany a future revision.¶
The bank's Validation Profile includes a Type Profile for
payment_initiation whose admitted members are instructedAmount,
creditorAccount, and remittanceInformation. A Permission that does
not constrain one of them leaves it unrestricted.¶
Authority Assertion from a company register, stating which payments the director may delegate to agents:¶
{
"iss": "https://register.example",
"jti": "aa-5c1e",
"iat": 1792800000,
"exp": 1824336000,
"principal": {"id": "J40/0000/2020", "scheme": "urn:example:reg"},
"delegator": {"id": "p-41f9", "scheme": "urn:example:pairwise"},
"powers": [{
"type": "payment_initiation",
"constraints": [
{"pred": "eq", "ptr": "/instructedAmount/currency",
"value": "EUR"},
{"pred": "max", "ptr": "/instructedAmount/amount",
"value": "100000.00"}
]
}],
"max_depth": 1,
"tf": "https://tf.example/finance"
}
¶
Root Mandate Assertion to the treasury agent:¶
{
"iss": "https://mandates.treasury.example",
"sub": "spiffe://treasury.example/agents/payments-7",
"jti": "ma-90b2",
"iat": 1792886400,
"nbf": 1792886400,
"exp": 1795478400,
"cnf": {"jkt": "..."},
"principal": {"id": "J40/0000/2020", "scheme": "urn:example:reg"},
"delegator": {"id": "p-41f9", "scheme": "urn:example:pairwise"},
"authority": [{"dig": "...", "iss": "https://register.example"}],
"perms": [{
"type": "payment_initiation",
"actions": ["initiate"],
"locations": ["https://bank.example/payments"],
"constraints": [
{"pred": "eq", "ptr": "/instructedAmount/currency",
"value": "EUR"},
{"pred": "max", "ptr": "/instructedAmount/amount",
"value": "20000.00"},
{"pred": "in", "ptr": "/creditorAccount/iban",
"value": ["RO49AAAA1B31007593840000",
"DE89370400440532013000"]},
{"pred": "sum_max", "ptr": "/instructedAmount/amount",
"value": "50000.00", "period": 2592000,
"budget": "monthly-out"},
{"pred": "cosign_above", "ptr": "/instructedAmount/amount",
"value": "10000.00"}
]
}],
"max_depth": 1,
"aud": ["https://bank.example"],
"tf": "https://tf.example/finance",
"loa": "substantial"
}
¶
Protected header of the sub-delegated mandate, carrying the treasury agent's public key:¶
{
"typ": "mandate+jwt",
"alg": "EdDSA",
"jwk": {"kty": "OKP", "crv": "Ed25519", "x": "..."}
}
¶
Sub-delegated Mandate Assertion to the reconciliation agent:¶
{
"iss": "spiffe://treasury.example/agents/payments-7",
"sub": "spiffe://treasury.example/agents/reconcile-2",
"jti": "ma-17c4",
"iat": 1792890000,
"nbf": 1792890000,
"exp": 1792976400,
"cnf": {"jkt": "..."},
"principal": {"id": "J40/0000/2020", "scheme": "urn:example:reg"},
"delegator": {"id": "spiffe://treasury.example/agents/payments-7",
"scheme": "urn:example:workload"},
"parent": {"dig": "..."},
"perms": [{
"type": "payment_initiation",
"actions": ["initiate"],
"locations": ["https://bank.example/payments"],
"constraints": [
{"pred": "eq", "ptr": "/instructedAmount/currency",
"value": "EUR"},
{"pred": "max", "ptr": "/instructedAmount/amount",
"value": "5000.00"},
{"pred": "eq", "ptr": "/creditorAccount/iban",
"value": "DE89370400440532013000"},
{"pred": "sum_max", "ptr": "/instructedAmount/amount",
"value": "20000.00", "period": 2592000,
"budget": "monthly-out"},
{"pred": "cosign_above", "ptr": "/instructedAmount/amount",
"value": "5000.00"}
]
}],
"aud": ["https://bank.example"],
"tf": "https://tf.example/finance"
}
¶
Requested authorization detail:¶
{
"type": "payment_initiation",
"actions": ["initiate"],
"locations": ["https://bank.example/payments"],
"instructedAmount": {"currency": "EUR", "amount": "4000.00"},
"creditorAccount": {"iban": "DE89370400440532013000"}
}
¶
Validation Result, abbreviated. The amount does not exceed the co-signature threshold, so the only Obligation is the shared budget:¶
{
"outcome": "valid",
"profile": {"uri": "https://bank.example/profiles/agents/3",
"dig": "..."},
"time": 1792972800,
"tf": "https://tf.example/finance",
"chain": [{"dig": "..."}, {"dig": "..."}],
"errors": [],
"diagnostics": [],
"authority": "established",
"claims": ["..."],
"alternatives": [{
"perm": 0,
"obligations": [{
"type": "sum_max", "constraint": 3, "root": "ma-90b2",
"budget": "monthly-out", "period": 2592000,
"value": "20000.00", "amount": "4000.00"
}]
}],
"evidence": [],
"rejected": [],
"status_evidence": []
}
¶
At authorization time A, the bank checks again that both mandates and
the Authority Assertion are unexpired, records 4000.00 against budget
monthly-out of root ma-90b2 in the same atomic operation, and
issues a single-use token whose exp is no later than 1792976400, the
exp of the sub-delegated mandate.¶
Signed test vectors for the following cases are planned. Each lists the expected result.¶
| Case | Expected result |
|---|---|
Valid chain with two delegations; keys in jwk headers |
valid
|
Sub-delegated mandate without jwk header |
invalid, key_missing
|
Authority Assertion under a framework not in authority_frameworks
|
invalid, framework_mismatch
|
Request matching two Permissions with different sum_max
|
valid; two alternatives, each with its own Obligations |
| Valid mandate plus attestation result with a bad signature |
valid; evidence_rejected diagnostic |
Child sum_max with longer period; negative earlier contribution |
request with a negative amount does not match; budget shared |
SD-JWT Authority Assertion with _sd inside powers
|
invalid, malformed
|
| Status List Token unavailable for a required status |
indeterminate, status_unavailable
|
| Status unavailable only for the supporting Authority Assertion |
indeterminate; authority is unknown; no authority error |
| Two eligible Status List Tokens; later one revokes |
invalid, revoked
|
Two eligible Status List Tokens with equal iat and different status |
indeterminate, status_unavailable
|
| Child adds a constraint on a member the parent does not admit |
invalid, not_attenuated
|
Root constrains a member admitted by the Type Profile but absent from powers
|
valid
|
Root max_depth greater than the Authority Assertion's |
invalid, authority_insufficient
|
| Exposure Statement reused with a new signature nonce |
evidence_rejected diagnostic |
| Exposure Statement presented at a second RP |
evidence_rejected diagnostic (aud mismatch) |
Forged Exposure Statement copying a legitimate iss and jti
|
evidence_rejected; consumption record unchanged |
| Authentic Exposure Statement presented with another agent's key or nonce |
evidence_rejected; later legitimate presentation succeeds |
Accepted Exposure Statement in a presentation that is invalid (binding_mismatch) |
request rejected; statement not consumed |
| Accepted Exposure Statement, action later refused by RP policy | statement remains consumed |
Two Status List Tokens with equal iat and status, different exp
|
token with later exp selected, regardless of input order |
| Only an optional evidence status token too old at A | evidence not relied on; RP policy reapplied; outcome unchanged |
| Exposure Statement reused at the same RP after the first signature expired | request rejected by the authorization server (consumed jti) |
Status fresh at T but older than max_status_age at A |
fresh validation at A, or indeterminate path |
Two sum_max with the same budget and different ptr in one Permission |
invalid, malformed
|
Validation Profile with a schema lacking $schema 2020-12 |
profile refused; no validation |
| Chain without a reachable root |
invalid, chain_broken; authority is not_evaluated
|
| Mandate in the chain with an invalid signature |
invalid, signature_invalid; its claims omitted |
| Status issuer accepted only under another framework |
indeterminate, status_unavailable
|
Status value 0x03 with no mapping in status_values
|
indeterminate, status_unavailable
|
| Two requests validated at the same T, both within budget alone | second denied at authorization time A |
Token used after the sub-delegated mandate's exp
|
rejected at the resource server |
Alignment of the chain format with [I-D.asor-wimse-agent-delegation-chain].¶
A CBOR/CWT encoding.¶
Presentation outside OAuth Token Exchange.¶
Shared budget accounting across RPs.¶
Cumulative limits on a delegator's authority across root mandates, for example a budget identifier issued by the Authority Source.¶
Several actions in one request or token, with atomic reservation for the whole batch.¶
A predicate for refunds and reversals.¶
Signed test vectors for the conformance cases.¶
A human-readable rendering of mandates for delegator consent.¶
TBD.¶