RFC-AITP-0001

RFC-AITP-0001

Agent Identity & Trust Protocol (AITP) — Core

Document: RFC-AITP-0001 Version: 0.1.0-rc.3 Status: Community Standards Track (Release Candidate) Canonical wire format: JSON Normative transport: HTTPS (any HTTP/1.1+ runtime) Canonical signing input: RFC 8785 (JCS) canonical JSON Intended status: Stable Core

This is an RFC-style open standard. It is not an IETF RFC.


Abstract

The Agent Identity & Trust Protocol (AITP) is an agent-to-agent (A2A) trust protocol. Its purpose is to let two autonomous agents — running in different organizations, behind different identity providers, with no pre-configured shared verifier — establish bidirectional trust before they exchange any binding work.

AITP introduces one strict invariant:

Trust between two agents MUST be expressed as a pair of signed, audience-bound, capability-scoped Trust Context Tokens (TCTs) produced by a Mutual Handshake.

There is no central verifier. Each agent is its own verifier for the peer it is authenticating. The output of the handshake is a TCT each peer holds about the other. A TCT is verified locally — its signature is checked against the issuing peer's public key, resolved from the peer's signed Agent Manifest.

AITP Core does not define decision theory, reputation models, identity issuance, authorization semantics inside a peer, or domain logic. AITP Core defines structure: the message envelope, replay protection, signature semantics, message types, transport requirements, canonical JSON mapping, error codes, and the registry hooks the rest of the spec depends on.


1. Status of This Memo

This document is Draft Standards Track. Implementations MAY adopt it experimentally. Backward-incompatible changes remain possible until Final status.

This is the first published version of AITP. The numbering scheme treats aitp/0.1 as the inaugural A2A protocol.


2. Conventions and Terminology

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.

TermDefinition
AgentAny software entity that emits or receives AITP envelopes. Every AITP agent has an AID and publishes an Agent Manifest.
AIDAgent ID — a cryptographic identifier of the form aid:<method>:<identifier>.
PeerThe other agent in a bilateral AITP exchange. Roles are symmetric.
Initiating Peer / Target PeerRole labels for one round of the Mutual Handshake. The initiator sends mutual_hello; the target responds. Either peer may initiate.
Issuing PeerThe peer that signed a particular TCT. Equivalent to the TCT issuer AID.
Subject PeerThe peer the TCT was issued for. Equivalent to the TCT subject and audience AIDs.
TCTTrust Context Token — the signed output of a Mutual Handshake. Each side of a successful handshake holds a TCT issued by the other.
Trust AnchorA locally configured trusted issuer (e.g. an OIDC provider) and its public keys, used to verify a peer's identity binding.
Identity BindingA verifiable claim binding an AID to a trusted issuer's subject. See RFC-AITP-0002.
ManifestAn agent's signed self-description. Defined in RFC-AITP-0003.

3. Scope and Design Goals

AITP exists to make A2A trust establishment explicit, auditable, and stateless on the consumer side. It provides:

  1. an explicit, signed message envelope with replay protection;
  2. a pluggable identity-binding model (RFC-AITP-0002);
  3. a signed Agent Manifest for peer discovery (RFC-AITP-0003);
  4. a Mutual Handshake that produces peer-issued TCTs (RFC-AITP-0004);
  5. an audience-bound, capability-scoped Trust Context Token (RFC-AITP-0005);
  6. a stateless single-hop delegation model (RFC-AITP-0006);
  7. transport independence through a canonical envelope;
  8. a defined error and revocation surface;
  9. registry hooks for identity types, capabilities, and error codes.

AITP does not define:

  • identity issuance — that lives in OIDC providers, DID methods, etc.;
  • reputation algorithms;
  • authorization semantics inside a peer (what the peer does with grants);
  • a third-party verifier or trust authority;
  • audit-logging requirements;
  • service-consumer flows. AITP is peer-to-peer.

4. Architecture

┌─────────────────────────────────────────────────────────┐
│                     Agent A                             │
│   (identity, AID, signed Manifest, accepted anchors)    │
└──────────────────────────┬──────────────────────────────┘

              Mutual Handshake (RFC-0004)

                          ▼ ▲
                          ▲ ▼

                  TCT_B (A → B)   TCT_A (B → A)

┌──────────────────────────┴──────────────────────────────┐
│                     Agent B                             │
│   (identity, AID, signed Manifest, accepted anchors)    │
└─────────────────────────────────────────────────────────┘

Each agent's responsibilities are symmetric:

  • Publish a signed Manifest at /.well-known/aitp-manifest.
  • Verify peers' Manifests, identity proofs, and proof-of-possession.
  • Issue a peer-issued TCT for the peer when policy allows.
  • Verify the peer's TCT against the peer's Manifest public key.
  • Maintain a local JTI deny list for TCTs it has issued.
  • Honor its own offered_capabilities when granting; honor its own required_peer_capabilities when accepting.

Trust verification is stateless and local. To check a TCT presented by a peer, an agent needs only: (a) the peer's Manifest public key, (b) its own AID, and (c) the current time. No third-party call, no central registry.

This applies to TCT signature, expiry, audience, grant, and PoP validation. Revocation status is pull-based — checking whether a jti is revoked requires consulting the issuing peer's deny list (RFC-AITP-0008), which may involve a network call.


5. Message Envelope

Every AITP protocol message — mutual_hello, mutual_hello_ack, mutual_commit, mutual_commit_ack, tct, pop_challenge, pop_response, error — is wrapped in a standard envelope. (pop_challenge and pop_response are introduced by RFC-AITP-0005 §6.1 and are part of v0.1 conformance for any peer that issues TCTs.)

5.1 Schema

{
  "version": "aitp/0.1",
  "message_type": "<string>",
  "message_id": "<uuid-v4>",
  "timestamp": 1711900000,
  "sender": {
    "agent_id": "aid:pubkey:<base64url>"
  },
  "payload": {},
  "signature": "<base64url>"
}

5.2 Fields

FieldTypeRequiredDescription
versionstringREQUIREDMUST be "aitp/0.1" for this RFC.
message_typestringREQUIREDOne of: mutual_hello, mutual_hello_ack, mutual_commit, mutual_commit_ack, tct, pop_challenge, pop_response, error.
message_idstringREQUIREDUUID v4, hyphenated lowercase.
timestampintegerREQUIREDUnix timestamp (seconds).
sender.agent_idstringREQUIREDAID of the sending agent.
payloadobjectREQUIREDMessage-type-specific content.
signaturestringREQUIREDbase64url-encoded envelope signature.

The canonical schema is the JSON Schema at schemas/json/aitp-envelope.schema.json.

5.3 Agent ID (AID)

An AID is a stable, cryptographic identifier derived from a public key:

aid:<method>:<identifier>

v0.2 supported methods:

MethodFormatExample
pubkey (legacy, Ed25519)unpadded base64url of the 32-byte raw Ed25519 public key (43 chars)aid:pubkey:11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo
pubkey:ed25519 (algorithm-tagged)unpadded base64url of the 32-byte raw Ed25519 public key (43 chars)aid:pubkey:ed25519:11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo
pubkey:p256unpadded base64url of the 33-byte SEC1 compressed P-256 public key (44 chars)aid:pubkey:p256:A8XBp7TBpRl6Q1QXZqXxZcGo1bRCw9KkV-Mn8eqXC8GE

v0.2 introduces the algorithm-tagged grammar aid:pubkey:<algorithm>:<identifier> while preserving the legacy v0.1 form aid:pubkey:<43-char-identifier> (which implicitly means Ed25519). The legacy form is accepted indefinitely for interop — implementations MUST parse both. New AIDs published under the v0.2 profile SHOULD use the algorithm-tagged form. The legacy form is canonically equivalent to aid:pubkey:ed25519:<same-identifier> for trust decisions; the two forms are NOT byte-equal in canonical signing bytes, so issuers MUST publish each AID in exactly one form for the duration of its lifetime.

The algorithm tag, when present, is part of the AID identifier — verifiers MUST reject AIDs whose algorithm tag is not in the registered set above.

Implementations MUST NOT use SPKI DER encoding, PEM wrappers, or any other encoding for the identifier component. The unpadded base64url alphabet [A-Za-z0-9_-] is the only accepted character set. Identifier length is algorithm-specific:

  • ed25519 (and the legacy untagged form) — exactly 43 chars (32 raw bytes).
  • p256 — exactly 44 chars (33 raw bytes; SEC1 compressed point per SEC 1 §2.3.3).

Known-answer test. Pinned (seed → public key → AID) vectors live at schemas/conformance/known-answer/keypairs.json. For example, the all-zero 32-byte seed produces public key O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik and AID aid:pubkey:O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik. Implementations MUST reproduce these values byte-for-byte.

An AID is not trusted by itself. It MUST be bound to an identity via an Identity Binding before any trust decision is made. The relationship between an AID, its identity binding, and its Manifest is defined in RFC-AITP-0003.

5.4 Signature

The signature covers the canonical serialization of:

sig_input = message_id + "|" + timestamp_string + "|" + sender.agent_id + "|" + hex(sha256(payload_canonical_json))
signature = base64url(sign(sender_private_key, sha256(sig_input)))

The payload object MUST be canonicalized per RFC 8785 — JSON Canonicalization Scheme (JCS) before hashing. JCS specifies compact JSON with no whitespace, lexicographically sorted keys at every nesting level, ECMAScript-style number formatting, and well-defined Unicode handling. Implementations MUST NOT use ad-hoc canonicalization; cross-implementation signature interop depends on JCS.

All signature, pop_signature, cnf, proof, and the AID identifier component (aid:<method>:<identifier>) are encoded as unpadded base64url per RFC 4648 §5. Implementations MUST NOT emit = padding. Implementations SHOULD reject input that contains = padding; if they choose to accept it for compatibility with non-conformant senders, they MUST normalize to unpadded form before any signature verification.

For each algorithm the unpadded base64url encoding length is fixed; verifiers MUST reject any field whose encoded length differs from the algorithm's expected size:

FieldAlgorithmRaw bytesUnpadded base64url length
AID identifier — Ed25519ed255193243 chars
AID identifier — P-256p25633 (SEC1 compressed)44 chars
binding.cnf (TCT) and cnf (delegation)(matches AID alg)32 / 3343 / 44 chars
signature, pop_signature — Ed25519ed255196486 chars
signature, pop_signature — P-256 ECDSAp25664 (R||S, fixed-length)86 chars
pop_nonce, Manifest proof_of_possession.challenge(any)16 (128-bit nonce)22 chars

The canonical JSON Schemas under schemas/json/ carry these constraints as pattern regexes; implementations MUST validate against the schema before attempting cryptographic verification.

5.4.3 Algorithm-tagged signature wire format

Signature fields (envelope signature, manifest signature, TCT signature, delegation signature, revocation signature, PoP pop_signature, identity proof) MAY carry an algorithm tag prefix in v0.2:

<base64url-signature> := <86-char-b64url>                  (legacy v0.1, Ed25519 implicit)
                       | "ed25519." <86-char-b64url>       (v0.2 tagged, Ed25519)
                       | "p256." <86-char-b64url>          (v0.2 tagged, P-256)

The untagged 86-char form remains valid and is interpreted as ed25519 for backward compatibility with v0.1. The tagged form is an ASCII algorithm name (ed25519 or p256), a single period (.), then the unpadded base64url-encoded signature bytes. Verifiers MUST:

  1. Split on the first . to obtain the algorithm tag and signature bytes.
  2. Reject if the algorithm tag is not in the registered set, or if the encoded signature length doesn't match the algorithm's expected size.
  3. Reject if the algorithm tag does NOT match the signing AID's algorithm (e.g. an ed25519-AID signing with a p256. tagged signature). This prevents downgrade attacks where a P-256-only peer is tricked into accepting an Ed25519 signature labelled as P-256.

The algorithm tag is part of the canonical bytes that get hashed for outer signatures: changing the tag changes the bytes and therefore the hash. This binds the algorithm to the signed data.

Implementations MUST use one of:

AlgorithmIdentifierStatus
Ed25519 (RFC 8032)ed25519REQUIRED
ECDSA on P-256 with SHA-256p256REQUIRED

Both are mandatory in v0.2. A v0.2 peer MUST be able to verify both, even if it only signs with one. Manifests MAY advertise which algorithms a peer is willing to accept via the accepted_signature_algorithms field (RFC-AITP-0003 §3.2).

A verifier that encounters a signature whose algorithm tag it does not implement MUST reject with INVALID_SIGNATURE, never KEY_RESOLUTION_FAILED. "Algorithm not supported" is a signature-verification failure: the key may well be resolvable, but the signature cannot be checked. KEY_RESOLUTION_FAILED is reserved for the distinct case where the issuer or peer key itself cannot be resolved (RFC-AITP-0007). The distinction is load-bearing because KEY_RESOLUTION_FAILED is retryable (§5.7) while INVALID_SIGNATURE is not — reporting an unsupported-algorithm condition as KEY_RESOLUTION_FAILED would invite a caller to retry a request that can never succeed.

5.4.4 JWK thumbprint for cnf

The cnf field on TCTs and delegation tokens (RFC-AITP-0005, RFC-AITP-0006) MAY be one of:

  • Legacy v0.1 form (Ed25519-only) — the 32-byte raw Ed25519 public key, base64url-unpadded (43 chars).
  • v0.2 algorithm-agile form — RFC 7638 JWK thumbprint of the bound public key, base64url-unpadded SHA-256 over the canonical JWK JSON. Algorithm-agnostic: a P-256 cnf is computed from the JWK {"crv":"P-256","kty":"EC","x":"…","y":"…"} shape, an Ed25519 cnf from {"crv":"Ed25519","kty":"OKP","x":"…"}.

Verifiers MUST accept both forms during the v0.2 transition. New issuers SHOULD prefer the JWK thumbprint form because it survives key encoding changes (raw → SEC1 → JWK x-coordinate, etc.) and because it's the only form that works for non-Ed25519 keys.

To distinguish the two forms, verifiers compare the cnf string length: 43 chars matches the legacy raw-pubkey form (and is then interpreted as Ed25519); 43 chars MUST also be tried as a JWK thumbprint when the bound key isn't Ed25519. Implementations SHOULD log a deprecation warning when accepting the legacy form, and SHOULD reject it once a deployment migration window has closed.

5.4.1 Signing input

All AITP v0.1 signatures (envelope, Manifest, TCT, delegation token, revocation snapshot) are computed over the canonical JSON form of the object per RFC 8785 (JCS). JSON is the only canonical form in v0.1: there is no Protobuf signing input, no CBOR signing input, no transport-specific signing input.

Implementations MAY transport AITP messages over any binary or text frame (raw JSON over HTTP, JSON inside a gRPC bytes field, MessagePack, CBOR, etc.) but MUST convert to canonical JSON before signing or verifying. Non-JSON transports are not part of the v0.1 conformance profile; their use is a deployment choice that does not affect the trust contract.

A signed object that round-trips through any transport MUST produce identical canonical JSON when verified. If a transport adds wrappers or renames fields, the implementation MUST strip them before reconstructing the canonical form.

URL canonicalization. String fields holding URLs (e.g. accepted_trust_anchors, handshake_endpoint, identity_hint.issuer) are signed as the verbatim wire string — NOT the RFC 3986 §6 canonical form. An implementation that deserializes such fields into a typed URL value (which normalizes trailing slashes, lowercases the scheme, etc.) MUST preserve the original byte form for re-serialization, or it will compute a different signing input than the issuer did. Implementations SHOULD model URL fields as opaque strings at the serde layer and validate URL syntax separately when transport-layer parsing is needed.

Optional-array round-trip. Optional array fields (e.g. accepted_identity_types, the extensions map) MUST preserve the absent-vs-explicit-empty distinction in canonical bytes. Implementations modeling such fields as Vec<T> with skip_serializing_if = "Vec::is_empty" collapse the two states and will diverge from issuers that wrote an explicit []. Use Option<Vec<T>> (or equivalent) so the signing view emits the same bytes the issuer signed.

Known-answer test. Pinned (object → JCS canonical bytes → SHA-256 digest) vectors for the four signed AITP artifacts (TCT, Manifest, delegation token, revocation snapshot) live at schemas/conformance/known-answer/jcs-sha256.json. Implementations MUST reproduce both the canonical byte sequence and the digest byte-for-byte. Mismatches typically indicate JCS sort-order, number-formatting, or Unicode-escaping bugs.

5.4.2 PoP signing input convention

All AITP v0.1 proof-of-possession signing inputs follow a single rule:

hash_input = sha256(base64url_decode(nonce_or_challenge))

The hash input is always the raw bytes obtained by base64url-decoding the nonce or challenge — never the ASCII bytes of the encoded form. The rule applies uniformly to:

  • Manifest PoPRFC-AITP-0003 §3 (proof_of_possession.challenge, 16 raw bytes / 22 base64url chars).
  • Handshake round-2 PoPRFC-AITP-0004 §3 (pop_nonce, 16 raw bytes / 22 base64url chars).
  • Downstream TCT PoPRFC-AITP-0005 §6.1 (nonce in the pop_challenge / pop_response exchange).
  • Pinned-key identity proof inputRFC-AITP-0002 §3.1 (via pop_nonce_decoded_bytes).

Implementations MUST hash the decoded bytes; hashing the ASCII form is non-conformant. An implementation that consistently hashes the encoded string will be internally self-consistent but will fail cross-implementation verification — this is the most common interop bug observed in early AITP implementations.

Known-answer test. A pinned PoP signing-input vector (kat-manifest-pop-001) lives at schemas/conformance/known-answer/jcs-sha256.json. It pins (challenge → decoded bytes → SHA-256 digest → Ed25519 signature with kat-keypair-001). Implementations MUST add a KAT cross-check that runs the same input through every PoP code path and confirms each produces the pinned signature byte-for-byte.

5.5 Replay Protection

Verifiers MUST enforce both controls:

  1. Timestamp window. Reject envelopes where abs(now() - envelope.timestamp) > tolerance. Default tolerance: 300 seconds. Configurable per deployment.
  2. Message-ID deduplication. Maintain a deny list of seen message_id values for at least the timestamp tolerance window. Reject any envelope whose message_id appears in the deny list.

5.6 Error Envelope

An error envelope uses message_type: "error" and an AitpError payload:

{
  "code": "<error_code>",
  "reason": "<human-readable string>",
  "retryable": true
}

Verifiers MUST NOT reveal which specific policy check failed beyond the error code. reason strings are informational only and MUST NOT be used in automated decision-making.

5.7 Error Code Registry (envelope-level)

CodeMeaningRetryable
INVALID_ENVELOPEEnvelope failed schema validationfalse
INVALID_SIGNATURESignature verification failedfalse
REPLAY_DETECTEDDuplicate message_idfalse
TIMESTAMP_EXPIREDTimestamp outside tolerancetrue
UNKNOWN_VERSIONUnsupported protocol versionfalse
IDENTITY_FAILEDIdentity binding could not be verifiedfalse
POLICY_VIOLATIONRequested capability not grantedfalse
GRANT_OVERFLOWPeer-issued TCT grants exceed offered_capabilitiesfalse
INSUFFICIENT_GRANTSReceived TCT lacks a capability listed in own required_peer_capabilitiesfalse
KEY_RESOLUTION_FAILEDCould not resolve issuer or peer keystrue
MANIFEST_EXPIREDPeer's Manifest is past expires_atfalse
MANIFEST_SIGNATURE_INVALIDPeer's Manifest signature failedfalse
MANIFEST_POP_FAILEDPeer's Manifest proof-of-possession failedfalse
MANIFEST_VERSION_UNKNOWNPeer's Manifest version not supportedfalse
INCOMPATIBLE_TRUST_ANCHORSNo trust-anchor overlapfalse
POP_VERIFICATION_FAILEDMutual-handshake PoP signature failedfalse
POP_CHALLENGE_INVALIDDownstream pop_challenge envelope malformed, replayed, or expiredfalse
POP_RESPONSE_INVALIDDownstream pop_response envelope or pop_signature failed verificationfalse
NONCE_MISMATCHpop_nonce_echo did not match the sent noncefalse
AUDIENCE_MISMATCHTCT audience ≠ self AIDfalse

Mode-specific error codes are defined in their respective RFCs (mutual handshake in RFC-AITP-0004, delegation in RFC-AITP-0006). The full registry is maintained in registries/error-codes.md.


6. Capability Negotiation

Capability negotiation is part of the Mutual Handshake. Discovery-time screening (offered_capabilities and required_peer_capabilities on the Manifest) is normative in RFC-AITP-0003 §3; handshake-time grant intersection is normative in RFC-AITP-0004 §4. Capability string format and the registry of well-known prefixes are in registries/capabilities.md.

There is no separate "protocol capability" object in v0.1. Implementations either support the full mandatory protocol surface (envelope + manifest + mutual handshake + TCT) or they are not conformant.


7. Compatibility Model

AITP uses a layered compatibility model:

  • Protocol version governs envelope and base behavior (version field, e.g. aitp/0.1).
  • JSON Schema namespace governs canonical schema compatibility (the $id URIs under https://aitp.dev/schema/v0.1/).
  • TCT version governs the canonical token contract.
  • Manifest version governs the agent self-description format.

Major protocol version mismatches are not compatible. Minor versions are expected to be backward compatible. Verifiers receiving an unknown version MUST respond with UNKNOWN_VERSION.

Unknown JSON fields outside explicit extensions namespaces MUST be rejected. Signed AITP objects depend on canonical JCS representation; silently ignoring unknown fields would create signature ambiguity across implementations (one peer hashes the field in, another hashes it out, and the same wire bytes verify differently). Forward compatibility is provided exclusively through explicit extensions objects (see RFC-AITP-0012) — every signed object reserves an extensions slot, and unknown keys inside extensions MUST be ignored.


8. Transport

The normative transport for AITP v0.1 is HTTPS carrying canonical JSON. The endpoints normatively required of every conformant peer:

EndpointMethodPurposeDefined in
/.well-known/aitp-manifestGETFetch this peer's signed ManifestRFC-AITP-0003 §4
<handshake_endpoint>POSTReceive mutual_hello / mutual_commit envelopesRFC-AITP-0004

Other endpoints are deployment-defined in v0.1. TCT verification, delegation verification, and revocation list publication (RFC-AITP-0005 §10, RFC-AITP-0006, RFC-AITP-0008) are operational surfaces. Peers that expose them MAY advertise their URLs in the Manifest's extensions namespace (RFC-AITP-0012); v0.1 does not normatively pin those advertisement fields.

Request and response bodies are AITP envelopes serialized as JSON with Content-Type: application/json. The well-known Manifest endpoint and handshake_endpoint (advertised in the Manifest) are the only paths v0.1 normatively requires.

Implementations MAY transport AITP messages over other framings (binary RPC, message bus, etc.) but MUST convert to canonical JSON before signing or verifying (§5.4.1). v0.1 does not standardize any non-JSON binding.


9. Registry Hooks

AITP maintains four registries under registries/:

  • identity-types — registered values for IdentityDescriptor.type
  • capabilities — well-known capability strings
  • error-codes — protocol-level error codes (envelope, manifest, handshake, delegation)
  • media-types — content types used in transport bindings

New entries are added via the RFC process. Experimental identifiers SHOULD use reverse-domain notation.


10. Conformance

A conformant AITP v0.1 implementation MUST:

  1. Use the JSON wire format (§5.1) and the JCS signing input (§5.4.1). Non-JSON framings (binary RPC, CBOR, MessagePack, etc.) are not part of v0.1 conformance; using them is a deployment choice that does not satisfy v0.1 conformance on its own.
  2. Parse and verify the envelope as defined in §5.
  3. Verify identity bindings as defined in RFC-AITP-0002.
  4. Publish and consume Agent Manifests as defined in RFC-AITP-0003.
  5. Implement the Mutual Handshake defined in RFC-AITP-0004.
  6. Issue and verify peer-issued TCTs as defined in RFC-AITP-0005.
  7. Reject expired, mismatched-audience, or revoked TCTs.
  8. Reproduce the canonical-bytes and digest pins in schemas/conformance/known-answer/ byte-for-byte. The v0.1-mandatory KATs are: the four JCS canonicalization vectors (kat-tct-001, kat-manifest-001, kat-delegation-001, kat-revocation-001) and the unified PoP signing-input vector kat-manifest-pop-001. Implementations MUST run kat-manifest-pop-001 through every PoP code path (Manifest PoP, handshake PoP, downstream TCT PoP, pinned-key identity proof) and confirm each produces the pinned signature — see §5.4.2. Implementations that opt into the post-v0.1 RFCs MUST additionally reproduce kat-multihop-chain-001 and kat-multihop-truncation-001 (RFC-AITP-0011) and kat-session-bundle-001 (RFC-AITP-0010); v0.1-only implementations MAY skip those.
  9. Pass the conformance fixtures in schemas/conformance/. The v0.1 fixture surface is the env-*, man-*, mh-*, id-*, tct-*, del-*, and rev-* IDs. The del-mh-* and bundle-* fixtures are post-v0.1 (RFC-AITP-0010 / RFC-AITP-0011) — v0.1 implementations are expected to reject del-mh-* tokens with DELEGATION_MULTIHOP_NOT_SUPPORTED and to skip the bundle-* operations (SKIP rather than FAIL).

11. Security Considerations

See RFC-AITP-0009 Security for the full threat model. Implementations MUST use a cryptographically secure RNG for message_id and nonces, store private keys in secure storage, and validate all inputs against the JSON Schema before processing.


12. References