Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ The project defines a schema for a secure, extensible AI Catalog. This may inclu

* **Common catalog metadata**, such as publisher, documentation links, descriptions, icons, and versioning.
* **Verifiable metadata**, such as attestations, certifications, provenance, and trust signals.
* **Identity metadata**, such as Decentralized Identifiers (DID) or Secure Production Identity Framework For Everyone (SPIFFE).
* **Identity metadata**, including a `did:web` profile for authenticating artifact publishers.
* **Custom metadata** defined by individual producers or consumers for their own needs.

Actual properties for inclusion will be debated in PRs.
Expand Down
5 changes: 5 additions & 0 deletions adr/0015-agent-identifier-naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Accepted

**Participants:** Pamela Dingle (Microsoft), Sam Betts (Cisco), Junjie Bu (Google), Darrel Miller (Microsoft), Alan Blount (Google), Srinivas Krishnan (Google), Krishna Thota (Google), Tadas Antanavicius (Pulse MCP), Ramiz Polic (Cisco), Jeffrey Damick (Amazon)

**Later clarification:** [ADR-0027](0027-did-web-entry-signature-profile.md)
narrows the interoperable v1 signature profile to a root `did:web` issuer and
assigns runtime or workload identity to separate profiles. The logical-name and
cryptographic-issuer separation established here remains unchanged.

## Context
The `ai-catalog` specification originally recommended using URNs or URIs for the `identifier` field in catalog entries, but did not mandate a specific format. This led to inconsistency in examples and potential interoperability issues across different registries and orchestrators.

Expand Down
4 changes: 4 additions & 0 deletions adr/0020-substantive-trust-manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

**Participants:** Luca Muscariello (Cisco)

**Later clarification:** [ADR-0027](0027-did-web-entry-signature-profile.md)
supersedes this ADR's description of `identity` as a workload principal. The
manifest-validity rule established here remains unchanged.

## Context

The Trust Manifest is an OPTIONAL companion to a Catalog Entry. Within
Expand Down
130 changes: 130 additions & 0 deletions adr/0025-bind-signed-trust-manifests-to-releases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# ADR-0025: Bind Signed Trust Manifests to Artifact Releases

**Status:** Proposed

**Date:** 2026-09-03

## Context

A signed entry Trust Manifest currently binds the signer's claims to an
artifact's media type, content digest, and optionally its URL. The containing
Catalog Entry's `identifier` and `version` remain outside that signature.

ADR-0015 established that the two existing identity fields serve different
purposes. `entry.identifier` is the artifact's logical name in the catalog,
whereas `trustManifest.identity` is the cryptographic identity associated with
the Trust Manifest. They need not be the same URI; their domains need only
align.

The development work that later introduced `subject` temporarily required
those two fields to be exactly equal. Because `trustManifest.identity` is
inside the signed payload, that temporary equality rule also placed
`entry.identifier` under the signature. The accompanying security analysis
could therefore focus on the remaining problem: binding the signature to the
artifact's exact representation through its media type, digest, and optional
URL.

Review subsequently restored the domain-alignment rule from ADR-0015, but the
definition of `subject` remained representation-only. Once those two decisions
were combined, no field inside the signed payload was required to equal
`entry.identifier`. The artifact bytes were still protected, but their logical
catalog identifier was not.

Catalog Entries that share an `identifier` can represent different releases
using `version`. The resolution procedure compares those versions when
selecting the latest release or satisfying a version constraint. A present
`entry.version` can therefore determine which artifact a consumer receives,
even though it remains outside the Trust Manifest signature.

An attacker who can modify a catalog can retain a valid signed manifest and
its exact artifact bytes while changing only the entry's logical identifier or
version. For example, the attacker can label an old, vulnerable release as a
newer version. A consumer requesting the latest release, or requiring a
minimum version containing a security fix, can then receive the vulnerable
code while the signature, URL, media type, and digest all verify.

A top-level catalog signature detects changes to the catalog document, but it
authenticates a different statement. It establishes that the catalog signer
published a particular snapshot, including its identifiers and versions. An
entry Trust Manifest establishes that its signer made claims about a
particular artifact. When the catalog and Trust Manifest have different
signers, the catalog signature does not establish that the Trust Manifest
signer assigned those release coordinates. Conversely, an entry signature
does not protect the catalog's collection-wide structure. The two controls
provide complementary guarantees.

## Decision

For a signed Trust Manifest attached to a Catalog Entry, extend `subject` to
identify both the logical artifact release and its exact representation.

For a signed entry Trust Manifest:

- `subject.identifier` is REQUIRED in every Subject and MUST exactly equal
`entry.identifier` when the Subject appears on a Catalog Entry.
- `subject.version` is REQUIRED when `entry.version` is present and MUST
exactly equal it. When `entry.version` is absent, `subject.version` MAY be
present and no entry-version comparison is required.
- `subject.type` remains REQUIRED and MUST exactly equal `entry.type`.
- `subject.digest` remains REQUIRED and MUST match the artifact content.
- `subject.url` remains OPTIONAL. When present, it MUST exactly equal
`entry.url`.

Consumers MUST perform the entry-to-subject comparisons in addition to
verifying the signature, anchoring its identity, and checking the artifact
digest. A signature over a mismatched subject does not authenticate the
containing entry.

Catalog-level integrity remains complementary. Per-entry signatures cannot
detect removal of a valid entry, injection of unrelated entries, or
reordering. A catalog signature or trusted content-addressed distribution can
protect the catalog snapshot as a whole. Neither an entry signature nor a
catalog signature alone prevents replay of an older, correctly signed value.
A consumer that must prevent rollback needs either a trusted source of current
release information or local state recording the newest release it has already
accepted.

The release-coordinate comparison rules in this decision are limited to signed
Trust Manifests attached to Catalog Entries. Requiring every Subject to include
an `identifier` does not define what the Subject of a signed Host Trust Manifest
represents. This decision also does not change the meaning of `identity` or
define how an identity resolves to an authorized signing key. Those concerns
require separate decisions.

The specification's CDDL is updated to represent `subject`, `issuedAt`, and
`expiresAt`, which were already defined in the normative prose but missing from
the machine-readable data model.

## Consequences

- A valid signed manifest and artifact cannot be transplanted to another
logical identifier or relabeled as another version without detection.
- The same signed manifest remains usable in catalogs that omit the optional
entry `version`; when a catalog supplies a version, it must agree with the
signed subject.
- Mirrors remain possible because `subject.url` stays optional.
- Catalog signatures continue to protect collection-level decisions and may
be made by a different principal than the Trust Manifest signer.
- Signing the release coordinates does not by itself prevent rollback to an
older, correctly labelled and validly signed release. Consumers still need a
trusted source of current release information or a record of the newest
release they have already accepted.

## Alternatives Considered

### Rely only on catalog-level integrity

Rejected as the sole mitigation. It protects the catalog operator's snapshot,
but does not establish that the Trust Manifest signer made claims about the
listed identifier and version. It also couples that claim to one catalog.

### Bind only the artifact digest

Rejected. It proves which bytes were endorsed but permits those exact bytes and
claims to be relabeled under another logical artifact or release coordinate.

### Require `subject.url`

Rejected. Location binding would prevent mirrors and does not substitute for a
stable logical identifier. Publishers may opt into location binding by
including the existing optional field.
190 changes: 190 additions & 0 deletions adr/0027-did-web-entry-signature-profile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# ADR-0027: Define a `did:web` Signature Profile for Entry Trust Manifests

**Status:** Proposed

**Date:** 2026-09-04

## Context

The Trust Manifest signature procedure defines a detached JWS over canonical
JSON, but its identity and key-selection rules do not provide an interoperable
verification procedure.

The `identity` field has accumulated several meanings. It is described as the
artifact's primary subject, as a workload principal, and as the URI from which
the signer's public key is resolved. The signature instructions separately
refer to the publisher's key. These roles need not identify the same thing.

ADR-0025 assigns artifact identity to the signed `subject`. In particular,
`subject.identifier` names the logical artifact and `subject.version` names the
release when the Catalog Entry declares one. The remaining role needed for
`identity` is the issuer to which the Trust Manifest's claims are attributed.

The existing key-resolution text lists DID, HTTPS, SPIFFE, and DNS mechanisms
as though a short lookup instruction were sufficient for each. These
mechanisms have different authorization models and lifecycles. In particular:

- A DID document can contain several verification methods authorized for
different purposes. Merely finding a key in `verificationMethod` does not
authorize it to make assertions.
- A SPIFFE Workload API returns credentials to the local workload calling the
API. It is not a public resolver for an arbitrary SPIFFE ID carried in a
catalog document.
- A URL or DNS name does not by itself define whether the TLS key, a JWKS key,
a DNSSEC record, or some other key is authorized to sign a Trust Manifest.

The existing list therefore creates apparent breadth without giving
independent implementations enough information to select the same key or reach
the same verification result.

AI Catalog also needs to distinguish publisher authentication from publisher
trustworthiness. A signature profile can prove that the controller of a domain
authorized claims about an artifact in that domain's namespace. It cannot
decide whether that publisher is reputable, whether its claims are true, or
whether an artifact is safe for a particular consumer.

## Decision

### Identity Roles

`TrustManifest.identity` identifies the issuer to which the Trust Manifest's
claims are attributed. It does not identify the artifact and does not identify
a running instance of the artifact.

The signed `subject` identifies the artifact release and representation.
Runtime and workload identities belong to the artifact's protocol or a future
runtime-security profile.

### One Interoperable v1 Profile

AI Catalog defines one signature profile for signed Entry Trust Manifests:

- The artifact identifier uses the standard `urn:air` syntax defined in
[Catalog Entry](../specification/ai-catalog.md#catalog-entry).
- The `{publisher}` component is a lowercase ASCII DNS domain name.
- The Trust Manifest issuer is exactly the root `did:web` DID for that domain.
- The JWS algorithm is ES256.
- The signing key is a P-256 `publicKeyJwk` authorized by the current DID
document's `assertionMethod` relationship.

For example, a Trust Manifest whose signed subject is
`urn:air:example.com:agent:billing` has the issuer
`did:web:example.com`.

This equality is an authorization rule, not merely a consistency check. The
signed subject identifies the publisher namespace, and the `did:web` method
authenticates control of the corresponding domain through HTTPS. A catalog
attacker can publish a separately named artifact under a domain they control,
but cannot retain the original publisher's `urn:air` identifier without
producing a signature authorized by that publisher's DID document.

Under the `did:web` Publisher Profile, the publisher and Trust Manifest issuer
are the same domain authority. The signing operation can be performed by
publishing automation whose key is authorized by the publisher's DID document,
but the profile does not support a separately identified issuer signing on the
publisher's behalf.

The profile supports only root `did:web` DIDs. Ports, method-specific paths,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why only root did:web ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To give us a clear and simple starting point for v1 (so that we can implement it in SDKs). More profiles with different support/requirements can be added in the future, but I think each profile should be considered individually (and motivated by concrete use cases).

subdomain matching, corporate-affiliation heuristics, and delegated issuers are
not inferred. They require an explicit future profile because each changes who
is authorized to speak for the publisher namespace.

### Signature and Verification Semantics

The normative profile specifies the detached JWS construction, protected
headers, key representation, DID resolution, verification-method selection,
and verification result. The important application choices are that `alg` is
`ES256`, `kid` identifies one method under the exact issuer DID, and that method
must be authorized by `assertionMethod`. Merely listing a key under
`verificationMethod`, `authentication`, or `keyAgreement` is insufficient.

No `typ` header is required. The signature appears in a specifically defined
Trust Manifest field, so the containing data model supplies the application
context. A future need for cross-protocol token separation can be addressed by
a separate profile rather than adding a marker without a demonstrated
ambiguity.

A Trust Manifest is verified only after the issuer, signature, signed subject,
Catalog Entry, and artifact all satisfy their respective checks. Failure does
not require rejecting the entire catalog, but the consumer cannot rely on the
manifest's claims or count the entry as Level 3. An expired manifest likewise
cannot supply current verified claims.

The profile uses the DID document returned at verification time. `issuedAt` is
a signed claim rather than a trusted timestamp, so it cannot prove that a
removed key was authorized in the past. Historical verification requires a
separate versioning, logging, or timestamping mechanism.

### Explicit Scope Boundaries

This decision does not define:

- signature profiles for SPIFFE IDs, HTTPS key URLs, DNS records, other DID
methods, or path-based `did:web` identities;
- publisher delegation, hosted signing, or corporate-affiliation rules;
- historical DID document resolution or transparency-log verification;
- whether an authenticated publisher is trusted for a particular use;
- runtime or workload identity;
- the identity and authorization of a top-level catalog signer;
- signature verification for provenance statement formats; or
- a credential format for `publisher-identity` attestations.

Those mechanisms can be added independently when an end-to-end use case and
authorization model are available.

## Consequences

- Implementations have one mandatory producer-consumer intersection instead of
an open list from which they can choose incompatible algorithms and keys.
- A standard `urn:air` identifier can be authenticated without a separately
pinned DID. The verifier relies on its DNS and Web PKI trust roots to resolve
the corresponding `did:web` document.
- Publisher authentication remains distinct from publisher trustworthiness.
Registries and consumers can layer allowlists, vetting, attestations, or
organizational policy on top of the authenticated domain.
- The `identity` field no longer carries artifact or workload semantics.
- Existing signed Trust Manifests that use another identity form or algorithm
do not satisfy the `did:web` Publisher Profile. They can still be processed
under a separately defined implementation policy.
- Long-term verification is not guaranteed after a signing key is removed from
the current DID document.
- The generic key-resolution text for SPIFFE, HTTPS, and DNS is removed rather
than promising behavior the specification does not define.

## Alternatives Considered

### Require an independently configured expected DID

The verifier could require an exact expected issuer DID supplied out of band.
This is appropriate for private policy and remains available as an additional
constraint. It was not chosen as the only interoperable path because the
standard `urn:air` identifier already contains a publisher domain that can
authorize a matching root `did:web` issuer.

### Retain a generic identity-scheme dispatch table

This would preserve the appearance of supporting more identity mechanisms, but
each mechanism still needs profile-specific rules for signer authorization,
key selection, algorithms, lifecycle, and failure behavior. The table is
removed until those rules exist.

### Support multiple mandatory algorithms

Allowing each producer and consumer to implement any one algorithm from a list
does not ensure that a conforming consumer can verify a conforming producer.
ES256 with P-256 `publicKeyJwk` is selected as the required v1 intersection.
Additional algorithms can be defined in later profiles.

### Infer publisher delegation

Suffix matching, path-based DIDs, and organizational-affiliation rules could
allow subsidiaries or signing services to act for a publisher. Such inference
can also authorize an unintended party. Delegation is deferred until the data
model can express who delegated which namespace to whom.

### Use SPIFFE for the Entry Trust Manifest signer

SPIFFE is designed to authenticate workloads within participating trust
domains. Its Workload API supplies credentials to the local workload rather
than resolving arbitrary public SPIFFE IDs. Runtime authentication can use
SPIFFE without treating it as a public artifact-release signing mechanism.
2 changes: 1 addition & 1 deletion docs/examples/multi-protocol-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ An agent that supports both MCP and A2A protocols can be represented as a single
]
},
"trustManifest": {
"identity": "urn:air:acme-corp.com:agent:finance",
"identity": "did:web:acme-corp.com",
"attestations": [
{
"type": "SOC2-Type2",
Expand Down
Loading
Loading