Specifications Draft for comment

Emissar Mandate v0.1

A scoped, revocable credential that says what an AI agent may do for one person or company, and an A2A extension for presenting it in a task.

JSON Schema · Demo (Node) · Validator (Python) · Example mandate

Field Value
Version 0.1, draft for comment
Date 2026-09-26; published for comment 2026-10-05
Author Emissar team
Extension URI https://emissar.ai/ext/mandate/v1 (redirects to this document)
Credential media type application/vnd.emissar.mandate+sd-jwt (JOSE typ: vnd.emissar.mandate+sd-jwt)
JSON Schema mandate-v0.1.schema.json
Runnable proof The demo and example files in Appendix C (output in Appendix A)

Abstract

This document defines the Emissar Mandate, a credential stating what one AI agent may do for one principal (a person or organization) at one verifier, and an Agent2Agent (A2A) extension for presenting it inside a task. A mandate is an SD-JWT (RFC 9901) signed by an issuer the verifier trusts. It names the principal, binds use to the agent’s key by JWK thumbprint (cnf.jkt), names the verifier (aud), lists permitted actions and resources as RFC 9396 authorization details with amount, count and rate limits, expires, and points to a Token Status List entry so the principal can revoke it.

The agent presents it in A2A message metadata with a Key Binding JWT that proves possession of the key, answers the verifier’s single-use challenge, and names the one operation being authorized. The document specifies the data model, issuance obligations, the extension, a numbered verification algorithm, revocation checking, and the A2A task states and errors returned when a mandate is missing, insufficient, expired or revoked. It fills the gap A2A section 7.6.4 leaves open and composes with AP2 payment mandates rather than replacing them.

Status of this document

  • A draft published for comment on 2026-10-05. Not submitted to any standards body. Emissar Front Door implements it for businesses that turn it on.
  • v0.1 will change incompatibly. Breaking changes get a new extension URI (.../v2, A2A section 4.6.3).
  • Comments and questions: the contact form at https://emissar.ai/contact (topic “General”).
  • Third-party facts were checked against primary sources on 2026-09-26 (section 15). A2A citations are to main, where section 7.6.4 was added after the v1.0.1 release.

1. Conventions

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.

Convention Rule
base64url Base64 with the URL-safe alphabet and no padding, as in RFC 7515 section 2
Time NumericDate (RFC 7519) in JWTs; RFC 3339 strings in A2A metadata
JSON Member names MUST be unique. RFC 7519 section 4 allows rejecting duplicates or keeping the last; verifiers SHOULD reject
Money Integer amount in minor units plus ISO 4217 currency, as in AP2’s Amount type. {"amount": 4200, "currency": "CAD"} is CAD 42.00
Examples Illustrative, with reserved .example names, A2A ProtoJSON field names and the JSON-RPC binding. Keys and identifiers come from the demo run in Appendix A

2. Terminology

Term Meaning
Principal The person or organization the action is for. The mandate’s sub
Agent (holder) The agent that holds the mandate and its bound private key, and presents it. The A2A client
Verifier The A2A server agent (or the system behind it) asked to act. It checks the presentation, then performs or refuses the operation. Named in aud
Issuer Signs the mandate after the principal approves it. iss. May be the verifier itself
Trusted surface The non-agentic interface where the principal reviews and approves a mandate (term and rule from AP2)
Mandate The issuer-signed SD-JWT of section 5, with all its Disclosures
Presentation An SD-JWT+KB: the issuer-signed JWT, the Disclosures the agent reveals, and a Key Binding JWT (KB-JWT) signed with the agent’s key
Operation One concrete action: type, action, optional resource, optional amount. The KB-JWT claim op
Authorization detail One RFC 9396-style object in authorization_details: actions on a resource type, optionally one resource, within limits
Challenge A single-use nonce the verifier issues with TASK_STATE_AUTH_REQUIRED, which the next presentation on the task must carry
Status List Token The issuer’s signed, compressed status bit array (IETF Token Status List draft). Each mandate has one index

3. Overview

3.1 The gap this fills

A2A lets an agent pause a task in TASK_STATE_AUTH_REQUIRED when it needs authorization (section 7.6). By default, the credential arrives out of band. An in-band exchange needs prior agreement or an extension (7.6.1, 7.6.3). Section 7.6.3 recommends that in-band credentials be bound so that only one agent can use them, and that sensitive ones be protected from other agents in a chain. Section 7.6.4 then leaves the credential’s scope, representation, validity and revocation undefined. It forbids treating the state change itself as authorization, requires the meaning of any resulting credential to come from the implementation, the credential issuer or an extension, requires implementations to define how an authorized operation is identified and checked before it runs, and forbids assuming that one credential authorizes later messages on the task unless that behavior is defined.

This extension defines all of those points for one class of credential: a principal’s delegation to an agent.

3.2 Goals and non-goals

Goal Mechanism
Say who authorized the action sub and principal, signed by a trusted iss
Only one agent can use it cnf.jkt plus a KB-JWT signed with that key
Only the intended verifier accepts it aud, the KB-JWT aud, and a per-task challenge
Say exactly what is allowed authorization_details; the agent names one op per presentation
Bound the damage limits: per-operation amount, total amount, use count, rate
Expire iat, optional nbf, exp
Let the principal withdraw it status (Token Status List); checked before every operation
Leave evidence jti, sd_hash, and an op signed by the agent key; a result record in the task
Reveal little Selective disclosure of principal details and of individual authorization details

Out of scope for v0.1: agent-to-agent re-delegation, an issuance wire protocol (section 6 sets obligations only), payment execution (AP2, x402), agent reputation (Emissar Verify), signed receipts (Emissar Receipt), and encryption.

3.3 Walk-through

Illustrative: a customer’s assistant agent asks a retailer’s support agent to refund an order.

 Principal       Issuer                 Client agent (holder)          Verifier agent (A2A server)
    |        (trusted surface)                 |                                  |
    |               |                          | 1 SendMessage: "refund ORD-1042" |
    |               |                          |--------------------------------->|
    |               |                          | 2 Task AUTH_REQUIRED             |
    |               |                          |   challenge nonce, needed detail |
    |               |                          |<---------------------------------|
    |               | 3 mandate request        |                                  |
    |               |   (details, aud, JWK)    |                                  |
    |               |<-------------------------|                                  |
    | 4 review, approve                        |                                  |
    |<------------->|                          |                                  |
    |               | 5 SD-JWT, cnf.jkt=agent  |                                  |
    |               |------------------------->|                                  |
    |               |                          | 6 SendMessage(taskId) with       |
    |               |                          |   metadata: SD-JWT+KB            |
    |               |                          |--------------------------------->|
    |               | 7 GET Status List Token (cached up to its ttl)              |
    |               |<------------------------------------------------------------|
    |               |                          | 8 Task COMPLETED, result record  |
    |               |                          |<---------------------------------|

In step 2 the challenge carries a nonce, the verifier’s audience identifier and the detail it needs (refund ORD-1042, up to CAD 200.00). In step 4 the principal sees the verifier, the grant, the limits, the expiry and the agent. In step 6 the agent reveals only the Disclosures this operation needs and signs a KB-JWT over them with the nonce and the exact operation. In step 8 the verifier performs exactly that operation.

With a standing mandate, steps 3 to 5 happen once, and steps 1, 2 and 6 repeat for every operation. Illustrative business-to-business case: a buyer organization’s identity system gives its procurement agent a 90-day mandate to place purchase orders with one supplier, at most CAD 5,000.00 each and 20 per month.

4. Credential format

The format was open at the start of this work: a signed JWT/JWS or a W3C Verifiable Credential. Three candidates were compared.

Criterion JWT with cnf (RFC 7519, RFC 7800) SD-JWT with Key Binding (RFC 9901) W3C VC 2.0 (secured with VC-JOSE-COSE or Data Integrity)
Standard status on 2026-09-26 RFCs since 2015 and 2016 Standards Track RFC, November 2025. The SD-JWT VC profile is still a draft (-19, IESG state “Waiting for AD Go-Ahead”) W3C Recommendations, 15 May 2025
Proof of possession at presentation Not defined. Needs a custom proof token, or DPoP, which is bound to HTTP method and URL and does not fit a credential carried in message metadata Built in: the KB-JWT carries aud, nonce, iat and sd_hash A holder-signed Verifiable Presentation; details depend on the securing mechanism
Selective disclosure None: the verifier sees every claim Per claim and per array element, with salted digests Depends on the securing mechanism (SD-JWT through VC-JOSE-COSE, or specific Data Integrity suites)
Fit with AP2 v0.2 and Verifiable Intent Different structure Same family. AP2 mandates are SD-JWTs with cnf key binding; Verifiable Intent chains SD-JWTs AP2 allows other credential formats in principle, but specifies SD-JWT
Revocation Token Status List status claim works with any JWT Token Status List names SD-JWT as a Referenced Token format (draft section 6.2) Bitstring Status List (W3C Recommendation)
Authorization semantics None; this document defines them None; this document defines them VC 2.0 section 5.9 says the data model is not an appropriate authorization tool without an accompanying authorization framework
Implementation cost Lowest: any JOSE library Low: JOSE plus about 100 lines of hashing and Disclosure handling (the demo script has it) Highest with JSON-LD processing; lower with VC-JOSE-COSE
Carried in A2A metadata as One compact string One compact ~-separated string A JSON object or an enveloped string

Decision for v0.1: SD-JWT (RFC 9901) with a mandatory Key Binding JWT, explicitly typed vnd.emissar.mandate+sd-jwt, not profiled as SD-JWT VC.

Why: the KB-JWT is a standard proof of possession carrying exactly what a presentation needs (audience, freshness, nonce, a hash of the disclosed content), which a plain JWT would force this extension to invent. An SD-JWT with no Disclosures costs no more than a JWT, and selective disclosure is there when a mandate covers several resources or personal data. AP2 and Verifiable Intent use the same format, so verifiers can share code. RFC 9901 is a published RFC, while SD-JWT VC is not yet (section 14, question 3). VC 2.0 adds a JSON-LD model this check does not need and disclaims authorization semantics.

Consequences: revocation uses the Token Status List draft (section 9), ES256 is the only algorithm, and the agent key is referenced by thumbprint (5.4).

5. Data model

5.1 Structure

A mandate, as issued, is the compact SD-JWT serialization (RFC 9901 section 4):

<issuer-signed JWT>~<Disclosure 1>~...~<Disclosure N>~

The issuer-signed JWT is a JWS in compact serialization over the claims in section 5.3. Disclosures follow RFC 9901 section 4.2. The data model in this section describes the Processed SD-JWT Payload: the claims after the presented Disclosures are applied and the digest placeholders removed (RFC 9901 section 7.1). The JSON Schema in section 5.12 validates that processed form.

5.2 Issuer-signed JWT header

Parameter Requirement
alg REQUIRED. ES256 (ECDSA P-256 with SHA-256, RFC 7518 section 3.4). Verifiers MUST reject none, MAC algorithms and anything not on their allowlist (RFC 8725 sections 3.1 and 3.2)
typ REQUIRED. vnd.emissar.mandate+sd-jwt, checked by verifiers (explicit typing, RFC 8725 section 3.11, RFC 9901 section 9.11). Vendor tree, since it is unregistered
kid REQUIRED. Selects the issuer key from the verifier’s trust configuration
jku, jwk, x5u MUST NOT be present; verifiers MUST reject them. Issuer keys come only from the verifier’s trust configuration
crit MUST NOT be present in v0.1

5.3 Claims

“SD” says whether the claim may be selectively disclosable. Anything marked “No” MUST appear in plaintext in the issuer-signed JWT.

Claim Req. SD Content Source
iss REQUIRED No Issuer identifier, an HTTPS URI RFC 7519
sub REQUIRED No Principal identifier, unique within the issuer. SHOULD be pairwise: a different value for each verifier RFC 7519
aud REQUIRED No Verifier identifier (string), or an array of them. A single value is RECOMMENDED RFC 7519
iat REQUIRED No Issue time RFC 7519
nbf OPTIONAL No Start of validity RFC 7519
exp REQUIRED No End of validity RFC 7519
jti REQUIRED No Unique mandate identifier within the issuer, with at least 128 bits of randomness RFC 7519
cnf REQUIRED No Object with jkt: the agent key thumbprint (5.4) RFC 7800, RFC 9449 section 6.1
act OPTIONAL No Object with sub: an identifier for the acting agent, such as its Agent Card URL. Informational only RFC 8693 section 4.1
status REQUIRED No Object with status_list: {idx, uri} (5.9) Token Status List section 6.2
principal OPTIONAL Members only Object with type (person or organization, plaintext) and optional name and account, each of which SHOULD be selectively disclosable This document
authorization_details REQUIRED Elements only Array of one or more authorization details (5.6). The array is plaintext; each element MAY be selectively disclosable RFC 9396 (profiled)
_sd_alg Conditional No sha-256 when any Disclosure exists. No other value is allowed in v0.1 RFC 9901 section 4.1.1

Selective disclosure anywhere else MUST be rejected (step 6). RFC 9901 section 9.7 leaves the list of security-critical claims to each profile; here, everything deciding validity, binding, audience, revocation and the shape of the grant is plaintext. Verifiers MUST ignore other claims they do not understand, but unknown members inside an authorization detail make it unusable (5.6).

5.4 Agent binding

cnf.jkt is the base64url SHA-256 JWK Thumbprint (RFC 7638) of the agent’s public key, as RFC 9449 section 6.1 defines the jkt confirmation method. For a P-256 key, the thumbprint input is the JSON object with the members crv, kty, x and y in that order and without whitespace. The demo checks its implementation against the RFC 9449 example key (Appendix A, self-tests).

RFC 9901 section 4.1.2 suggests the jwk confirmation method but allows others. jkt is used because the thumbprint is a stable agent-key identifier that Ledger records and Emissar Verify can share, because DPoP-capable OAuth resource servers already compare it, and because it keeps the mandate short. The agent therefore supplies its public key in the KB-JWT header as jwk (RFC 7515 section 4.1.3), and the verifier checks the thumbprint before using the key, which meets RFC 9901 section 4.3.2. cnf MUST NOT contain jwk, jwe or jku in v0.1.

5.5 Audience

The verifier’s identifier is the audience it declares in its Agent Card (7.2), an HTTPS URI it controls such as its A2A endpoint’s origin. aud MUST contain it. A mandate with several audiences MUST NOT carry stateful limits (5.7), since no single verifier could count them.

5.6 Authorization details

Each element of authorization_details is a JSON object in the shape of RFC 9396 section 2, restricted to these members:

Member Req. Content
type REQUIRED A string naming the kind of resource and the meaning of the other members. RFC 9396 section 2.1 recommends a collision-resistant URI the definer controls. In v0.1 the verifier defines its types and lists them in its Agent Card
actions REQUIRED Non-empty array of action names defined by the type, such as refund or cancel
identifier OPTIONAL One specific resource, such as an order or subscription number. If absent, the detail covers every resource of the type that belongs to the principal. Issuers SHOULD include it
limits OPTIONAL Object, section 5.7

RFC 9396’s locations, datatypes and privileges are not used: aud names the verifier, and the other two describe data access. A detail with any other member, an unknown limit, or a type the verifier does not support grants nothing (“unsupported”), as an unknown constraint fails in AP2. A detail grants every listed action on its resource within every limit; different limits for different actions need separate details.

Illustrative detail granting refunds on one order:

{
  "type": "https://provider.example/mandate-types/order",
  "actions": ["refund"],
  "identifier": "ORD-1042",
  "limits": {
    "max_amount": { "amount": 20000, "currency": "CAD" },
    "total_amount": { "amount": 20000, "currency": "CAD" },
    "max_uses": 2
  }
}

5.7 Limits

Limit Meaning Needs verifier state
max_amount Largest op.amount for one operation No
total_amount Largest sum of op.amount over all accepted operations under this detail Yes
max_uses Largest number of accepted operations under this detail Yes
rate {count, window}: at most count accepted operations in any sliding window of window seconds Yes

Rules:

  • max_amount and total_amount MUST share one currency. An operation in another currency is not covered; there is no conversion.
  • Only a detail with max_amount or total_amount covers an operation that moves money.
  • Stateful limits are counted per (iss, jti, i), where i is the detail’s zero-based position in the array as issued, counting undisclosed placeholders, which the verifier always sees. They need a single audience (5.5).
  • Limits are the principal’s ceiling. The verifier’s own policy, such as its refund policy, still applies.

5.8 Validity

Issuers SHOULD set exp as short as the task allows, as AP2 advises for open mandates. Verifiers MUST reject mandates whose exp minus iat exceeds a local maximum (the demo uses 30 days). Long standing mandates lean harder on revocation (section 9).

5.9 Status reference

status.status_list.uri identifies the issuer’s Status List Token and status.status_list.idx the mandate’s index in it (Token Status List section 6.2). The claim is REQUIRED whatever the lifetime, so the public promise holds: a principal can revoke, and the verifier checks before acting.

5.10 Selective disclosure

Only the members of principal (other than type) and whole elements of authorization_details may be selectively disclosable (5.3). The agent discloses principal.account when the verifier needs it to find the principal, principal.name only when asked, and only the details that cover the operation. An undisclosed detail grants nothing. Issuers MAY add decoy digests (RFC 9901 section 4.2.5).

5.11 Example

Mandate M1 from the demo run in Appendix A (full file: examples/mandate/mandate.json). The issuer-signed JWT header and payload, as signed:

{ "alg": "ES256", "typ": "vnd.emissar.mandate+sd-jwt", "kid": "mandate-key-2026-09" }
{
  "iss": "https://mandates.assistant.example",
  "sub": "psub-6f1c2a9e",
  "aud": "https://agents.provider.example",
  "iat": 1790468221,
  "exp": 1790471821,
  "jti": "D-ekl0v6NGLB9TPxac_hGQ",
  "cnf": { "jkt": "F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk" },
  "act": { "sub": "https://agents.assistant.example/billing" },
  "status": { "status_list": { "idx": 108115, "uri": "https://mandates.assistant.example/status/3" } },
  "principal": {
    "type": "person",
    "_sd": ["5gzmGTgTyhk1LJ3oeLm7CD7jB_OBb-wMe9QPgcNIZU0", "zlkEreM-9cg8jPSuKqRVxTt_tEY0ilau9QNlR0yugpU"]
  },
  "authorization_details": [
    { "...": "LitkWRLnCpP3fxwQOzNTy0PwBrjZstOLSU3D0Uu3v-Q" },
    { "...": "Cw---7_D7bYl9llorl2zQAQHOuCNx_nw2yRq4am-0vI" }
  ],
  "_sd_alg": "sha-256"
}

The four Disclosures reveal principal.name (“Alex Example”), principal.account (“CUST-88121”), detail 0 (refund ORD-1042, the object in section 5.6) and detail 1 (cancel subscription SUB-3310). In scenario B the agent disclosed only the account and detail 0, so the verifier never saw the principal’s name or the subscription.

5.12 JSON Schema

mandate-v0.1.schema.json (JSON Schema draft 2020-12) validates the processed payload at its root. Its $defs cover the other objects in this document: issuerJwtHeader, kbJwtHeader, kbJwtPayload, operation, presentationEnvelope, challengeEnvelope, resultEnvelope, cardParams and statusListTokenPayload. validate.py (Appendix C) checks every example file against it, runs nine negative tests, and validates the A2A objects against the A2A JSON Schema bundle generated from a2a.proto (Appendix B). Schema validity is necessary but not sufficient: only the algorithm in section 8 decides acceptance.

6. Issuance

6.1 Issuer models

Who may issue is the verifier’s decision, expressed in its trust configuration. Four models fit v0.1:

Model Issuer and trusted surface Why a verifier trusts it Typical use
Verifier-issued The verifier, through its own sign-in and consent page It authenticated the principal itself Consumer accounts; strongest account link
Organization-issued The principal organization’s identity system and approval workflow Agreement made at supplier or partner onboarding Procurement, logistics
Agent-provider-issued The agent’s provider, through a deterministic part of its app Agreement with the provider. AP2 calls this “Trusted Agent Provider” Consumer assistants
Third-party issuer A bank, identity provider or wallet Accreditation or a trust framework Regulated actions

A verifier MUST decide per issuer what that issuer may assert. A link between the principal and an account at the verifier (principal.account, or a sub the verifier maps to an account) is trustworthy only from the verifier itself or from an issuer that verified the link with it. A verifier MUST NOT act on an account named by an issuer it does not trust for account linking.

6.2 Issuer requirements

  1. The issuer MUST obtain the principal’s approval on a non-agentic trusted surface: no processing on it may be delegated to a language model (AP2’s rule for its Trusted Surface).
  2. The surface MUST display, from the structured request rather than agent-written prose: the verifier, each authorization detail (type, actions, resource, limits) in plain words, the validity period, and the agent that will hold the mandate.
  3. The agent MUST NOT be able to use the issuer’s signing key without the principal’s approval.
  4. The issuer SHOULD require the agent to prove possession of the private key before binding it, for example by signing the request with it.
  5. The issuer MUST assign a fresh jti with at least 128 random bits, a status list index (section 9.1), and a new salt of at least 128 random bits for each Disclosure (RFC 9901 section 9.3).
  6. The issuer MUST record which mandates are bound to which cnf.jkt, so it can revoke all of them if an agent key is compromised.
  7. The issuer MUST return the mandate with all Disclosures to the agent over an authenticated, encrypted channel, and SHOULD NOT keep the Disclosures longer than it needs them.
  8. The issuer MUST give the principal a way to see and revoke their active mandates (section 9.2).

6.3 Issuance steps

v0.1 defines no issuance wire protocol (section 14, question 5). Whatever protocol is used MUST carry these steps: (1) the agent requests authorization_details, an audience and a lifetime, and sends its public key as a JWK; (2) the issuer applies its own policy and may narrow the request; (3) the principal authenticates and approves, narrows or declines on the trusted surface; (4) the issuer builds the section 5.3 claims with cnf.jkt set to the RFC 7638 thumbprint of the agent’s key, creates the Disclosures and signs; (5) the issuer returns the SD-JWT with all Disclosures.

6.4 Keys

Issuers SHOULD publish their public keys as a JWK Set at an HTTPS URL, which verifiers pin in their trust configuration. The issuer signs its Status List Tokens with a key from the same set (the single-entity case of Token Status List section 11.3). Rotation uses a new kid, and retired keys stay published until every mandate they signed has expired.

7. Presentation inside A2A

7.1 Extension identity

The URI is https://emissar.ai/ext/mandate/v1. It is a profile extension in the A2A extensions guide’s terms: it adds typed data under the URI in the metadata of messages, status messages and artifacts, and adds no methods, fields or enum values. New outcomes use existing task states. It works over all three standard bindings and depends on no other extension.

7.2 Agent Card declaration

A verifier that accepts mandates MUST declare the extension in capabilities.extensions:

params member Req. Content
audience REQUIRED The verifier identifier that mandates and KB-JWTs must name (5.5)
algorithms REQUIRED Accepted signing algorithms. ["ES256"] in v0.1
types OPTIONAL The authorization_details types the verifier supports
acceptedIssuers OPTIONAL Issuer identifiers the verifier trusts. A verifier MAY leave this out and name issuers per challenge instead

required SHOULD be false: mandates usually apply to some skills only, and required: true makes every request without the extension fail with ExtensionSupportRequiredError (A2A section 3.3.4). The A2A extensions guide likewise reserves required for extensions fundamental to the agent.

Illustrative declaration (from examples/mandate/agent-card.json, which validates against the A2A AgentCard schema):

{
  "uri": "https://emissar.ai/ext/mandate/v1",
  "description": "Refunds and membership cancellations need an Emissar Mandate from the account holder.",
  "required": false,
  "params": {
    "audience": "https://agents.provider.example",
    "algorithms": ["ES256"],
    "types": [
      "https://provider.example/mandate-types/order",
      "https://provider.example/mandate-types/subscription"
    ],
    "acceptedIssuers": ["https://mandates.assistant.example"]
  }
}

7.3 Activation

A client that presents a mandate MUST list the URI in the A2A-Extensions service parameter of that request: the HTTP header for JSON-RPC and HTTP+JSON, the a2a-extensions metadata key for gRPC. It SHOULD also list the URI in Message.extensions. A verifier MUST process mandate metadata only when the extension is activated for the request. When it is not, the verifier MUST ignore any metadata under the URI and treat the request as carrying no mandate. A verifier that activates the extension SHOULD echo the URI in the response’s A2A-Extensions header.

7.4 The challenge

When an operation needs a mandate and none was presented, or a presentation failed, the verifier moves the task to TASK_STATE_AUTH_REQUIRED (section 10) and puts this object in status.message.metadata under the URI:

Member Req. Content
error REQUIRED An error code from section 10.2 (mandate_required when nothing was presented)
errorDescription OPTIONAL Short human-readable text. It MUST NOT reveal information that helps an attacker (section 12.9)
challenge REQUIRED with AUTH_REQUIRED {nonce, audience, expiresAt}: a fresh nonce with at least 128 random bits, single use and bound to this task; the verifier’s audience identifier; and the nonce’s expiry as an RFC 3339 time (RECOMMENDED: 10 minutes ahead)
authorizationDetails OPTIONAL The details the operation needs, in the section 5.6 shape, so the agent can request a matching mandate
acceptedIssuers OPTIONAL Issuers the verifier would accept for this operation

The status message MUST also contain a text part explaining what is needed, for the principal to read (A2A section 7.6.1 asks for one). A new challenge MUST invalidate any earlier challenge for the task. The challenge is input from another party: authorizationDetails is a request for the principal to decide on the issuer’s trusted surface, never something the client approves on the principal’s behalf (section 12.6).

7.5 Carrying the presentation

The client continues the task by sending a message with the task’s taskId and this object in Message.metadata under the URI:

{ "presentation": "<issuer-signed JWT>~<selected Disclosures>~<KB-JWT>" }

The object MUST contain exactly the presentation member, a compact SD-JWT+KB of at most 16,384 characters. One message carries at most one presentation.

The agent builds the KB-JWT as RFC 9901 section 4.3 defines, with these profile rules:

Part Member Content
Header typ kb+jwt
Header alg ES256
Header jwk The agent’s public key. Its RFC 7638 thumbprint MUST equal cnf.jkt. It MUST NOT contain private key members
Payload iat Current time
Payload aud The verifier’s audience identifier: one string, equal to challenge.audience
Payload nonce challenge.nonce from the task’s latest AUTH_REQUIRED status
Payload sd_hash base64url SHA-256 over the presented <issuer JWT>~<Disclosures>~ string (RFC 9901 section 4.3.1)
Payload op The one operation this presentation authorizes (below)

op is an extra KB-JWT claim, which RFC 9901 says to avoid without a compelling reason. The reason: a mandate grants a range, so the agent’s key must commit to the concrete operation. Otherwise the verifier would take it from message text, which prompt injection can shape, or from unsigned metadata. The signed op is also evidence for the Ledger record. AP2 has the agent sign a closed mandate per transaction for the same reason.

op member Req. Content
type REQUIRED An authorization detail type
action REQUIRED One action
identifier OPTIONAL The resource acted on. REQUIRED when the covering detail has an identifier
amount OPTIONAL Money moved by the operation (section 1). REQUIRED when the operation moves money

The agent SHOULD disclose only the Disclosures the operation needs: the covering authorization detail, and principal members the verifier asked for. It MUST NOT send a Disclosure twice or one that was not issued (RFC 9901 section 4).

7.6 Example

Scenario B from Appendix A, presented on the task that scenario A put in AUTH_REQUIRED. The presentation string is shortened here; the full request is examples/mandate/send-message-request.json.

POST /a2a/v1 HTTP/1.1
Host: agents.provider.example
Content-Type: application/json
A2A-Version: 1.0
A2A-Extensions: https://emissar.ai/ext/mandate/v1

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "accc4087-21a2-4a97-a443-e3c93d6b9300",
      "role": "ROLE_USER",
      "parts": [{ "text": "Refund 42.00 CAD on ORD-1042. Mandate attached." }],
      "taskId": "ba8e2999-d7b1-4cf5-9391-fb4389c48851",
      "extensions": ["https://emissar.ai/ext/mandate/v1"],
      "metadata": {
        "https://emissar.ai/ext/mandate/v1": {
          "presentation": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZuZC5lbWlzc2FyLm1hbmRhdGUrc2Qt..."
        }
      }
    },
    "configuration": { "historyLength": 0 }
  }
}

The KB-JWT inside that presentation (examples/mandate/presentation.json):

{ "typ": "kb+jwt", "alg": "ES256",
  "jwk": { "kty": "EC", "crv": "P-256",
           "x": "tdSAJw2C_T7Wt_hYlGlhUYoYz3czD2O3H9UymXC8nK8",
           "y": "Bznu_9Twp-3RzdFVjR00gxyopAZwx6KT48kAR4dxe-0" } }
{
  "iat": 1790468221,
  "aud": "https://agents.provider.example",
  "nonce": "-Wzblvf9Zom1-tuyljKiOg",
  "sd_hash": "NfZhRWM2VtPe6phbp6-tveuSUpZyMVTgwxI-JSsQOlY",
  "op": {
    "type": "https://provider.example/mandate-types/order",
    "action": "refund",
    "identifier": "ORD-1042",
    "amount": { "amount": 4200, "currency": "CAD" }
  }
}

7.7 Result record

After an accepted presentation, the verifier SHOULD put this object under the URI in the metadata of the artifact that records the outcome, or of the final status message when there is no artifact:

Member Content
result accepted
iss, jti The mandate used
sdHash The KB-JWT sd_hash, identifying the exact presentation
jkt OPTIONAL. The agent key thumbprint

The record is protected only by the transport; signed receipts belong to Emissar Receipt v0.1. Example: examples/mandate/send-message-response-completed.json.

8. Verification algorithm

The verifier runs these steps in order for each message carrying a presentation. The first failing step sets the error code (section 10.2). Steps 2 to 16 match the numbered steps in mandate-demo.mjs (trace in Appendix A). Inputs: the request; the verifier’s audience identifier; its trust configuration (issuers, their keys, permitted status URIs, accepted types); clock skew s (RECOMMENDED 60 seconds); a KB-JWT age limit (RECOMMENDED 300 seconds); a maximum mandate lifetime; the task’s live challenge; the usage store.

  1. Locate. If A2A-Extensions does not list the URI, ignore mandate metadata. If Message.metadata[URI] is absent and the operation needs a mandate, return mandate_required. If it is not an object whose only member is a string presentation, return Invalid params (10.3). Resolve the task as A2A requires (unknown: TaskNotFoundError; terminal: UnsupportedOperationError).
  2. Split. Reject presentations over 16,384 characters. Split on ~. The last component is the KB-JWT and MUST be non-empty. The first is the issuer-signed JWT. The ones between are Disclosures and MUST be non-empty. Failure: mandate_invalid.
  3. Check the issuer JWT header. It MUST be a compact JWS. typ MUST be vnd.emissar.mandate+sd-jwt; alg MUST be on the allowlist; kid MUST be a string; jku, jwk, x5u and crit MUST be absent. Failure: mandate_invalid.
  4. Resolve the issuer key. Read iss from the not-yet-verified payload. Look it up in the trust configuration and select the key by kid from that issuer’s keys only. Unknown issuer or key: mandate_invalid.
  5. Verify the issuer signature (RFC 7515 section 5.2). ES256 signatures are the 64-byte R||S form. Failure: mandate_invalid.
  6. Apply Disclosures as RFC 9901 section 7.1 describes, with this profile’s limits. _sd_alg, if present, MUST be sha-256. Each Disclosure MUST decode to a JSON array (three elements for an object member, two for an array element) whose first element is a string salt. Compute each digest over the ASCII Disclosure string. Each digest MUST be referenced exactly once, and only in principal._sd or as an {"...": digest} element of authorization_details. A disclosed member name MUST NOT be _sd or ... and MUST NOT already exist. Remove undisclosed placeholders, _sd and _sd_alg. Remember each remaining detail’s issued position. Failure: mandate_invalid.
  7. Check claims. iss, sub, aud, iat, exp, jti (at least 16 characters), cnf.jkt, status.status_list.idx and status.status_list.uri MUST be present with the right types, and the issued authorization_details array MUST be non-empty. exp MUST be later than iat, and exp minus iat MUST NOT exceed the maximum lifetime. Failure: mandate_invalid.
  8. Check the validity window. With skew s: iat more than s in the future gives mandate_invalid; now earlier than nbf - s gives mandate_not_yet_valid; now at or after exp + s gives mandate_expired.
  9. Check the audience. aud MUST equal, or be an array containing, the verifier’s audience identifier. Failure: mandate_invalid.
  10. Check key binding. The KB-JWT MUST be a compact JWS with header typ kb+jwt, an allowlisted alg, and a jwk that is a P-256 public key without private members. Compute its RFC 7638 thumbprint. It MUST equal cnf.jkt. Verify the KB-JWT signature with that key. Failure: proof_invalid.
  11. Check KB-JWT claims. sd_hash MUST equal the base64url SHA-256 of the presented <issuer JWT>~<Disclosures>~ string. aud MUST be a string equal to the verifier’s audience identifier. iat MUST be no more than s in the future and no older than the age limit. nonce MUST be a string and op an object. Failure: proof_invalid.
  12. Consume the challenge. nonce MUST match a challenge this verifier issued for this task that has not expired. Delete it whatever the later steps decide, so it can never be used twice. Failure: proof_invalid.
  13. Check status (section 9.3). Fetch or reuse the Status List Token named by status.status_list.uri, fetching only URIs the trust configuration permits for this issuer (any other URI counts as unobtainable). Verify it, decompress it, and read the value at idx. Out-of-bounds index: mandate_invalid. 0x01 (INVALID): mandate_revoked. 0x02 (SUSPENDED): mandate_suspended. Any other non-zero value: mandate_invalid. Token unobtainable, unverifiable or expired: status_unavailable. Only 0x00 (VALID) continues.
  14. Match the operation. op MUST contain only type, action, identifier and amount, with valid types (malformed: proof_invalid). A disclosed detail covers op when it is well formed and supported (5.6), its type equals op.type, its actions contain op.action, its identifier (if any) equals op.identifier, and, when op.amount is present, it has an amount limit in the same currency. The verifier MUST also confirm, from its own records, that the resource belongs to the principal. No covering detail: unsupported_detail if a detail of op.type was unsupported, otherwise insufficient_scope.
  15. Check limits. For covering details in issued order, accept the first one where op.amount does not exceed max_amount, the accepted total plus op.amount does not exceed total_amount, accepted uses plus one do not exceed max_uses, and accepted uses within the last rate.window seconds plus one do not exceed rate.count. None passes: limit_exceeded.
  16. Commit. Record the use (count, amount, time) under (iss, jti, position) atomically with the decision, so concurrent presentations cannot overspend. The verifier MAY release the reservation if the operation then fails.
  17. Act and record. Perform exactly the operation in op, nothing broader. If the verifier derives the operation independently, for example from the conversation, it MUST confirm it equals op in type, action, identifier and amount. Add the result record (7.7). Log iss, jti, sub, jkt, sd_hash, op, the task id and the outcome, but not the presentation or Disclosures unless required and protected (A2A section 13.4).

Steps 2 to 16 MUST be decided by deterministic code. A language model in the verifier agent may run the conversation but MUST NOT decide whether a mandate authorizes an operation.

9. Revocation and status checking

9.1 Issuer duties

  • The issuer is the Status Issuer for its mandates in v0.1, and signs Status List Tokens (typ statuslist+jwt) with a key from its published set.
  • Each list SHOULD hold at least 131,072 entries (Bitstring Status List’s default, chosen for herd privacy), with indices assigned at random.
  • bits is 1 when only revocation is needed, and 2 when suspension is also used.
  • Tokens MUST include sub equal to the list URI, iat, exp and ttl. ttl SHOULD be 300 seconds or less for lists covering mandates that move money.
  • The list MUST be served over HTTPS at its URI in response to GET with Accept: application/statuslist+jwt (Token Status List section 8.1).

9.2 Principal actions

Action Effect Status value
Revoke Permanent. The mandate is dead 0x01 INVALID
Suspend Temporary pause, for example while a dispute is open 0x02 SUSPENDED
Resume Only from suspension back to 0x00 VALID
Revoke all for one agent Every mandate with that cnf.jkt (6.2, item 6) 0x01 for each

The issuer MUST republish the Status List Token promptly after any change, and SHOULD tell the principal when it takes effect (9.4).

9.3 Verifier duties

  • Check status on every presentation (step 13), after the checks on the mandate itself, as Token Status List section 8.3 requires.
  • Validate the Status List Token: typ, a signature by a key trusted for the mandate’s issuer, sub equal to the URI, exp not passed, and bits one of 1, 2, 4 or 8.
  • Cache a token no longer than the shorter of its ttl and local policy. For operations above a local amount threshold, verifiers SHOULD refetch regardless of the cache.
  • Fail closed: if the status cannot be established, do not act (status_unavailable).
  • Fetch only status URIs the trust configuration allows for the issuer, such as its own origin. Trust to sign mandates is not trust to direct the verifier’s HTTP requests.

9.4 Revocation latency

Worst case from revocation to refusal: the issuer’s publishing delay, plus the verifier’s cache age (at most ttl), plus any CDN caching. With ttl 300 seconds, a revoked mandate can still be accepted for about five minutes. Tighter bounds need a shorter ttl and refetching for high-value operations. The demo refetches every time, so scenario H refuses at once.

10. Interaction with TASK_STATE_AUTH_REQUIRED

10.1 Rules

  1. An operation that needs a mandate MUST run as a Task (A2A section 7.6.1).
  2. Unless rule 3 applies, when a mandate is missing or a presentation fails, the verifier MUST move the task to TASK_STATE_AUTH_REQUIRED with the section 7.4 challenge and a text part. It MUST NOT answer with an A2A error (such as a JSON-RPC error), which would leave the client no task to continue.
  3. The verifier MAY instead end the task in TASK_STATE_REJECTED when policy says stop, for example after three failed presentations, a proof_invalid suggesting theft, or a barred issuer or principal. The status message then carries error and errorDescription but no challenge.
  4. A blocking SendMessage returns at AUTH_REQUIRED (A2A section 3.2.2), so the client gets the challenge in the response. The client answers with a presentation on the same taskId, or cancels.
  5. After acceptance the task moves to TASK_STATE_WORKING and then a terminal state. If the operation then fails for business reasons, the task ends in TASK_STATE_FAILED and the verifier MAY release the usage reserved in step 16.

10.2 Outcomes

Condition Step Task state error What the client can do
No presentation for an operation that needs one 1 AUTH_REQUIRED mandate_required Get a mandate
Malformed, wrong typ or alg, untrusted issuer, bad signature or Disclosures, missing claims, lifetime too long, wrong audience, status index out of range 2 to 9, 13 AUTH_REQUIRED (or REJECTED) mandate_invalid Get one from an accepted issuer
Not yet valid 8 AUTH_REQUIRED mandate_not_yet_valid Wait
Expired 8 AUTH_REQUIRED mandate_expired Get a new mandate
Wrong agent key, bad KB-JWT, sd_hash or aud mismatch, stale iat, unknown or reused nonce, malformed op 10 to 12, 14 AUTH_REQUIRED (or REJECTED) proof_invalid Re-present with the bound key and new nonce
Revoked 13 AUTH_REQUIRED mandate_revoked Ask the principal
Suspended 13 AUTH_REQUIRED mandate_suspended Ask the principal
Status unavailable 13 AUTH_REQUIRED status_unavailable Retry later
No disclosed detail covers the operation 14 AUTH_REQUIRED insufficient_scope Disclose the right detail, or get a broader mandate
The matching detail has an unsupported type or member 14 AUTH_REQUIRED unsupported_detail Use the verifier’s declared types
Over a limit 15 AUTH_REQUIRED limit_exceeded New mandate, or a person
Accepted 16, 17 WORKING, then terminal result record accepted None

Every AUTH_REQUIRED response carries a new challenge that replaces the old one. insufficient_scope is RFC 6750’s name; section 11.1 maps the codes to AP2’s.

10.3 Protocol-level errors

These are A2A errors, not mandate outcomes. They follow A2A sections 3.3.2, 3.3.4 and 5.4, with google.rpc.ErrorInfo reasons in the A2A style (upper snake case, domain a2a-protocol.org for A2A-specific errors).

Condition JSON-RPC gRPC HTTP+JSON
The Agent Card marks the extension required: true and the request does not activate it -32008 ExtensionSupportRequiredError FAILED_PRECONDITION 400
Message.metadata[URI] is not an object whose only member is a string presentation -32602 Invalid params, with a google.rpc.BadRequest field violation on message.metadata["https://emissar.ai/ext/mandate/v1"] INVALID_ARGUMENT 400
taskId unknown or not accessible -32001 TaskNotFoundError NOT_FOUND 404
taskId names a terminal task -32004 UnsupportedOperationError FAILED_PRECONDITION 400

Scenario C1 in Appendix A shows the last row: replaying an accepted request on its finished task is refused by A2A itself, before any mandate check.

10.4 Later messages on the same task

Per A2A section 7.6.4, this extension defines the scope of what a presentation authorizes: exactly one operation, the op in its KB-JWT, performed once. A presentation authorizes nothing else on the task, including later messages. A further operation on the same task needs a new challenge (the verifier moves the task back to AUTH_REQUIRED) and a new KB-JWT. The same mandate may be presented again within its limits. Credentials a verifier receives out of band, such as OAuth tokens, are outside this extension and keep whatever meaning their own issuer gives them.

10.5 Chains of agents

A2A section 7.6.2 lets a client that is itself an agent pass an AUTH_REQUIRED request upstream. If agent B, working for agent A, meets a verifier that wants a mandate, B moves its own task with A to AUTH_REQUIRED, and the mandate must be issued to B’s key: a mandate bound to A’s key is useless to B. Re-delegation is out of scope (section 14, question 6). Intermediaries that relay a presentation can read its disclosed content but cannot use it, since they lack the agent’s key and the nonce and audience tie it to one verifier’s task. That is the property A2A section 7.6.3 asks in-band credentials to have.

11.1 AP2: compose, do not compete

AP2 v0.2 (released 2026-04-28) defines Checkout and Payment Mandates as SD-JWT credentials, in closed form (final values approved by the user) and open form (constraints plus the agent’s key in cnf, from which the agent signs closed mandates). Its general Agent Authorization model says the approach could apply beyond payments, and that new mandate and constraint types may be defined. Emissar Mandate is such an application for non-payment actions, built from the same parts.

Aspect AP2 v0.2 Emissar Mandate v0.1
Domain Purchases: checkout and payment Any action a verifier defines: refunds, cancellations, bookings, orders, disputes
Format SD-JWT (SD-JWT VC claims such as vct) SD-JWT (RFC 9901), own typ, no vct
Agent binding cnf.jwk in open mandates cnf.jkt, key supplied in the KB-JWT header
Concrete action A closed mandate, signed by the user or by the agent The op claim in the KB-JWT
Constraints Typed constraints; unknown ones fail Authorization details plus limits; unknown members fail
Revocation None defined; reuse limited by receipts and short expiry Token Status List, checked before every operation
Receipts Verifier-signed Mandate Receipts Unsigned result record now; signed receipts in Emissar Receipt
Agent-to-agent delegation Out of scope Out of scope

Composition rules:

  1. Separate jobs. In a purchase, AP2 mandates authorize the checkout and payment; an Emissar Mandate authorizes the business action around it, such as changing a booking. A verifier MUST NOT treat one kind as the other.
  2. Side by side. Both extensions can be active in one request, each with its own metadata entry. Neither credential embeds the other.
  3. One agent key. If the agent uses one key for both, the verifier can check that the thumbprint of the AP2 cnf.jwk equals the mandate’s cnf.jkt.
  4. Stricter limit wins. Where both constrain an amount, the operation must satisfy both. Emissar Settle is planned to enforce this.
  5. Refunds. The AP2 v0.2 documents reviewed define no refund mandate. A refund requested by a customer’s agent is an Emissar Mandate operation; executing it is outside both specifications.
Emissar error Closest AP2 receipt error
mandate_invalid, proof_invalid, mandate_expired, mandate_not_yet_valid, mandate_revoked, mandate_suspended invalid_credential
unsupported_detail unresolved_constraint
insufficient_scope, limit_exceeded invalid_mandate
(verifier does not support the extension) mandates_not_supported

11.2 Verifiable Intent

Mastercard’s Verifiable Intent (v0.1.0, changelog dated 2026-02-19, Apache-2.0) layers SD-JWTs: a credential provider binds the user’s key, the user signs mandates, and in autonomous mode the agent signs final values, each layer bound to the one before by cnf and sd_hash. It covers checkout and payment with AP2’s mandate types and defers revocation to a future version. On 2026-04-28 the FIDO Alliance announced that Google contributed AP2 and Mastercard contributed Verifiable Intent to its Payments Technical Working Group, and formed an Agentic Authentication Technical Working Group. Emissar Mandate uses the same building blocks for non-payment actions and adds revocation (section 14, question 12).

11.3 OAuth

The mandate reuses OAuth data shapes so that a verifier’s existing policy code applies:

OAuth element Use here
RFC 9396 authorization_details The scope format (5.6). RFC 9396 section 9.1 lets JWT access tokens carry the same claim, so one policy engine can check both
RFC 9449 cnf.jkt The agent binding (5.4)
RFC 8693 act Names the acting agent (informational)
RFC 7800 cnf The confirmation claim
Token Status List Revocation without introspection calls

When the verifier runs an authorization server and the principal has an account there, a short-lived DPoP-bound access token with authorization_details, obtained out of band, is the established path, and A2A’s default (sections 7.3, 7.6.1). Emissar’s delegated-authority guide walks through it. A mandate adds in-band carriage (no redirect mid-task), an issuer that need not be the verifier, a per-operation signature by the agent key, and revocation by status list instead of introspection. The verifier’s authorization server can itself be the issuer (6.1). Exchanging an accepted mandate for an internal token with RFC 8693 is possible but not defined here.

11.4 The OID4VP in-task authorization extension

This experimental a2aproject extension puts an OpenID for Verifiable Presentations request in an AUTH_REQUIRED status message, and the principal’s wallet answers the verifier out of band. It proves facts about the principal; a mandate carries the principal’s delegation to an agent, in band. Both can sit on one Agent Card, and an SD-JWT VC profile (question 3) would let an OID4VP request ask a wallet for a mandate.

11.5 Other Emissar modules

Verify answers whether to trust the agent and its provider; a mandate answers whether the principal authorized the action, and a verifier needs both. Settle is planned to check payment amounts against mandate limits. Ledger and Receipt record iss, jti, sd_hash, jkt, op and the outcome. Front Door’s per-tenant policy says which skills require a mandate.

12. Security considerations

AP2’s threat model assumes prompt injection cannot be fully prevented and treats every model and agent as a potential attacker. This document makes the same assumption: the principal’s agent, the verifier’s agent and any intermediary may be manipulated.

12.1 Replay

  • Each presentation needs a verifier-issued, single-use, task-bound nonce (step 12). A copied presentation fails in any other task (scenario C2).
  • The KB-JWT aud, iat window and sd_hash stop reuse at another verifier, after a delay, or with different Disclosures.
  • A2A refuses messages to finished tasks (scenario C1).
  • Stateful limits bound what a replay could achieve even if a nonce check were missed.

12.2 Confused deputy

  • Wrong verifier. A mandate for verifier X cannot be accepted by Y: aud and the KB-JWT aud must both name Y.
  • Wrong principal’s resource. Naming ORD-1042 does not prove it belongs to the principal. The verifier MUST check ownership in its own records (step 14) and accept account links only from issuers trusted for them (6.1).
  • The verifier’s own agent. A model-driven agent can be talked into doing more. Step 17 limits it to the signed op, decided by deterministic code (section 8).

12.3 Scope escalation

  • Unknown types, members and limits grant nothing (5.6). Undisclosed details grant nothing (5.10).
  • An operation that moves money needs a detail with an amount limit in the same currency (5.7).
  • A detail without identifier covers every resource of its type the principal owns. Issuers SHOULD avoid that for consequential actions, and surfaces MUST say “any” plainly.
  • The agent cannot widen a mandate: it only chooses which signed parts to reveal.

12.4 Key compromise

Key Effect Response
Agent key The attacker can present every mandate bound to it until expiry Issuer revokes all mandates with that cnf.jkt (9.2). Short lifetimes, hardware-backed keys, and per-verifier keys limit the damage
Issuer key The attacker can mint mandates for any principal the issuer serves, and sign status lists Verifiers remove the key from their trust configuration. Issuers keep keys in a hardware security module and rotate by kid
Stolen mandate without the agent key Useless: step 10 fails (scenario D) None needed; the issuer may revoke as a precaution

12.5 Clock skew

Clock checks use a skew of 60 seconds (RECOMMENDED) on iat, nbf and exp, and on the KB-JWT iat. Challenge expiry is measured on the verifier’s own clock, so skew does not affect it. Parties SHOULD synchronize clocks. Verifiers SHOULD NOT raise the skew to accommodate a peer’s broken clock.

12.6 Prompt-injection-driven misuse

  • At the principal’s agent. Injected content can lead the agent to request operations the principal did not intend. Mandate limits cap the damage. The trusted surface shows the principal the structured request, not the agent’s summary of it, so a manipulated agent cannot word its way to approval.
  • Malicious challenges. A hostile verifier can ask, in authorizationDetails, for far more than the task needs. The client MUST NOT forward such a request for approval without the trusted surface rendering it in full, and SHOULD warn the principal when requested details go beyond what the conversation needs.
  • At the verifier. Authorization comes only from op, checked by steps 14 and 15. Text parts of the message cannot add to it.
  • Explanations. errorDescription and status text are untrusted input to the client. They MUST NOT steer the client’s tools.

12.7 Algorithm and type confusion

The issuer JWT, the KB-JWT and the Status List Token have distinct typ values, each checked (steps 3, 10, 13). Only ES256 is accepted and none never is. Issuer keys never come from token headers. The one embedded key, in the KB-JWT header, is used only after its thumbprint matches the issuer-signed cnf.jkt.

12.8 Denial of service

Presentations are capped at 16,384 characters, and verifiers SHOULD rate-limit presentations per task and per client (A2A section 13.4). The status fetch, the only network call, comes after the local checks, and only to URIs permitted for the issuer (9.3), which also keeps the verifier from being used for server-side request forgery.

12.9 Error detail

Detailed failure reasons help attackers probe. Verifiers MAY report every failure in steps 2 to 9 as mandate_invalid and in steps 10 to 12 as proof_invalid, with no detail, and keep the precise reason in their logs. The demo does this: the client gets a generic errorDescription, and only the report prints the internal reason.

12.10 Trusted surface

Everything rests on the surface showing the principal the truth. A surface an agent can drive, or one that shows agent-written text as the grant, defeats every check in section 8. Hence the non-agentic rule in section 6.2, taken from AP2.

13. Privacy considerations

Topic Design
What the verifier learns The plaintext claims, the disclosed details and principal members; not undisclosed ones, and not other mandates
Minimal disclosure Principal members and individual details are selectively disclosable (5.10). The agent discloses only what the operation needs (7.5)
Correlation across verifiers Mandates are audience-bound, so a verifier never sees another verifier’s mandate. sub SHOULD be pairwise. The agent key thumbprint is a correlation handle, so agents SHOULD use a separate key for each verifier
Issuer tracking use Verifiers fetch whole lists; large lists with random indices give herd privacy, and caching lowers fetch frequency. The issuer still sees which verifiers fetch (Token Status List section 12.1)
Salts 128-bit random salts stop verifiers from guessing hidden values (RFC 9901 section 9.3)
Intermediaries A presentation passing through other agents exposes its disclosed content to them. v0.1 does not encrypt presentations (question 9). Agents SHOULD send presentations directly to the verifier
Retention Verifiers SHOULD keep only the step 17 log fields, only as long as disputes and law require. If Emissar runs an issuer, verifier or status service for customers, the trust center and privacy policy change first and retention is enforced in code (repository rule 4)

14. Open questions

Items 1 and 2 were settled when this draft was published. Items 3 to 13 are open for v0.2; comments are welcome.

# Question Default until decided
1 Publish this draft for comment? Settled: published on 2026-10-05
2 The A2A extensions guide says an extension’s specification should be hosted at its URI Settled: https://emissar.ai/ext/mandate/v1 redirects to this document
3 Profile the mandate as an SD-JWT VC (dc+sd-jwt, a vct value) once that draft is an RFC? That would let OID4VP wallets and AP2 toolchains carry mandates Own typ, no vct
4 Accept cnf.jwk as well as cnf.jkt, for tools built for AP2 and Verifiable Intent? jkt only
5 Standardize issuance: an OAuth authorization request with authorization_details and a DPoP-proved key whose response is a mandate, or OpenID for Verifiable Credential Issuance? Obligations only (section 6)
6 Re-delegation from one agent to another: the Delegate SD-JWT individual draft that AP2 cites, or RFC 8693 token exchange? Out of scope
7 Allow one-round-trip presentations without a challenge, using messageId as the nonce plus a replay cache? Saves a round trip for standing mandates Challenge required
8 Publish shared authorization detail types for the procurement and logistics wedge (quote request, purchase order, delivery exception) so suppliers need not each invent them? Types are verifier-defined
9 Encrypt presentations (JWE) for multi-hop chains, as A2A section 7.6.3 recommends for sensitive credentials? Not encrypted; send directly
10 Should verifiers return a signed receipt for every accepted presentation, as AP2 requires, or leave that to Emissar Receipt? Unsigned result record
11 Who hosts status lists for small issuers? If Emissar does, it becomes a data processor with privacy-policy and retention duties Issuer hosts
12 Track and align with the FIDO Alliance agentic work (AP2, Verifiable Intent, Agentic Authentication Technical Working Group), which may extend beyond payments Monitor
13 The media type (vnd.emissar...) and the URI embed the name Emissar. A rename would change both identifiers Keep

15. References

All URLs were accessed on 2026-09-26.

15.1 Normative

Reference Title URL
[A2A] A2A Protocol Specification, main branch (sections 3.2, 3.3, 3.4, 4.6, 5.4, 7.6 including 7.6.4, 8.4, 9, 13.4, 14.2.2) https://github.com/a2aproject/A2A/blob/main/docs/specification.md
[A2A-PROTO] A2A protocol definition (a2a.proto) https://github.com/a2aproject/A2A/blob/main/specification/a2a.proto
[RFC2119] Key words for use in RFCs to Indicate Requirement Levels https://www.rfc-editor.org/rfc/rfc2119
[RFC8174] Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words https://www.rfc-editor.org/rfc/rfc8174
[RFC3339] Date and Time on the Internet: Timestamps https://www.rfc-editor.org/rfc/rfc3339
[RFC7515] JSON Web Signature (JWS) https://www.rfc-editor.org/rfc/rfc7515
[RFC7517] JSON Web Key (JWK) https://www.rfc-editor.org/rfc/rfc7517
[RFC7518] JSON Web Algorithms (JWA) https://www.rfc-editor.org/rfc/rfc7518
[RFC7519] JSON Web Token (JWT) https://www.rfc-editor.org/rfc/rfc7519
[RFC7638] JSON Web Key (JWK) Thumbprint https://www.rfc-editor.org/rfc/rfc7638
[RFC7800] Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs) https://www.rfc-editor.org/rfc/rfc7800
[RFC8725] JSON Web Token Best Current Practices https://www.rfc-editor.org/rfc/rfc8725
[RFC9396] OAuth 2.0 Rich Authorization Requests https://www.rfc-editor.org/rfc/rfc9396
[RFC9449] OAuth 2.0 Demonstrating Proof of Possession (DPoP), section 6.1 (jkt) https://www.rfc-editor.org/rfc/rfc9449
[RFC9901] Selective Disclosure for JSON Web Tokens (SD-JWT), Standards Track, November 2025 https://www.rfc-editor.org/rfc/rfc9901
[TSL] Token Status List, draft-ietf-oauth-status-list-21 (2026-06-21). IESG state: RFC Editor queue https://datatracker.ietf.org/doc/draft-ietf-oauth-status-list/
[ISO4217] ISO 4217 Currency codes https://www.iso.org/iso-4217-currency-codes.html

15.2 Informative

Reference Title URL
[A2A-EXT] Extensions in A2A https://github.com/a2aproject/A2A/blob/main/docs/topics/extensions.md
[A2A-JSON] A2A JSON Schema bundle generated from a2a.proto (non-normative build artifact) https://a2a-protocol.org/latest/spec/a2a.json
[A2A-OID4VP] OID4VP In-Task Authorization Extension, v1 draft (experimental) https://github.com/a2aproject/experimental-ext-oid4vp-auth/blob/main/v1/spec.md
[AP2] Agent Payments Protocol specification v0.2 https://github.com/google-agentic-commerce/AP2/blob/main/docs/ap2/specification.md
[AP2-AUTH] AP2 Agent Authorization https://github.com/google-agentic-commerce/AP2/blob/main/docs/ap2/agent_authorization.md
[AP2-PM] AP2 Payment Mandate https://github.com/google-agentic-commerce/AP2/blob/main/docs/ap2/payment_mandate.md
[AP2-SEC] AP2 Security and Privacy Considerations https://github.com/google-agentic-commerce/AP2/blob/main/docs/ap2/security_and_privacy_considerations.md
[AP2-LOG] AP2 changelog (0.2.0, 2026-04-28) https://github.com/google-agentic-commerce/AP2/blob/main/CHANGELOG.md
[AP2-AMT] AP2 Amount schema https://github.com/google-agentic-commerce/AP2/blob/main/code/sdk/schemas/ap2/types/amount.json
[DSDJWT] Delegate SD-JWT, draft-gco-oauth-delegate-sd-jwt-00 (individual draft, 2026-04-22) https://datatracker.ietf.org/doc/draft-gco-oauth-delegate-sd-jwt/
[SDJWTVC] SD-JWT-based Verifiable Digital Credentials, draft-ietf-oauth-sd-jwt-vc-19 (2026-08-31). IESG state: Waiting for AD Go-Ahead https://datatracker.ietf.org/doc/draft-ietf-oauth-sd-jwt-vc/
[VC2] W3C Verifiable Credentials Data Model v2.0, Recommendation, 15 May 2025 (section 5.9) https://www.w3.org/TR/vc-data-model-2.0/
[VC-JOSE] W3C Securing Verifiable Credentials using JOSE and COSE, Recommendation, 15 May 2025 https://www.w3.org/TR/vc-jose-cose/
[VC-DI] W3C Verifiable Credential Data Integrity 1.0, Recommendation, 15 May 2025 https://www.w3.org/TR/vc-data-integrity/
[BSL] W3C Bitstring Status List v1.0, Recommendation, 15 May 2025 https://www.w3.org/TR/vc-bitstring-status-list/
[VI] Verifiable Intent specification (v0.1.0) https://github.com/agent-intent/verifiable-intent/blob/main/spec/README.md
[FIDO] FIDO Alliance to Develop Standards for Trusted AI Agent Interactions (2026-04-28) https://fidoalliance.org/fido-alliance-to-develop-standards-for-trusted-ai-agent-interactions/
[RFC6750] OAuth 2.0 Bearer Token Usage (insufficient_scope) https://www.rfc-editor.org/rfc/rfc6750
[RFC8693] OAuth 2.0 Token Exchange https://www.rfc-editor.org/rfc/rfc8693
[RFC6838] Media Type Specifications and Registration Procedures (vendor tree) https://www.rfc-editor.org/rfc/rfc6838
[EMISSAR-DA] Emissar guide: Delegated authority https://emissar.ai/learn/delegated-authority
[EMISSAR-EXT] Emissar guide: A2A extensions https://emissar.ai/learn/a2a-extensions

Appendix A. Demo output

node mandate-demo.mjs --write . in the examples folder, run on 2026-09-26 (local time; the script prints UTC) with Node v24.13.0. The script generates new keys on each run, so keys, identifiers and signatures differ between runs; the outcomes do not. The example JSON files in examples/mandate/ were written by this run. Long strings are shortened in the printout only.

Scenario What it tests
A First contact without a mandate
B A valid presentation: refund CAD 42.00 on ORD-1042
C1, C2 Replay: on the finished task, and of the presentation in a new task
D Wrong agent key: an attacker holds the mandate and Disclosures but signs with its own key
E Over the per-operation limit: CAD 250.00 against max_amount CAD 200.00
F Out of scope: cancel SUB-9999 when the mandate covers SUB-3310
G Expired mandate
H Revoked mandate: the issuer flips the status bit and republishes the list
Emissar Mandate v0.1 demo. node v24.13.0, clock 2026-09-27T00:17:01.000Z

Self-tests
  RFC 7638 thumbprint of the RFC 9449 example key: 0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I (matches RFC 9449 section 6.1)
  Token Status List example "eNrbuRgAAhcBXQ" inflates to b9a3 (matches draft section 4.2)

Setup
  issuer https://mandates.assistant.example (kid mandate-key-2026-09); verifier audience https://agents.provider.example
  agent key jkt    F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk
  attacker key jkt hPtwcgortBgK2E9s7u18B-jW8glSQ6WTBl4MP39lSzA
  status list https://mandates.assistant.example/status/3: 131072 entries, bits 1, lst 52 chars

Issued mandate M1: issuer JWT header
{
  "alg": "ES256",
  "typ": "vnd.emissar.mandate+sd-jwt",
  "kid": "mandate-key-2026-09"
}

Issued mandate M1: issuer JWT payload (as signed; _sd and ... hold digests)
{
  "iss": "https://mandates.assistant.example",
  "sub": "psub-6f1c2a9e",
  "aud": "https://agents.provider.example",
  "iat": 1790468221,
  "exp": 1790471821,
  "jti": "D-ekl0v6NGLB9TPxac_hGQ",
  "cnf": {
    "jkt": "F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk"
  },
  "act": {
    "sub": "https://agents.assistant.example/billing"
  },
  "status": {
    "status_list": {
      "idx": 108115,
      "uri": "https://mandates.assistant.example/status/3"
    }
  },
  "principal": {
    "type": "person",
    "_sd": [
      "5gzmGTgTyhk1LJ3oeLm7CD7jB_OBb-wMe9QPgcNIZU0",
      "zlkEreM-9cg8jPSuKqRVxTt_tEY0ilau9QNlR0yugpU"
    ]
  },
  "authorization_details": [
    {
      "...": "LitkWRLnCpP3fxwQOzNTy0PwBrjZstOLSU3D0Uu3v-Q"
    },
    {
      "...": "Cw---7_D7bYl9llorl2zQAQHOuCNx_nw2yRq4am-0vI"
    }
  ],
  "_sd_alg": "sha-256"
}

Issued mandate M1: disclosures
  principal.name             digest zlkEreM-9cg8jPSuKqRVxTt_tEY0ilau9QNlR0yugpU  ["W02UKv9i1nflJH6CiNwSig","name","Alex Example"]
  principal.account          digest 5gzmGTgTyhk1LJ3oeLm7CD7jB_OBb-wMe9QPgcNIZU0  ["bVsAmshBY4EUkfxMnQ0hsw","account","CUST-88121"]
  authorization_details[0]   digest LitkWRLnCpP3fxwQOzNTy0PwBrjZstOLSU3D0Uu3v-Q  ["ijmTP0iJwsG9xv67alS6pA",{"type":"https://provider.example/mandate-types/order","actions"
  authorization_details[1]   digest Cw---7_D7bYl9llorl2zQAQHOuCNx_nw2yRq4am-0vI  ["wv_-YH7oR3Y3e2mhqIJuPQ",{"type":"https://provider.example/mandate-types/subscription","a
  compact SD-JWT as issued: 1722 chars

B: SendMessage request body (A2A v1.0 JSON-RPC)
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "SendMessage",
  "params": {
    "message": {
      "messageId": "accc4087-21a2-4a97-a443-e3c93d6b9300",
      "role": "ROLE_USER",
      "parts": [
        {
          "text": "Refund 42.00 CAD on ORD-1042. Mandate attached."
        }
      ],
      "taskId": "ba8e2999-d7b1-4cf5-9391-fb4389c48851",
      "extensions": [
        "https://emissar.ai/ext/mandate/v1"
      ],
      "metadata": {
        "https://emissar.ai/ext/mandate/v1": {
          "presentation": "eyJhbGciOiJFUzI1NiIsInR5cCI6InZuZC5lbWlzc2FyLm1hbmRhdGUrc2Qt…[2173 chars]"
        }
      }
    },
    "configuration": {
      "historyLength": 0
    }
  }
}

B: verification trace
  step  2  ok  issuer JWT, 2 disclosure(s), KB-JWT
  step  3  ok  typ vnd.emissar.mandate+sd-jwt, alg ES256, kid mandate-key-2026-09
  step  4  ok  trusted issuer https://mandates.assistant.example
  step  5  ok  issuer signature valid
  step  6  ok  2 disclosure(s) applied, 1 detail(s) visible
  step  7  ok  jti D-ekl0v6NGLB9TPxac_hGQ, lifetime 3600 s
  step  8  ok  valid until 2026-09-27T01:17:01.000Z
  step  9  ok  aud https://agents.provider.example
  step 10  ok  agent key thumbprint matches cnf.jkt F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk
  step 11  ok  sd_hash, aud and iat valid
  step 12  ok  challenge nonce consumed
  step 13  ok  status VALID at index 108115
  step 14  ok  covered by authorization_details[0]
  step 15  ok  within limits (use 1 of 2)
  step 16  ok  usage recorded

B: response (task completed; artifact metadata carries the result)
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "task": {
      "id": "ba8e2999-d7b1-4cf5-9391-fb4389c48851",
      "contextId": "e51e4c94-cbc1-4059-b73e-b8ef02cbe4ed",
      "status": {
        "state": "TASK_STATE_COMPLETED",
        "timestamp": "2026-09-27T00:17:01.000Z"
      },
      "artifacts": [
        {
          "artifactId": "34265d41-6d0a-4806-b1ab-b83ac9fe8873",
          "name": "Refund",
          "parts": [
            {
              "text": "Refund of 42.00 CAD on order ORD-1042 approved."
            },
            {
              "data": {
                "orderId": "ORD-1042",
                "refunded": {
                  "amount": 4200,
                  "currency": "CAD"
                },
                "status": "approved"
              },
              "mediaType": "application/json"
            }
          ],
          "extensions": [
            "https://emissar.ai/ext/mandate/v1"
          ],
          "metadata": {
            "https://emissar.ai/ext/mandate/v1": {
              "result": "accepted",
              "iss": "https://mandates.assistant.example",
              "jti": "D-ekl0v6NGLB9TPxac_hGQ",
              "sdHash": "NfZhRWM2VtPe6phbp6-tveuSUpZyMVTgwxI-JSsQOlY",
              "jkt": "F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk"
            }
          }
        }
      ]
    }
  }
}

H: response (revoked; task back in AUTH_REQUIRED with a fresh challenge)
{
  "jsonrpc": "2.0",
  "id": 14,
  "result": {
    "task": {
      "id": "5111ddb1-8ced-4d5f-a286-fd67234f4824",
      "contextId": "9377c64d-daa2-4cd9-82c1-e3bff6a72371",
      "status": {
        "state": "TASK_STATE_AUTH_REQUIRED",
        "timestamp": "2026-09-27T00:17:01.000Z",
        "message": {
          "messageId": "c7d2c78f-2ecb-477e-ace4-768f0a1ffd34",
          "contextId": "9377c64d-daa2-4cd9-82c1-e3bff6a72371",
          "taskId": "5111ddb1-8ced-4d5f-a286-fd67234f4824",
          "role": "ROLE_AGENT",
          "parts": [
            {
              "text": "The mandate was revoked. This refund needs a mandate from th…[114 chars]"
            }
          ],
          "extensions": [
            "https://emissar.ai/ext/mandate/v1"
          ],
          "metadata": {
            "https://emissar.ai/ext/mandate/v1": {
              "error": "mandate_revoked",
              "errorDescription": "The mandate was revoked.",
              "challenge": {
                "nonce": "vEDD36Y146IHPgvbCt8htA",
                "audience": "https://agents.provider.example",
                "expiresAt": "2026-09-27T00:27:01.000Z"
              },
              "authorizationDetails": [
                {
                  "type": "https://provider.example/mandate-types/order",
                  "actions": [
                    "refund"
                  ],
                  "identifier": "ORD-1042",
                  "limits": {
                    "max_amount": {
                      "amount": 20000,
                      "currency": "CAD"
                    }
                  }
                }
              ],
              "acceptedIssuers": [
                "https://mandates.assistant.example"
              ]
            }
          }
        }
      }
    }
  }
}

Scenarios
  id  scenario                                     result                                          step  pass
  A   no mandate presented                         TASK_STATE_AUTH_REQUIRED mandate_required          -  yes
  B   valid mandate, refund 42.00 CAD              TASK_STATE_COMPLETED accepted                      -  yes
  C1  replay of B on its finished task             JSON-RPC -32004 UNSUPPORTED_OPERATION              -  yes
  C2  replay of B's presentation in a new task     TASK_STATE_AUTH_REQUIRED proof_invalid            12  yes
      reason: nonce is not a live challenge for this task
  D   stolen mandate, attacker's own key           TASK_STATE_AUTH_REQUIRED proof_invalid            10  yes
      reason: presenting key hPtwcgortBgK2E9s7u18B-jW8glSQ6WTBl4MP39lSzA is not the bound agent key F1HWDtbr4TVd6yoilQPcluMOKm8EqUUxOCEZJcdPBEk
  E   refund 250.00 CAD, max_amount 200.00         TASK_STATE_AUTH_REQUIRED limit_exceeded           15  yes
      reason: 250.00 CAD exceeds max_amount 200.00 CAD; total would exceed 200.00 CAD
  F   cancel SUB-9999, mandate covers SUB-3310     TASK_STATE_AUTH_REQUIRED insufficient_scope       14  yes
      reason: no disclosed authorization detail covers cancel SUB-9999
  G   expired mandate                              TASK_STATE_AUTH_REQUIRED mandate_expired           8  yes
      reason: expired at 2026-09-26T23:17:01.000Z
  H   revoked mandate, refund 10.00 CAD            TASK_STATE_AUTH_REQUIRED mandate_revoked          13  yes
      reason: status list says INVALID (revoked)

9/9 scenarios matched the expected outcome; self-tests passed.

Wrote example files to .

Appendix B. Validation output

python validate.py (jsonschema 4.26.0), run after the demo on the same files:

Mandate schema: examples
  ok   mandate.json processedPayloadAsPresentedInB (root)
  ok   mandate.json with every disclosure applied (root)
  ok   mandate.json header ($defs/issuerJwtHeader)
  ok   compact issuer JWT decodes to the listed header and payload
  ok   presentation.json kbJwtHeader ($defs/kbJwtHeader)
  ok   presentation.json kbJwtPayload ($defs/kbJwtPayload)
  ok   KB-JWT in the presentation decodes to the listed header and payload
  ok   send-message-request.json metadata entry ($defs/presentationEnvelope)
  ok   request carries the presentation from presentation.json
  ok   auth-required-response.json status metadata ($defs/challengeEnvelope)
  ok   send-message-response-completed.json artifact metadata ($defs/resultEnvelope)
  ok   agent-card.json extension params ($defs/cardParams)
  ok   status-list-token.json payload ($defs/statusListTokenPayload)

Mandate schema: negative tests
  ok   detail limits with an unknown member (rejected as expected)
  ok   detail with a member v0.1 does not define (locations) (rejected as expected)
  ok   processed payload that still contains _sd (rejected as expected)
  ok   mandate without a status claim (rejected as expected)
  ok   mandate bound with cnf.jwk instead of cnf.jkt (rejected as expected)
  ok   amount that is not an integer in minor units (rejected as expected)
  ok   KB-JWT header carrying a private key (rejected as expected)
  ok   issuer JWT header with jku (rejected as expected)
  ok   presentation without a KB-JWT (rejected as expected)

A2A JSON Schema (generated from a2a.proto)
  source https://a2a-protocol.org/latest/spec/a2a.json
  ok   send-message-request.json params ($defs/SendMessageRequest)
  ok   send-message-response-completed.json result ($defs/SendMessageResponse)
  ok   auth-required-response.json result ($defs/SendMessageResponse)
  ok   agent-card.json ($defs/AgentCard)

All checks passed.

Appendix C. Files

All files are published under https://emissar.ai/specs/ with the paths below; keep the same layout locally (the validator reads the schema at ../../schemas/ from its folder).

Path Content
mandate/v0.1 This document
schemas/mandate-v0.1.schema.json JSON Schema (draft 2020-12): processed mandate payload and $defs
examples/mandate/mandate-demo.mjs Issuer, agent, verifier and a minimal A2A JSON-RPC verifier agent. Node 20 or later, no dependencies
examples/mandate/validate.py Schema checks, negative tests, and A2A schema checks
examples/mandate/mandate.json Mandate M1: compact form, header, payload as issued, Disclosures, processed payload
examples/mandate/presentation.json Scenario B’s SD-JWT+KB with its decoded KB-JWT
examples/mandate/send-message-request.json Scenario B’s full SendMessage request
examples/mandate/send-message-response-completed.json Scenario B’s response with the result record
examples/mandate/auth-required-response.json Scenario H’s response: AUTH_REQUIRED, mandate_revoked, new challenge
examples/mandate/agent-card.json Illustrative verifier Agent Card declaring the extension
examples/mandate/status-list-token.json The Status List Token after revocation, with the revoked index