Internet-Draft A2A Trust September 2026
Trujillo Expires 8 March 2027 [Page]
Workgroup:
Network Working Group
Internet-Draft:
draft-tonyai-a2a-trust-03
Published:
Intended Status:
Informational
Expires:
Author:
T. Trujillo
Individual Submission

Agent-to-Agent Trust, Identity, and Verifiable Provenance

Abstract

This document defines a trust model for agent-to-agent (A2A) interactions in multi-agent AI systems. It specifies how agents obtain verifiable identities via CA-signed templates, how spawn chains are cryptographically established and validated, how dynamic policies are governed under a dual-signature model, and how cross-organizational agent interactions are explicitly authorized. The model applies existing PKI primitives (X.509, CRL, CSR) and established identity patterns (OAuth 2.0, On-Behalf-Of) to the problem of agent provenance. This document does not address agent-to-resource access control, human-in-the-loop orchestration, or agent behavior, as those concerns belong to the resource enforcement layer and the orchestration layer respectively.

Status of This Memo

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

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

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

This Internet-Draft will expire on 8 March 2027.

Table of Contents

1. Introduction

Multi-agent AI systems introduce identity and authorization gaps that existing standards do not fully address. When Agent A spawns Agent B, and Agent B calls a resource, no current standard defines how the resource verifies that Agent B was legitimately spawned, that its scope has not been escalated, or that its origin template is trusted.

This document proposes a trust model based on:

The model reuses proven PKI primitives and applies them to a new surface -- agent identity -- rather than inventing new cryptographic mechanisms.

2. Conventions Used in This Document

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.

3. Document Encoding

Every document defined by this specification -- the Agent Template extension of Section 8.2, the Agent Spawn extension of Section 10.5, the dynamic policy document of Section 11.4, the cross-organizational grant of Section 13.2, and the audit log entry of Section 10.4 -- is a JSON object serialized using the JSON Canonicalization Scheme (JCS) [RFC8785].

Field names in the tables of this document are display names, written for a reader. The corresponding wire names are lowercase, use underscore as the word separator, and are given in Table 3. A relying party MUST compare wire names exactly and MUST NOT apply case folding, Unicode normalization, or any other transformation before comparison.

The same rule governs every string value this document compares for equality: an agent identifier, an Owner, an OrgID, a Grantor or Grantee, a scope, a nonce, an outcome. Two values are equal when their octets are identical, and a relying party MUST NOT apply case folding, Unicode normalization, trimming, or any other transformation to either before comparing them. Where a later section restates this for one value, it does so for emphasis, not because the rule differs there.

A JSON object carried under this specification MUST NOT contain a duplicate member name, which [RFC8785], Section 3.1, also requires of any input to JCS. A relying party MUST detect a duplicate and refuse the document. This is a requirement on the parser, not only on the document: JSON syntax permits duplicates, and a parser that silently keeps the first or the last occurrence does not satisfy it. Two such parsers disagree about what was signed while both report success, which is the failure this rule exists to prevent.

Every timestamp carried under this specification is an [RFC3339] date-time in UTC using the Z designator. A relying party MUST refuse a timestamp carrying a numeric offset, a lowercase designator, or no designator: a time is compared byte-for-byte in a signed body, and one instant with two spellings is two instants to a signature. Fractional seconds MAY be present.

The JSON objects this document defines are flat. Their members are strings, integers, or arrays of strings, as the tables specify, and nothing else. A relying party MUST refuse an object carrying a nested object, an array of anything other than strings, a null, a boolean, or a non-integer number, before any further processing. A parser that will accept only the shapes this document defines has no depth to exhaust and no type to confuse.

3.1. Signature Envelope

A signed document is carried inside an envelope: a JSON object whose members are the signed document itself and the values that attest to it. The envelope members are named as follows. These names are REQUIRED; a relying party MUST refuse an envelope carrying any member not listed here.

Table 1: Envelope Members
Member Type Content
body object The signed document: a template, a policy, or a grant
owner_sig string Signature by the template Owner
pa_sig string Signature by the Policy Authority
content_hash string SHA-256 digest of the signed octets, lowercase hexadecimal. REQUIRED in the envelope of a dynamic policy document; MUST be absent from the envelope of a template or a grant (Section 11.6)

Every signature, and the content hash, is computed over the same octet string: the JCS serialization of body, and nothing else. The other envelope members are outside body and therefore never inside a preimage. A signature cannot cover itself, and an implementation that signs the whole envelope produces a value no verifier can reproduce. The rule that a document carrying an undefined field MUST be refused applies to body; the envelope members are not fields of the document they attest to.

Each signature member MUST be a string containing the base64 encoding [RFC4648] of the raw signature value, without line breaks and without PEM framing. A relying party MUST refuse an envelope whose owner_sig and pa_sig verify under the same public key: the subjectPublicKeyInfo of the Owner certificate and of the Policy Authority certificate MUST differ. Two roles satisfied by one key is one role. The comparison is of keys, not of signature octets: a randomized signature scheme produces different octets from one key on every signing, so equal signatures would never be observed even when a single key holds both roles.

The signature algorithm is determined by the type of the signer's public key, as carried in the signer's certificate, and is not signalled in the envelope. A signer MUST use, and a relying party MUST verify with, exactly the algorithm this table assigns; any other combination MUST be refused.

Table 2: Signature Algorithm by Key Type
Signer key Algorithm Signature value
RSA, 3072 bits or more RSASSA-PSS with SHA-256, MGF1 with SHA-256, salt length 32 octets The PSS signature octets
EC, curve P-256 ECDSA with SHA-256 r and s, each 32 octets, concatenated: 64 octets
EC, curve P-384 ECDSA with SHA-384 r and s, each 48 octets, concatenated: 96 octets
Ed25519 Ed25519 (PureEdDSA) [RFC8032] The 64-octet EdDSA signature

Fixing the digest to the key type is what allows the envelope to carry no algorithm identifier: a verifier learns everything it needs from the certificate it has already validated, and an attacker cannot negotiate a weaker algorithm because there is nothing to negotiate. ECDSA values are the fixed-width concatenation rather than DER, so that a signature has exactly one encoding. RSASSA-PSS is specified rather than RSASSA-PKCS1-v1_5 because PSS carries a security proof and is the scheme new profiles adopt; a relying party MUST refuse a PKCS1-v1_5 signature even when it verifies. PSS is randomized: the same key and body produce a different signature on each signing, so a test vector verifies a signature rather than comparing its octets.

3.2. Wire Names

The following table gives the wire name for every display name used in this document. Where a display name appears in more than one document it has the same wire name in each.

Table 3: Display Name to Wire Name
Display name Wire name Defined in
Subject subject Sections 8.1, 11.4
Owner owner Sections 8.1, 11.4
OrgID org_id Sections 8.1, 11.4
PermittedOperations permitted_operations Section 8.1
AllowedScopes allowed_scopes Sections 8.1, 13.2
CanSpawn can_spawn Section 8.1
MaxChildren max_children Section 8.1
PolicyRef policy_ref Section 8.1
TTL ttl_seconds Sections 8.1, 13.2
Scopes scopes Section 11.4
SpawnTargets spawn_targets Section 11.4
Version version Section 11.4
IssuedAt issued_at Sections 11.4, 13.2
NotAfter not_after Section 11.4
Grantor grantor Section 13.2
Grantee grantee Section 13.2
Template template Section 13.2
MaxSpawns max_spawns Section 13.2
GrantID grant_id Sections 13.2, 10.5
ParentAgentID parent_agent_id Section 10.5
SpawnedAt spawned_at Section 10.5
SpawnNonce spawn_nonce Section 10.5

4. Terminology

Agent:
An ephemeral, autonomous process that performs tasks on behalf of a user or another agent.
Agent Template:
A CA-signed artifact defining exactly one agent's identity, allowed scopes, spawn rules, and policy reference. A template is not a class from which many agents are made: its Subject is the identifier of the one agent it defines, and spawning from a template instantiates that agent. A deployment wanting many similar agents registers many templates.
Relying Party:
Any party that validates an agent's certificate, chain, policy, or grant in order to decide whether to act on it -- a resource, a Registry evaluating a spawn request, or another agent.
Owner:
The party responsible for a template, identified by the template's Owner field and holding the private key of the Owner certificate described in Section 9.2.
Orchestrator:
An agent that spawns other agents. The figures in this document use the bare term for any such agent; the Root Orchestrator is the one with no parent.
Root Orchestrator:
An agent that has no parent. Its certificate carries no Agent Spawn extension (Section 10.5).
Template Registry:
The authoritative store of approved, signed agent templates for an organization.
Template Registry CA:
The Certificate Authority that signs agent templates -- the root of trust for the agent ecosystem.
Spawn:
The act of an agent instantiating a child agent from an approved template.
Spawn Chain:
The ordered, cryptographically verifiable sequence of agents from the root orchestrator to the current agent.
Policy Authority:
The entity responsible for countersigning dynamic policy changes after automated gate validation.
CRL:
Certificate Revocation List -- the list of revoked template and agent certificates maintained by the CA.
CSR:
Certificate Signing Request -- the template author's request to the CA for a signed template certificate.
Cross-Org Grant:
An explicit, signed authorization allowing agents from one organization to spawn from a template owned by another.

The Template Registry and the Template Registry CA are described as one logical entity throughout this document -- "the Registry" -- that stores templates, evaluates spawn requests, and issues certificates. A deployment may separate them; the interface between them is outside this document, and every requirement placed on "the Registry" applies to that entity as a whole.

5. Problem Statement

Multi-agent orchestration creates identity and authorization gaps:

   Agent A --> spawns --> Agent B --> calls --> Resource
Figure 1

The author is not aware of a standard, from the W3C, the IETF, or a vendor, that fully addresses agent provenance in multi-hop chains.

6. Existing Patterns and Gaps

Several systems address a neighbouring problem. Workload identity frameworks such as SPIFFE [SPIFFE] issue verifiable identities to services but do not model one service spawning another under a bounded delegation. Relationship-based authorization systems such as OpenFGA [OpenFGA] evaluate what an identity may do but assume the identity is already established. PKI secrets engines such as Vault [VAULTPKI] issue certificates on request but leave the content of a certificate to the requester. This document assumes the zero-trust posture of [NIST800-207], in which no request is trusted for where it came from, and applies it to the question those systems leave open: how an agent proves what authority it was granted, and by whom.

6.1. On-Behalf-Of (OBO)

Microsoft Entra ID OBO provides user-to-service delegation:

   User --> Agent A (token A) -->
   Agent A requests token for Agent B on behalf of user -->
   Entra validates the chain -->
   Issues scoped delegated token
Figure 2

Key insight: a trusted third party validates the delegation chain. Agents do not self-assert trust.

OBO breaks down for agent-to-agent because agents are ephemeral, agent spawning is dynamic, and no registry exists for agent templates.

6.2. OAuth 2.0 Token Exchange (RFC 8693)

OAuth 2.0 [RFC6749] Token Exchange [RFC8693] defines scope constraint across delegation hops -- downstream tokens MUST be a subset of upstream grants. This document adopts that principle for agent scope inheritance.

7. Agent Identity

Agent identity MUST be established using X.509 certificate chains [RFC5280]. This reuses the same trust model used by TLS and existing workload identity systems.

7.1. Certificate Profile

Certificates used for agent identity MUST conform to [RFC5280]. In addition, a relying party validating an agent certificate MUST enforce all of the following, and MUST refuse the certificate if any is not satisfied:

  • An agent certificate MUST carry the basicConstraints extension asserting cA = FALSE. A certificate that omits basicConstraints MUST be refused; the extension's absence MUST NOT be treated as equivalent to cA = FALSE.
  • A Template Registry CA certificate MUST carry basicConstraints asserting cA = TRUE, marked critical, and MUST assert keyCertSign in its keyUsage extension.
  • Certificates MUST be signed using SHA-256 or a stronger digest. Certificates signed with SHA-1 or MD5 MUST be refused irrespective of key size.
  • Public keys MUST provide at least a 128-bit security level as defined in [SP800-57]: RSA with a modulus of 3072 bits or more, an EC key on P-256 or P-384, or an Ed25519 key [RFC8410]. A relying party MUST refuse a certificate whose key falls below this level, including an RSA key of 2048 bits. EC and Ed25519 keys are RECOMMENDED over RSA: they reach the floor with smaller certificates and faster generation, and Ed25519 signatures are deterministic.
  • An agent certificate MUST carry the keyUsage extension, marked critical, asserting digitalSignature and no other bit. keyCertSign and cRLSign MUST NOT be asserted on an agent certificate; a relying party MUST refuse one that asserts either, independently of the basicConstraints check above.
  • The serialNumber MUST contain at least 64 bits of output from a cryptographically secure random number generator. A predictable serial number is an input an attacker controls when searching for a digest collision over a certificate. The value is an ASN.1 INTEGER, which [RFC5280] requires to be positive, at most 20 octets, and in minimal DER form. An implementation that clears the top bit of the first random octet to keep the value positive discards a bit of entropy and, one draw in 256, produces a leading zero octet followed by an octet below 0x80 -- a non-minimal encoding that a strict parser refuses. Draw the random octets, at most 19 so that a prepended octet stays within the limit; strip any leading zero octets; and prepend a single zero octet only when the first remaining octet has its top bit set. The result is positive, minimal, and carries every bit it was given.

An agent certificate asserting cA = TRUE is a certificate entitled to issue further certificates. Such an agent can create children without presenting a request to the Template Registry CA, which removes both checks required by Section 10.1 from the spawn path entirely. No signature is invalid in that scenario and no chain fails to verify; the containment described in Section 8 is simply never consulted. This is the reason the constraint is stated normatively here rather than left to the general RFC 5280 profile.

These requirements are necessary and not sufficient. A certificate satisfying all of them establishes identity only; it carries no authorization. See Section 19.6.

7.2. Binding Identity to the Certificate

An agent has exactly one identity, expressed as a UUID in the canonical lowercase textual form defined in [RFC9562]. A relying party MUST refuse a certificate whose subject common name is absent, is not a well-formed UUID in that form, or does not match the agent identifier the presenting party claims. Uppercase hexadecimal MUST be refused rather than case-folded: the identifier is compared byte-for-byte in several places, and an implementation that folds in one of them and not another will accept a document another implementation refuses.

This document does not constrain which UUID version is used. Implementations SHOULD use version 4 where the time an agent was created should not be inferable from its identifier, and MAY use version 7 where time-ordered identifiers are wanted and that disclosure is acceptable. A version 7 identifier embeds a millisecond timestamp, and an agent identifier travels to places its template does not -- audit records, policy references, diagnostic messages -- so the disclosure is wider than the certificate's own notBefore field.

Where a chain document restates that identifier alongside the certificate, every restatement MUST be identical to the subject common name, and a relying party MUST refuse the document if any two disagree. An implementation MUST NOT treat one restatement as authoritative and the others as advisory.

This requirement exists because a restated identifier that no signature covers is an unsigned claim sitting next to a signed one. Without this rule a chain could name one agent in the position a relying party reads and present a certificate issued to a different agent, and both artifacts would validate on their own terms.

7.3. Certificate Signing Request Flow

   Template Author
       | defines template (scopes, spawn rules, TTL, owner)
       v
   Conformance gate (Section 9.1)
       | every REQUIRED field present and non-null
       v
   Dual attestation (Section 9.2)
       | Owner signs; Policy Authority countersigns
       | the same JCS octets
       v
   CSR carrying the attested template
       v
   Template Registry CA (Section 9.3)
       | re-applies the gate, re-verifies both signatures
       | signs the template certificate
       v
   Signed Agent Template (registered)
       |
       v
   Orchestrator spawns agent from signed template (Section 10)
       | agent receives a certificate the CA issues from it
       | CA chain proves provenance
       v
   Resource validates certificate chain:
       - certificate issued by a trusted Template Registry CA?
       - Agent Template extension present and well-formed?
       - scope within bounds?
       - ALLOW or DENY
Figure 3

7.4. Certificate Chain Structure

   Template Registry CA (root of trust)
       |
       | issues BOTH certificates (Section 9.3)
       |
       +--> Orchestrator Agent Certificate
       |      Subject CN:  9f3c...  (a UUID, Section 7.2)
       |      Issuer:      Template Registry CA
       |      Agent Template extension (Section 8.2):
       |        subject: 9f3c...  (equals Subject CN, 9.3)
       |        owner, org_id
       |        permitted_operations: [spawn]
       |        allowed_scopes:       [read:data, write:data]
       |        can_spawn: [2b7e...], max_children: 1
       |        policy_ref, ttl_seconds: 3600
       |
       +--> Child Agent Certificate
              Subject CN:  2b7e...  (a UUID)
              Issuer:      Template Registry CA
              Agent Template extension:
                subject: 2b7e...
                allowed_scopes: [read:data]  (subset, 10.3)
                ttl_seconds:    900          (shorter, SHOULD)
              Agent Spawn extension (Section 10.5):
                parent_agent_id: 9f3c...
                spawned_at, spawn_nonce
                grant_id  (only when spawned under a grant, 13.2)

   An agent certificate never issues a certificate (Section 7.1).
   The parent-child link is recorded in the child's Agent Spawn
   extension; the chain of authority runs through the CA.
Figure 4

8. Template Structure

8.1. Static Fields

The following fields MUST be present in every agent template certificate and MUST NOT be modified without full re-certification:

Table 4
Field Required Description
Subject REQUIRED Unique template identifier
Owner REQUIRED Verified identity of template owner
OrgID REQUIRED CA-validated organization identifier
PermittedOperations REQUIRED Operations this agent may perform
AllowedScopes REQUIRED Maximum scopes this agent may hold
CanSpawn REQUIRED Whitelist of permitted child templates
MaxChildren REQUIRED Maximum concurrent child agents
PolicyRef REQUIRED Pointer to dynamic policy store
TTL REQUIRED Maximum agent lifetime

This document defines one value of PermittedOperations: spawn, which an agent MUST hold to invoke Section 10. Any other value, including those shown in examples, is defined by the deployment and carries no meaning under this specification. A template whose CanSpawn is non-empty while its PermittedOperations omits spawn describes an agent permitted to spawn specific children and not permitted to spawn; the conformance gate of Section 9.1 SHOULD refuse it, and a Registry MUST refuse a spawn request from it.

A template defines exactly one agent (Section 4), so each entry of CanSpawn names a child that can exist at most once at a time, and MaxChildren counts named children rather than instances of one. MaxChildren MUST NOT exceed the number of entries in CanSpawn. The conformance gate of Section 9.1 MUST refuse a template that violates this, and a relying party MUST refuse a certificate whose extension does. A cap above the number of children a template can name is a cap on nothing, and a validator reading it would count toward a limit that can never be reached.

The certificate's issuer is not a template field. It is set by the Template Registry CA at issuance (Section 9.3) and read from the certificate (Section 8.2); a template carries no member for it.

8.2. Encoding of Static Fields

The fields in Section 8.1 MUST be carried in a single X.509 certificate extension, identified by the object identifier 2.25.318754453516410815925104555075461256891 and referred to in this document as the Agent Template extension. The extension MUST be marked critical. A validator that does not implement this specification therefore refuses the certificate, as [RFC5280] requires of any unrecognized critical extension, rather than accepting it as an ordinary client certificate and granting whatever its issuer's chain would grant. The certificate is unusable except by a party that understands what it says, which is the fail-closed outcome Section 15.1 requires; an agent certificate has no legitimate use outside this specification.

The extnValue MUST be a DER OCTET STRING whose contents are the UTF-8 encoding of a JSON object, serialized as required by Section 3. A relying party MUST refuse a certificate whose Agent Template extension is not valid JCS, and MUST NOT attempt to repair or re-canonicalize it.

The JSON object MUST carry exactly the following members, all of which are REQUIRED. Wire names are as given in Table 3. A relying party MUST refuse a certificate whose Agent Template extension omits any member, carries a member not listed here, or carries a member whose type differs from the type given.

Table 5: Agent Template Extension Members
Member Type
subject string
owner string
org_id string
permitted_operations array of string
allowed_scopes array of string
can_spawn array of string
max_children integer
policy_ref string
ttl_seconds integer

The ttl_seconds member states a duration in seconds; the display name TTL in Section 8.1 does not carry a unit, and a duration whose unit is inferred is a duration two implementations will infer differently.

The certificate's issuer has no member in this extension. X.509 already carries the issuer, and a second copy inside an extension the issuer signs could disagree with the copy the relying party validated the signature against. A relying party MUST take the issuer from the certificate.

A certificate MUST NOT carry more than one Agent Template extension, and a relying party MUST refuse a certificate carrying two rather than choosing between them. The duplicate member rule of Section 3 applies, and is a requirement on the parser used to read the extension.

A relying party MUST impose a limit on the size of the extension before parsing it, and MUST refuse an extension exceeding that limit rather than attempting a partial parse. The limit is 16384 octets of extnValue for the Agent Template extension and 1024 octets for the Agent Spawn extension of Section 10.5. The first holds two hundred scopes at the maximum length of Section 10.3, which is more than any template this document contemplates; the second holds every member of a fixed-shape object with room to spare; and neither is large enough to be worth handing to a parser unverified. The extension arrives inside a certificate presented by the party whose authority it describes; it is attacker-controlled input up to the point the issuer's signature has been verified, and that signature covers whether the bytes were issued, not whether they are safe to parse. Implementations SHOULD verify the certificate signature before parsing the extension, so that malformed input from an unsigned certificate is discarded without being decoded at all.

Placing these fields in the certificate rather than in a document accompanying it is deliberate. Section 8.1 requires that they not change without re-certification. A field carried outside the certificate is signed by whoever assembled the document, not by the Template Registry CA, so an agent could present a valid certificate beside a template granting authority the CA never issued. Carrying them inside the certificate makes the immutability requirement a property of the artifact rather than a rule an implementation is asked to remember.

8.3. Dynamic Policy Bounds

Dynamic policies MUST be bounded by the static template fields. A dynamic policy MUST NOT grant scopes beyond AllowedScopes. A dynamic policy MUST NOT add spawn targets beyond CanSpawn.

A relying party MUST evaluate these bounds itself, on every validation, against the static fields of the template certificate naming the subject the policy governs. This evaluation MUST be independent of signature validity -- a bounds violation is refused whether or not the signatures verify -- and it is performed after signature verification, in the order given by Section 11.7, so that a refusal under this section reports an authentic document whose content is not permitted. A policy exceeding the bounds MUST be refused before it is applied, however many valid signatures it carries.

The signatures required by Section 11.3 and the bounds required here answer different questions. The signatures establish who authorized a change. They do not, and cannot, establish that the change was within the ceiling the template set, because the ceiling is stated in a certificate that no signature over the policy covers. An implementation that treats a valid dual signature as sufficient authority to apply a policy has removed the only mechanism bounding what a policy may grant.

Refusal under this section is a distinct condition from a signature failure, and implementations SHOULD report it distinctly: the document is authentic and its content is not permitted. Reporting it as a signature failure misdirects the operator to the wrong lane of Section 11.1.

9. Template Authoring and Attestation

A template is authored before any certificate is issued against it. This section specifies the checks that MUST pass before a Template Registry CA issues a certificate carrying the fields of Section 8.1.

9.1. Conformance Gate

Every field marked REQUIRED in Section 8.1 MUST be present and non-null before a template is signed. A template missing any REQUIRED field is non-conforming and MUST be refused, both at signing and again at issuance. An implementation MUST NOT sign a non-conforming template, and MUST NOT issue a certificate against one by omitting the corresponding member from the Agent Template extension.

The gate is applied twice deliberately. A template that was conforming when signed can be edited afterwards, and an issuance path that trusts the signature without re-checking conformance will issue a certificate whose extension is missing a member the relying party requires.

9.2. Dual Attestation

A template MUST carry two signatures before it is eligible for issuance: one from the template Owner and one from the Policy Authority. Both signatures MUST be computed over the same octet string, as required by Section 3.1, being the JCS serialization of the template restricted to the members of Table 5. A relying party MUST verify both, and MUST refuse the template if either is absent or does not verify.

Signature verification MUST occur after the conformance gate of Section 9.1, not before. A signature over an incomplete body is a valid signature over an incomplete body.

Every member that becomes part of the Agent Template extension MUST be inside the signed body. A member carried into a certificate without having been covered by both signatures has entered the certificate without the approval the two signatures exist to record.

Both signatures MUST use the algorithm that Table 2 assigns to the signer's key type, over a key meeting the strength floor of Section 7.1. The requirement is stated by reference rather than restated, because two lists of acceptable algorithms in one document will eventually disagree, and the weaker of the two becomes the one an implementation follows.

The Owner and the Policy Authority each hold a certificate conforming to Section 7.1, issued by the Template Registry CA or by a CA the relying party trusts for that purpose. A relying party MUST validate that certificate to a trust anchor it holds before verifying any signature with its key, and MUST refuse a signature whose certificate does not validate: a signature that verifies under an untrusted key establishes nothing. The subject common name of the Owner certificate MUST equal the template's owner member; that equality is what binds the string in owner to a key. The Policy Authority certificate is a trust decision the relying party configures, one per Registry.

9.3. Issuance

On issuance the Template Registry CA MUST re-apply the conformance gate, MUST re-verify both signatures, and MUST copy the signed members into the Agent Template extension of Section 8.2 without alteration. The CA MUST set the certificate subject common name to the value of the template's subject member, which MUST satisfy Section 7.2, and MUST set the issuer to its own name. The template carries no issuer member, and the CA MUST NOT take the issuer from the template. A relying party MUST refuse a certificate whose subject common name differs from the subject member of its Agent Template extension.

The CA MUST set the certificate's notAfter to no later than its notBefore plus the template's ttl_seconds, so that the TTL of Section 8.1 is enforced by ordinary certificate path validation and not only by a relying party that reads the extension. A relying party MUST refuse a certificate whose notAfter minus notBefore, in seconds, exceeds its ttl_seconds: a certificate that outlives its own stated lifetime was not issued as this section requires.

ttl_seconds MUST NOT exceed 604800 (seven days), and SHOULD NOT exceed 86400 (one day). A relying party MUST refuse a certificate whose ttl_seconds exceeds the maximum. An agent is ephemeral by the definition in Section 4; its certificate's lifetime is the longest an attacker holding its key can act if revocation is slow to propagate, and Section 15.1 can only refuse a certificate a relying party knows to be revoked. A short lifetime bounds that window without depending on revocation reaching every relying party.

10. Spawn Chain Validation

10.1. Two-Check Spawn Rule

Every spawn MUST pass two independent checks. Either check failing MUST result in spawn denial with no fallback. The Template Registry performs both checks, as Section 10.2 specifies. That section lists the individual conditions in the order they are evaluated; this section states which check each condition belongs to, and an implementation MUST evaluate every condition of both.

Check 1 -- Static (from the spawning agent's certificate): The spawning agent's PermittedOperations MUST include spawn, the requested child template MUST appear in the spawning agent's CanSpawn list, and the requested scopes MUST be a subset of the spawning agent's AllowedScopes (Section 10.3). All three are read from the Agent Template extension of the spawning agent's certificate, never from a document the agent supplies. These are steps 1 and 4 of Section 10.2.

Check 2 -- Dynamic (Registry live lookup): The requested child template MUST be currently registered, CA-signed, not self-signed, not present in the current CRL, not DISABLED under Section 12.4, and owned either by the spawning agent's organization or by an organization that has issued a grant under Section 13 naming the spawning agent's organization as Grantee. The child template MUST also appear in the SpawnTargets of the dynamic policy currently in force for the spawning agent (Section 11.4), which the Registry retrieves through the PolicyRef of the spawning agent's certificate and never accepts from the agent; a policy with no SpawnTargets grants none, and an agent with no policy in force may not spawn. Finally the spawning agent's live child count MUST be below its MaxChildren. These are steps 2, 3 and 5 of Section 10.2.

Rationale: CanSpawn alone is insufficient because the certificate may be stale and a template may have been revoked since issuance. Registry lookup alone is insufficient because any party could forge a request claiming any template. The policy condition is what gives the fast lane of Section 11.1 authority over spawning: CanSpawn is the ceiling the certificate sets, SpawnTargets is what the Owner has currently authorized within it, and a spawn target can therefore be withdrawn by a policy change without re-certification. Both checks MUST pass.

10.2. Spawn Validation Sequence

   1.  CanSpawn check -- spawn in PermittedOperations, and
       child template in CanSpawn list?
       NO  --> DENY, audit log
       YES --> continue

   2.  Registry check -- child template registered, CA-signed,
       not revoked, not DISABLED, and owned by the spawning
       agent's organization or granted to it?
       NO  --> DENY, audit log
       YES --> continue

   3.  Policy check -- child template in the SpawnTargets of
       the policy in force for the spawning agent?
       NO  --> DENY, audit log
       YES --> continue

   4.  Scope check -- requested scope subset of parent scopes?
       NO  --> DENY, audit log
       YES --> continue

   5.  MaxChildren check -- current children < MaxChildren, and
       no live certificate for the child template already?
       NO  --> DENY, audit log
       YES --> spawn approved

   6.  Template Registry CA issues the child certificate with:
       - parent identity embedded (delegation chain)
       - scope equal to requested scope (not exceeding parent)
       - spawn timestamp and nonce (replay prevention)
       - grant identifier, when spawned under a grant
       - audit log entry written
Figure 5

The count compared against MaxChildren in step 5 is held by the Template Registry, which is the only party that observes every spawn under a template. The Registry MUST perform that comparison as part of Check 2 of Section 10.1, atomically with recording the new child, so that two concurrent spawn requests cannot both observe a count one below the limit and both succeed. The second condition of step 5 follows from Section 12.1: a template defines one agent, one identity never holds two valid certificates, and the Registry MUST therefore refuse to spawn a child whose template already has an unexpired, unrevoked certificate. A relying party validating a chain document counts only the children that document names, and MUST refuse a document in which that count exceeds the parent's MaxChildren; that is a consistency check on the document, not the enforcement of the cap, and an implementation MUST NOT present it as such.

The Template Registry CA performs steps 1 through 5 and issues the certificate in step 6. The spawning agent presents a spawn request -- the child template's subject, the requested scopes, a timestamp, and a nonce per Section 19.2 -- and receives the issued certificate; it signs nothing, because Section 7.1 forbids an agent certificate from issuing. Steps 1 and 4 are evaluated against the spawning agent's own Agent Template extension, which the Registry reads from the certificate it presented. Step 3 is evaluated against the policy in force for the spawning agent, which the Registry retrieves through the PolicyRef of that extension; a policy the agent supplies with its request MUST NOT be consulted. If the policy store cannot be reached, or no policy is in force, the request is refused under Section 15.1.

10.3. Scope Constraint

A child agent's AllowedScopes MUST be a subset of the parent agent's AllowedScopes: every scope granted to the child MUST also be held by the parent. A child MUST NOT be granted any scope the parent does not itself hold; scope escalation across agent hops is explicitly prohibited. Equality is permitted -- a child MAY be granted the same scope set as its parent, or fewer.

Example:

   Parent has:  read:data, write:data
   Child gets:  read:data              -- valid
   Child gets:  read:data, write:data  -- valid (same as parent)
   Child gets:  admin:data             -- MUST be rejected
Figure 6

A scope is an opaque token. Two scopes are the same scope when their octets are identical, and a relying party MUST NOT apply case folding, Unicode normalization, prefix matching, wildcard expansion, or any hierarchy: write:data does not imply read:data, and admin:* names nothing. A scope MUST be between 1 and 64 octets, each from the set of lowercase ASCII letters, ASCII digits, colon, underscore, and hyphen. A relying party MUST refuse a document carrying a scope outside that syntax; the syntax is constrained so that byte comparison is also visual comparison, and a confusable character cannot name a scope that looks like another.

What a scope grants access to -- a secrets store, a data set, a tool -- is resource-layer authorization and is outside this document, as the Abstract states. This document bounds which scopes an agent may hold and how that bound narrows across a spawn; it does not define what any scope means. A deployment that needs to express "this agent may read vault A" does so with a scope such as secrets:vault-a:read, carried in allowed_scopes, bounded by the parent's allowed_scopes, and interpreted by the resource that owns vault A. The registry of Section 17.3 exists so that such names can eventually mean the same thing across organizations.

A collection of scopes is a set. The order in which its members appear is not significant to any comparison in this document, and a collection carrying the same scope twice is malformed and MUST be refused. The subset test above is therefore set containment, and two conforming implementations reach the same answer for the same two collections regardless of ordering. Order is significant only to serialization: [RFC8785] preserves array order, so the octets a signature covers depend on it. An implementation that reorders a collection before verifying it has changed those octets, and the signature fails; reordering is therefore not a normalization step. Comparison is performed on the parsed set, verification on the octets as received.

A request for no scopes MUST be refused. The empty set is a subset of every set, so an empty request satisfies the containment test vacuously while declaring no intent for the test to bound.

A child's ttl_seconds SHOULD NOT exceed its parent's. A delegation that outlives its delegator holds authority derived from an agent that no longer exists; the parent's certificate may be renewed, but a child sized to outlast it was sized on the assumption that it would not need to be.

10.4. Audit Requirements

Every spawn event, accepted or refused, MUST be recorded as an audit log entry: a JSON object carrying exactly the following members, subject to the presence rules the table states, serialized as Section 3 requires and hashed as Section 19.7 requires. The entry has no display names; wire names are given directly.

Table 6: Audit Log Entry Members
Member Type Content
spawning_agent_id string Identifier of the spawning agent, in the form of Section 7.2
child_template_id string Subject of the requested child template, in the same form
requested_scopes array of string The scopes the request asked for
granted_scopes array of string The scopes issued; empty when outcome is DENIED
spawn_nonce string The nonce of the request, per Section 19.2
grant_id string The GrantID of Section 13.2 when the spawn was requested under a grant; MUST be absent otherwise
timestamp string The instant the Registry recorded the outcome, per [RFC3339], in UTC
outcome string ALLOWED or DENIED, exactly
reason string The step of Section 10.2 that refused the request, and why; REQUIRED when outcome is DENIED, MUST be absent otherwise
previous_hash string The entry_hash of the preceding entry, lowercase hexadecimal; sixty-four zero digits for the first entry of a log
entry_hash string SHA-256 over the canonical form of every other member of this entry, lowercase hexadecimal, per Section 19.7

A refused request is recorded for the same reason an accepted one is: a sequence of refusals is the evidence of an attempt, and a log that records only successes cannot show one.

10.5. Encoding of Spawn Provenance

Step 5 of Section 10.2 issues a child certificate carrying its parent's identity, the time of the spawn, and the nonce of the request that produced it. These MUST be carried in a single X.509 extension, marked critical for the reason given in Section 8.2, identified by the object identifier 2.25.316124730704531463413455892107752909312 and referred to in this document as the Agent Spawn extension. It is encoded exactly as the Agent Template extension of Section 8.2: a DER OCTET STRING containing the UTF-8 JCS serialization of a JSON object, subject to the same rules on criticality, duplicate members, duplicate extensions, size limits, and parse ordering.

Table 7: Agent Spawn Extension Members
Member Type Content
parent_agent_id string The parent's identifier, in the form required by Section 7.2
spawned_at string The instant of issuance, per [RFC3339], in UTC
spawn_nonce string The nonce of the spawn request, per Section 19.2
grant_id string The GrantID of the grant under which the spawn was authorized (Section 13.2); REQUIRED when the child template is owned by an organization other than the spawning agent's, MUST be absent otherwise

parent_agent_id, spawned_at and spawn_nonce are REQUIRED when the extension is present; grant_id is present exactly when the spawn was cross-organizational, and a relying party MUST refuse a certificate that carries it for a child owned by the parent's own organization or omits it for one that is not. A certificate for an agent that has a parent MUST carry the extension; a certificate for an agent that has none -- a root orchestrator -- MUST NOT. A relying party validating a chain MUST refuse a certificate whose parent_agent_id names no agent in the chain, MUST refuse one whose parent_agent_id differs from the parent the chain document names for it, and MUST refuse a root whose certificate carries the extension.

This is what makes a spawn chain cryptographically traceable rather than merely asserted. A parent identifier carried only in a chain document is an unsigned claim beside a signed certificate: a child could name any parent it liked, and the containment of Section 10.3 would be evaluated against whichever parent it chose. Carrying the link in the certificate means the CA that issued the child attested to which agent spawned it, and that attestation is what the scope and spawn checks are evaluated against.

The parent's Agent Template extension, not the child's Agent Spawn extension, is where the child's authority is bounded. The Agent Spawn extension says who the parent is; the parent's certificate says what the parent may delegate.

The absence of the Agent Spawn extension asserts that no agent spawned this one; it does not exempt the certificate from anything. A root is legitimate for the same reason any agent certificate is: it was issued by the Template Registry CA from a template attested under Section 9, and it chains to that CA under Section 7.1. No party can declare itself a root, because no party other than the CA can issue a certificate that validates, and the CA issues only from attested templates. A relying party verifies a root exactly as it verifies any other agent certificate.

spawned_at and spawn_nonce record the request the Registry accepted. The freshness window of Section 19.2 applies to that request, at the Registry, at the time it is made. A relying party validating an issued certificate later MUST NOT apply the window to spawned_at: a certificate an hour old is as valid as one a second old, and its currency is governed by its validity period and its revocation state, not by when it was requested. A relying party MUST, however, refuse a chain in which two certificates carry the same spawn_nonce. That is a consistency check on the document, in the sense Section 10.2 gives the term: what makes a nonce unique across every chain the Registry ever issues is that the Registry accepts each nonce once, under Section 19.2, and a relying party holding one chain cannot observe another. An implementation MUST NOT present the document-local check as the enforcement of uniqueness.

grant_id is what makes Section 13.4 enforceable. A grant can be revoked by its Grantor alone, and every certificate issued under it must then become untrusted; without a member naming the grant, nothing identifies those certificates. With it, the Registry that issued them can revoke them, and a relying party in either organization learns of it through the revocation state the certificate already points to.

11. Dynamic Policy Governance

11.1. Two-Lane Model

Template certificate (static): WHO the agent is and WHO it can spawn. Changes require full re-certification.

Dynamic policy (fast lane): WHAT the agent can do within the bounds of the template certificate. Changes require dual signature (Section 11.3).

Dynamic policies MUST NOT exceed the bounds defined in the static template certificate.

11.2. Ownership

Template ownership MUST be established at certificate signing time and embedded in the Owner and OrgID fields. Only the verified owner of the organization that signed the template MAY submit policy changes. Verified means holding the private key of the Owner certificate of Section 9.2, whose subject common name equals the template's Owner field; no other form of verification is defined by this document.

11.3. Dual Signature Requirement

Every policy change MUST be signed by two independent parties:

  1. Owner -- proves the right to change the policy.
  2. Policy Authority -- proves the policy passed automated validation gates.

Neither signature alone is sufficient. Both MUST be present and valid for a policy to be accepted.

   Owner key  +  Policy Authority key  =  policy accepted
       ^                  ^
   who owns it        passed the gates
Figure 7

11.4. Dynamic Policy Document Structure

A dynamic policy document MUST contain the following fields. This is the complete set; a document containing any other field MUST be refused, since an unrecognized field is either meaningless or an attempt to convey authority the profile does not define.

Table 8: Dynamic Policy Document Fields
Field Type Required Description
Subject string REQUIRED Identifier of the agent this policy governs; MUST match the Subject of the template certificate
Owner string REQUIRED Submitting owner; MUST match Owner in the template certificate
OrgID string REQUIRED Submitting organization; MUST match OrgID in the template certificate
Scopes array of string REQUIRED Scopes granted by this policy; bounded by AllowedScopes
SpawnTargets array of string OPTIONAL Spawn targets granted by this policy, each a template Subject in the form of Section 7.2; bounded by CanSpawn. Absent means none are granted, and a spawn request is then refused at step 3 of Section 10.2
Version integer REQUIRED Monotonically increasing integer, scoped to Subject
IssuedAt string REQUIRED Timestamp of issuance, per [RFC3339]
NotAfter string OPTIONAL Expiry of this policy, per [RFC3339]; MUST NOT be later than the notAfter of the certificate the policy governs. Absent means equal to it

Version is scoped to the Subject, not global. A relying party MUST refuse a policy whose Version is not strictly greater than the Version of the policy currently in force for that Subject.

A policy is never valid beyond the notAfter of the certificate it governs, whether or not NotAfter is present. NotAfter can only shorten that period. A relying party MUST treat an absent NotAfter as equal to the certificate's notAfter, MUST refuse a policy whose NotAfter is later than it, and MUST refuse a policy presented after either has passed.

11.5. Canonicalization

Signatures and hashes defined by this document are computed over bytes, so the mapping from a policy document to those bytes MUST be deterministic and identical across implementations.

Wherever this document requires a canonical form -- of a policy document, of any field subset thereof, or of an audit log entry -- that canonical form MUST be the JSON Canonicalization Scheme (JCS) serialization defined in [RFC8785]. A single canonical form is specified for all of them deliberately: an implementation carrying two serializations will eventually apply the wrong one, and the resulting failure presents as a signature or integrity error with no indication that serialization was the cause.

JCS is specified rather than described here because a bespoke serialization would require this document to define property ordering, string escaping, and number formatting correctly and completely, and any error in that definition surfaces to implementers as a signature failure that appears to be a cryptographic fault. Serializations that differ only in whitespace, key order, or the escaping of non-ASCII characters produce different bytes and therefore different signatures; implementers MUST NOT assume a language's default JSON encoder produces the canonical form, as most do not.

11.6. Signature and Hash Coverage

Both signatures required by Section 11.3 are computed over the preimage defined in Section 3.1: the canonical form (Section 11.5) of body. Because Section 11.4 makes its table the complete content of body, every field in that table is inside the preimage and none is excluded from either signature. This section and Section 3.1 describe the same octets.

In particular, Version MUST be inside the signed preimage. Version exists to prevent replay, and it cannot serve that purpose while it remains modifiable without invalidating a signature: an attacker holding no key can otherwise take a superseded but validly signed policy, increment its Version, and present it as current. Both signatures verify, the content hash matches, and the version reads as current. The same reasoning applies to Subject: a signature that does not bind the policy to the agent it governs permits a policy issued for one agent to be presented for another.

The content hash is a member of the envelope of a dynamic policy document only. It is REQUIRED there, because step 4 of Section 11.7 stores the policy and step 5 re-reads it, and a stored document wants an integrity value that is cheaper to check than two signatures; it MUST be absent from the envelope of a template or a grant, which are verified on presentation and whose signatures already cover the same octets. The content hash MUST be SHA-256, or a stronger digest, computed over the same canonical form and the same field set as the signatures. The hash field itself is stored alongside the policy document and MUST NOT be included in its own preimage. The content hash is a derived value: a relying party MUST recompute it from body and refuse the document on a mismatch, and MUST NOT use the envelope's content_hash as an input to any decision. A modified content_hash therefore causes a refusal and nothing else; it is not a value a signature needs to protect, because the signature already covers everything the hash summarizes.

The signatures and the content hash are carried in the envelope of Section 3.1, outside the policy document they attest to. A relying party MUST refuse a policy document that carries any of them as a policy field: they are not in Section 11.4, and a value inside body would be inside its own preimage.

11.7. Policy Change Sequence

   1.  Identity and ownership verification
       - requester matches Owner in template certificate?
       - requester OrgID matches certificate OrgID?
       NO  --> rejected, audit logged

   2.  Automated gate (policy engine):
       - scope within AllowedScopes?
       - spawn targets within CanSpawn?
       - no conflicts with active policies?
       ANY FAIL --> rejected

   3.  Dual signature applied:
       Owner signs, Policy Authority countersigns

   4.  Policy stored with dual signature, version, timestamp,
       and content hash

   5.  Relying party validates at runtime:
       - both signatures valid?
       - version current? (replay prevention)
       - hash matches? (tamper detection)
       - policy within template certificate bounds?
       ANY FAIL --> DENY, audit logged
Figure 8

11.8. Threat Coverage

Table 9
Scenario Single Sig Gap Dual Sig Fix
Rogue Policy Authority Pushes bad policy Owner key missing
Rogue owner Bypasses automated gates PA won't countersign
Compromised owner key Attacker modifies Automated gates enforced
Compromised Policy Auth Pushes bad policy Owner key missing

The table above concerns the dual signature. The following concerns the encodings this document specifies, and the attack each one closes.

Table 10: Encoding Threat Coverage
Scenario Without the encoding With it
Replayed Owner signature An Owner signature over anything other than the policy body verifies for every later policy on that agent; a rogue Policy Authority reuses it Both signatures cover the same body (Section 3.1); a signature is specific to one policy
Replayed policy A superseded but validly signed policy is presented as current Version is inside the preimage and must exceed the version in force (Section 11.4)
Swapped template A valid certificate is presented beside a template granting authority the CA never issued Static fields live in the certificate (Section 8.2); there is no separate template to swap
Forged parent A child names whichever parent gives it the widest scope; containment is evaluated against that parent The parent link is in the child's certificate, attested by the CA (Section 10.5)
Mismatched identity A chain names one agent and presents a certificate issued to another; both validate on their own terms Every restatement must equal the subject CN (Section 7.2)
Silent parser disagreement Two parsers keep different duplicates of a key and both report success Duplicate detection is a parser requirement (Section 3)
Unlocatable revocation Revocation must be consulted but the certificate does not say where cRLDistributionPoints or OCSP is required (Section 14.4)
Spawn under a revoked grant A grant is revoked and nothing identifies the certificates issued under it grant_id in the Agent Spawn extension; the issuing Registry revokes them (Section 13.4)
Spawn the policy withdrew A policy grants no spawn targets and the agent spawns everything its certificate's CanSpawn allows SpawnTargets is a step of the spawn sequence (Section 10.2)

12. Template Versioning

12.1. Full Re-Verification Required

A new template version MUST undergo full re-verification from scratch. Trust MUST NOT be inherited from a previous version.

Rationale: inheriting trust from v1 would allow a compromised v1 certificate to bootstrap trust for v2.

A new version keeps the template's Subject and receives a new certificate. The Registry MUST revoke the prior certificate when it issues the new one, so that one identity never has two valid certificates; a relying party that encounters two unrevoked certificates for one Subject MUST refuse both.

12.2. Versioning Principle

Everything on the old template chain continues to work unchanged as long as the certificate is valid. New connections and functionality are opt-in -- only available after the new template chain is fully verified and explicitly adopted.

12.3. Non-Inheritance Rules

The following MUST NOT be inherited from a previous version:

  • Trust chain
  • Cross-organizational grants
  • CanSpawn list
  • Dynamic policies

12.4. Template Lifecycle

ACTIVE:
Template is trusted. New spawns accepted.
DISABLED:
No new spawns. Existing agents run to TTL expiry. Reversible.
DELETED:
Certificate revoked, CRL updated, registry entry removed. Irreversible. Audit log preserved.

DISABLED is a Registry state, not a revocation. It is reported by the Registry in Check 2 of Section 10.1 and is not carried in a CRL. Because only the Registry performs spawns, no other party needs to distinguish DISABLED from ACTIVE: a relying party validating an existing agent's certificate consults revocation state as usual, and an agent issued under a template that is later DISABLED remains valid until its TTL or its revocation.

Disable SHOULD precede delete. Implementations SHOULD enforce a mandatory waiting period between DISABLED and DELETED.

12.5. Cross-Organizational Grant Re-Issuance

Cross-organizational grants MUST be explicitly re-issued for each new template version. Grants MUST NOT automatically roll over on version upgrade.

13. Cross-Organizational Agent Interaction

13.1. Explicit Grant Requirement

Cross-organizational agent spawning MUST be explicitly authorized by the resource-owning organization. No implicit trust exists between organizations.

13.2. Grant Structure

A cross-organizational grant MUST contain exactly the following fields:

Table 11: Cross-Organizational Grant Fields
Field Type Description
GrantID string Identifier of this grant: a UUID in the form of Section 7.2, unique among the grants the Grantor has issued
Grantor string OrgID of the resource-owning organization
Grantee string OrgID of the requesting organization
Template string Subject of the template granted, in the form of Section 7.2
AllowedScopes array of string MUST be a subset of the template's AllowedScopes
IssuedAt string Instant of issuance, per [RFC3339], in UTC
TTL integer Grant validity period in seconds, counted from IssuedAt
MaxSpawns integer Maximum concurrent agents permitted under this grant

Wire names are given in Table 3. A grant is signed as specified in Section 3.1, by the grantor's Owner and Policy Authority; the signatures are envelope members and are not fields of the grant.

A grant expires at IssuedAt plus TTL seconds. A relying party MUST refuse a grant whose expiry has passed, and MUST refuse one whose IssuedAt is later than its own clock by more than the freshness window of Section 19.2. A duration with no stated origin has no expiry two parties can agree on; IssuedAt is the origin.

A cross-organizational spawn is evaluated and issued by the Grantor's Registry, which owns the template and the CA that issues against it. That Registry holds the count compared against MaxSpawns and MUST enforce it atomically with recording the spawn, exactly as Section 10.2 requires of MaxChildren. The Grantee's organization performs no part of the issuance and cannot enforce the cap.

13.3. Trust Anchor Options

Federated CA:
Both organizations trust a shared root CA.
Explicit CA trust:
Org-B explicitly trusts Org-A's CA.
Third-party CA:
Both organizations use a public CA.

Which option applies is deployment policy. Under each, a relying party in the Grantee organization MUST hold a trust anchor for the Grantor's Template Registry CA and MUST validate the Grantor's Owner and Policy Authority certificates to it, as Section 9.2 requires, before accepting a grant's signatures. A grant whose signatures cannot be validated to a trust anchor the relying party holds MUST be refused.

13.4. Unilateral Revocation

The granting organization MAY revoke a cross-organizational grant without the cooperation of the receiving organization. Upon revocation, all agents spawned under the affected grant MUST be treated as untrusted on next validation. The Grantor's Registry issued every such certificate, and each carries the grant's GrantID in its Agent Spawn extension (Section 10.5). On revoking a grant the Registry MUST revoke, under Section 14, every unexpired certificate whose grant_id names it, and MUST refuse further spawn requests under it. A relying party in either organization then learns of the revocation through the revocation state the certificate itself points to (Section 14.4), and needs no channel to the Grantor beyond that.

13.5. Federated Audit

Each organization MUST maintain its own independent audit trail. Audit records MUST NOT depend on the other organization's systems.

14. Revocation

14.1. Template Revocation

Template revocation MUST be performed by recording the template certificate as revoked in the CA's revocation state -- an X.509 CRL, an OCSP responder, or an equivalent revocation registry consulted on every validation. All agent certificates derived from a revoked template MUST be treated as untrusted on the next revocation check.

14.2. Individual Agent Revocation

Individual agents MAY be revoked by explicit certificate revocation or, outside this document, by removal of authorization relationships at the resource layer.

14.3. Automation Requirement

Routine revocation (TTL expiry, task completion) MUST be fully automated. Human involvement SHOULD be reserved for incident response and high-impact decisions.

14.4. Locating Revocation State

Every certificate issued under this specification, other than a self-signed trust anchor, MUST carry either the cRLDistributionPoints extension or the authorityInfoAccess extension with an id-ad-ocsp accessMethod, both as defined in [RFC5280]. A relying party MUST refuse a certificate carrying neither, because the obligation in Section 14.1 to consult revocation state on every validation cannot be discharged against a certificate that does not say where that state lives.

A relying party MUST NOT treat an unreachable revocation source as an absence of revocation. This restates Section 15.1 and is stated again here because it is the requirement implementations most often relax under operational pressure.

15. Failure Model

15.1. Fail Closed

Any verification step that cannot be completed MUST result in DENY. This includes:

  • CA unreachable
  • Registry unreachable
  • CRL unreachable
  • Certificate expired or revoked
  • Policy store unreachable, or no policy in force
  • Scope escalation attempt
  • Policy invalid or unsigned
  • Dual signature missing or invalid

Implementations MUST NOT provide a degraded mode that allows partial spawning or execution when verification infrastructure is unavailable.

16. Conformance Requirements

16.1. Field Placement

Implementations MUST place every field in the location specified by this document: Section 3, Section 8.2, Section 10.5, Section 11.4, Section 13.2, and Section 10.4. Variable placement is not permitted.

16.2. CSR Validation

Non-conforming CSRs MUST be rejected by the CA. A non-conforming template MUST NOT be signed.

16.3. Test Vectors

Implementations MUST provide test vectors -- concrete examples of valid and invalid template chains -- for conformance validation.

16.4. Conformance Claims

No conformance certification authority exists for this document. An implementation claiming conformance MUST state the revision it claims, as Section 18 describes, and SHOULD publish the results of running the test vectors of Section 16.3 against that revision. A claim without a stated revision is not a conformance claim.

16.5. Reference Implementation

A reference implementation SHOULD be made available including:

  • Template Registry CA
  • Spawn chain validation
  • SDK with certificate chain validation, registry lookup, and CRL check handling
  • Template linter for pre-submission CSR validation

Known implementations are listed in Section 18.

17. IANA Considerations

17.1. Object Identifier

The Agent Template extension of Section 8.2 and the Agent Spawn extension of Section 10.5 each use an object identifier under the joint-iso-itu-t UUID arc (2.25), which is self-assigning from a UUID and requires no registration. This document requests no allocation from any IANA-managed OID arc. Should this document be adopted, the author is willing to replace them with OIDs under an arc the responsible working group prefers.

17.2. Media Type Registration

IANA is requested to register the following media type in the "Media Types" registry, per [RFC6838].

Type name:
application
Subtype name:
a2a-policy+json
Required parameters:
N/A
Optional parameters:
N/A
Encoding considerations:
binary; JSON is UTF-8 encoded and serialized per [RFC8785]
Security considerations:
See Section 19 of this document.
Interoperability considerations:
N/A
Published specification:
This document
Applications that use this media type:
Multi-agent systems exchanging dynamic policy documents.
Fragment identifier considerations:
N/A
Additional information:
N/A
Person and email address to contact for further information:
Tony Trujillo, founder@phalanxaisec.com
Intended usage:
COMMON
Restrictions on usage:
None
Author:
Tony Trujillo
Change controller:
IETF

17.3. Agent Scope Registry

IANA is requested to create a registry titled "A2A Agent Scopes", with a registration policy of Specification Required [RFC8126]. Each entry carries a scope name, a description, and a reference. The registry is initially empty; scope names not registered here are private to a deployment and MUST NOT be assumed to carry the same meaning across organizational boundaries.

18. Implementation Status

This section records the status of known implementations of the protocol defined by this specification at the time of posting, as described in [RFC7942]. It is meant to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist.

According to [RFC7942], "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit."

This section is to be removed before publishing as an RFC.

Three independent implementations exist at the time of writing. Each states the revision it was written and verified against, and continues to state that revision until someone re-reads the newer text and re-runs the vectors. An implementation pinned to an earlier revision remains a correct implementation of that revision; a version string is a conformance claim rather than a label, and advancing one without re-verifying asserts conformance nobody has tested. Each is tagged in its repository at the commit implementing the revision named here.

Table 12: Known Implementations
Implementation Revision Notes
a2a-trust-playground -03 Browser implementation, no installation or backend. Mints a Registry, attests and issues templates, and validates a chain against every check in this document, reporting the clause governing each refusal. Tagged impl/draft-03; the implementation of -02 remains retrievable at tag impl/draft-02. Source: https://github.com/tonyt68/a2a-trust-playground
ietf-a2a-trust-poc -00 Registry CA, spawn validation and policy governance services. Tagged impl/draft-00. Source: https://github.com/tonyt68/ietf-a2a-trust-poc
hack-my-own-code -00 Adversarial implementation that attacks its own conformance. Canonicalizes with a language-specific JSON serialization rather than the scheme required by Section 11.5, so it does not conform to that section. Tagged impl/draft-00. Source: https://github.com/tonyt68/hack-my-own-code

All three are maintained by the author of this document. They are independent in the sense that they share no code and were written against the specification text rather than against each other; they are not independent in the sense [RFC7942] most values, and a reviewer should weigh them accordingly. An implementation by an unrelated party would be more informative than all three, and is actively sought.

19. Security Considerations

19.1. Scope Escalation

Implementations MUST enforce at every hop that child agent scopes are a subset of parent scopes: child scopes are contained within parent scopes, and no scope may be introduced that the parent does not already hold. Failure to enforce this allows privilege escalation across the agent chain.

19.2. Replay Attacks

A spawn request MUST carry a timestamp and a nonce, both generated by the spawning agent. The timestamp MUST be an [RFC3339] instant in UTC. The nonce MUST be at least 128 bits of output from a cryptographically secure random number generator, encoded as base64 [RFC4648]. The nonce and timestamp of an accepted request are recorded in the child's Agent Spawn extension (Section 10.5); those of every request, accepted or refused, are recorded in the audit log entry of Section 10.4.

The Registry is the relying party for a spawn request. It MUST record the nonce when the request carrying it is received, before any step of Section 10.2 is evaluated, and MUST refuse a later request carrying the same nonce whatever became of the first. A nonce is spent by being presented, not by being accepted: a request refused at any step has consumed its nonce, and a retry MUST carry a fresh one. Recording only accepted nonces would let a refused request be replayed until something changed and it was accepted, and a fresh nonce costs nothing to generate.

A relying party MUST refuse a spawn request whose timestamp is more than 60 seconds from the relying party's own clock in either direction, and MUST refuse a request whose nonce it has already seen within that window. A relying party MUST retain seen nonces for at least twice the freshness window. Retaining them for exactly the window leaves a request replayable at the boundary, when the record has been discarded but the timestamp is still inside the window at the receiver.

The window is specified rather than left to the deployment because a value chosen independently at each end is not a shared window, and the wider of the two is the one an attacker gets. Accepting a request from the future by the same margin accommodates clock skew; an implementation that accepts only past timestamps will reject legitimate requests from a peer whose clock is marginally ahead. The window assumes clocks synchronized to within a small fraction of it. An operator whose clocks cannot meet that assumption MUST treat it as a failure condition under Section 15.1 rather than widen the window; a wider window is a longer replay opportunity for every party, not a fix for one party's clock.

Sixty seconds tolerates the skew of any correctly administered clock -- NTP holds hosts within milliseconds -- and bounds the nonce retention obligation of a Registry to two minutes. It is deliberately tighter than the five minutes Kerberos [RFC4120] adopted: that tolerance was sized for human-operated hosts with unsynchronized clocks, and a spawn request is a sub-second exchange between machines. A window sized for the former is a longer replay opportunity than the latter needs, and a peer whose clock is more than a minute wrong is not a peer to be accommodated.

19.3. Compromised Templates

A compromised template certificate MUST be revoked immediately. A single CRL update invalidates all downstream agent certificates derived from that template.

19.4. Single Point of Compromise

The dual signature requirement (Section 11.3) ensures no single compromised party can push unauthorized policy changes. CA compromise requires full ecosystem re-issuance.

Compromise of an Owner or Policy Authority key is handled by revoking its certificate under Section 14. Policies and templates signed under the compromised key MUST be re-signed under replacement keys, because a relying party cannot distinguish a signature made before the compromise from one made after it; a revoked signing certificate invalidates every signature it ever produced, not only the fraudulent ones.

19.5. Cross-Organizational Trust

Cross-organizational grants MUST be explicitly issued. Implicit trust between organizations is prohibited.

19.6. PKI Does Not Enforce Authorization

Because agent identity is carried in X.509 certificates and the chain is verified on every validation, it is natural to assume the certificate chain also constrains what an agent may do. It does not, and an implementation built on that assumption is unprotected while appearing rigorous.

X.509 carries no representation of the scopes defined by this document. AllowedScopes, CanSpawn and MaxChildren are conveyed in the template, and no certificate path validation algorithm inspects them. A conformant X.509 validator presented with an agent certificate whose associated template claims scopes far beyond those its parent holds will report success, because the certificate is genuinely valid and correctly issued. The over-scoping is not a defect the validator is looking for.

The nameConstraints extension does not close this gap. It constrains the namespace within which a CA may issue, not the authority a subject may claim once issued. Likewise certificatePolicies expresses which policies a chain supports, not whether a child exceeded its parent, and policy processing is disabled by default in common implementations.

Consequently Section 8.3 and Section 10.3 are load-bearing implementation logic. They are not restatements of a property the certificate chain already guarantees, and an implementation that omits them because "the chain verifies" has no containment at all. Certificate validity establishes identity. Authorization is evaluated separately, every time.

19.7. Audit Integrity

Audit logs MUST be tamper-evident. Logs MUST NOT be deletable by agents or orchestrators. Audit log infrastructure SHOULD be outside the control of the agent ecosystem itself.

Each entry's hash MUST be computed as SHA-256, or a stronger digest, over the canonical form (Section 11.5) of every member of Table 6 other than entry_hash -- that is, including previous_hash and excluding the entry's own hash. As with policy documents, an unspecified preimage is not a detail: two implementations hashing different field sets each read the other's chain as broken, and a chain that cannot be verified across implementations provides no evidence to anyone but its author.

19.8. Privacy Considerations

The Owner member of a template is carried inside a certificate that is presented to every relying party the agent ever contacts. An Owner value that identifies a person -- an email address, as the examples in this document use for readability -- is therefore personal data disclosed to every counterparty. Deployments SHOULD populate Owner with an identifier that is opaque outside the owning organization, and resolve it to a person only within that organization.

A version 7 agent identifier discloses the agent's creation time to every party that sees the identifier, as Section 7.2 describes. Audit records required by Section 10.4 carry agent identifiers and scopes, and Section 13.5 places one such record in each organization party to a cross-organizational spawn; the OrgID of each is disclosed to the other by the grant itself.

19.9. Algorithm Agility

The signature algorithms of Table 2 and the key strength floor of Section 7.1 are classical. This document does not specify a post-quantum signature algorithm, because no X.509 profile for one had reached the stability this document requires at the time of writing. The per-key-type mapping is the extension point: a future revision adds a row for a post-quantum key type without changing the envelope or any other structure, and a relying party that does not recognize a key type refuses the signature, which is the fail-closed outcome Section 15.1 requires.

19.10. Parsing Untrusted Input

Every document this specification defines reaches a relying party from the party whose authority it describes, and is attacker-controlled input until a signature over it has been verified. Section 8.2 states this for the two certificate extensions; it applies equally to a signature envelope, a chain document, and a grant. Three rules of this document exist for that reason and are restated here so that they are read as one defence. The shape rules of Section 3 -- flat objects, no duplicate members, exact wire names, a fixed member set -- mean a conforming parser accepts only the shapes this document defines and has nothing else to be confused by. The size limits of Section 8.2 bound what a parser is asked to read. And the ordering that section requires -- for a certificate, verify the issuer's signature before decoding an extension; for an envelope, verify the signatures over the body octets before acting on any member of body -- means input nobody signed is discarded before it is interpreted. A relying party that parses first and verifies afterwards has exposed its parser to every party able to present a certificate, which is every party.

20. References

20.1. Normative References

[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8032]
Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, , <https://www.rfc-editor.org/info/rfc8032>.
[RFC8410]
Josefsson, S. and J. Schaad, "Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 for Use in the Internet X.509 Public Key Infrastructure", RFC 8410, , <https://www.rfc-editor.org/info/rfc8410>.
[RFC8785]
Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, , <https://www.rfc-editor.org/info/rfc8785>.
[SP800-57]
Barker, E., "Recommendation for Key Management: Part 1 - General", NIST SP 800-57 Part 1 Rev. 5, , <https://doi.org/10.6028/NIST.SP.800-57pt1r5>.
[RFC5280]
Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, , <https://www.rfc-editor.org/info/rfc5280>.
[RFC3339]
Klyne, G. and C. Newman, "Date and Time on the Internet: Timestamps", RFC 3339, , <https://www.rfc-editor.org/info/rfc3339>.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, , <https://www.rfc-editor.org/info/rfc4648>.
[RFC6838]
Freed, N., Klensin, J., and T. Hansen, "Media Type Specifications and Registration Procedures", BCP 13, RFC 6838, , <https://www.rfc-editor.org/info/rfc6838>.
[RFC8126]
Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, , <https://www.rfc-editor.org/info/rfc8126>.
[RFC9562]
Davis, K., Peabody, B., and P. Leach, "Universally Unique IDentifiers (UUIDs)", RFC 9562, , <https://www.rfc-editor.org/info/rfc9562>.

20.2. Informative References

[RFC4120]
Neuman, C., Yu, T., Hartman, S., and K. Raeburn, "The Kerberos Network Authentication Service (V5)", RFC 4120, , <https://www.rfc-editor.org/info/rfc4120>.
[RFC7942]
Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, , <https://www.rfc-editor.org/info/rfc7942>.
[RFC6749]
Hardt, D., "The OAuth 2.0 Authorization Framework", RFC 6749, , <https://www.rfc-editor.org/info/rfc6749>.
[RFC8693]
Jones, M., Campbell, A., and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, , <https://www.rfc-editor.org/info/rfc8693>.
[NIST800-207]
Rose, S., Borchert, O., Mitchell, S., and S. Connelly, "Zero Trust Architecture", NIST SP 800-207, .
[SPIFFE]
SPIFFE Project, "Secure Production Identity Framework for Everyone", <https://spiffe.io>.
[OpenFGA]
OpenFGA Project, "OpenFGA Specification", <https://openfga.dev>.
[VAULTPKI]
HashiCorp, "Vault PKI Secrets Engine", <https://developer.hashicorp.com/vault/docs/secrets/pki>.

Appendix A. Changes since draft-tonyai-a2a-trust-02

As with the previous revision, every change here was surfaced by implementing the -02 text rather than by re-reading it. Three implementations of one specification produced three different answers to the same questions, which is what the changes below exist to prevent.

Appendix B. Changes since draft-tonyai-a2a-trust-01

Section numbers in this appendix are those of draft-tonyai-a2a-trust-02, the revision these changes produced. Several sections were renumbered in -03; see Appendix A.

All changes in this revision were surfaced by building a second, independent implementation of the -01 text and attacking it. Changes are described below by their effect on a conformant implementation rather than by intent: where an implementation conforming to -01 must change to remain conformant, this is stated plainly, because an implementer reading this appendix is deciding whether re-verification is required.

Four changes below are breaking. Two implementations exist at the time of writing, both under the author's control; the cost of these changes is at its minimum now and rises permanently once a third-party implementation ships.

Security fix -- breaking.

Interoperability -- breaking.

New normative requirements -- additive.

Rename -- breaking.

Removal -- breaking for any implementation reading the field.

Non-normative.

Appendix C. Changes since draft-tonyai-a2a-trust-00

Section numbers in this appendix are those of draft-tonyai-a2a-trust-01, the revision these changes produced.

Clarified two areas identified as ambiguous during development of a reference implementation:

Neither change alters the normative requirements themselves; both make explicit what the -00 text intended. Both were surfaced by building and red-teaming a conformance reference implementation against the -00 text.

Author's Address

Tony Trujillo (tonyai)
Individual Submission