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
13 changes: 13 additions & 0 deletions .changeset/tmp-router-attestation-rfc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"adcontextprotocol": minor
---

spec: TMP router attestation (experimental, `trusted_match.router_attestation`)

Promotes the existing one-paragraph "TEE upgrade path" mention in router-architecture into a normative, experimentally-gated feature with a wire shape: a `GET /.well-known/tmp-router-attestation?nonce=<base64url, 16-32 raw bytes>` endpoint, a JSON envelope schema (`/schemas/trusted-match/router-attestation.json`), a per-request `X-TMP-Attestation` header carrier, and a new optional `attestation_requirement` block on `provider-registration.json` so providers can declare they require an attested router. Experimental gate `trusted_match.router_attestation` is separate from `trusted_match.core` and `trusted_match.verified_identity`, so participants can support core TMP without committing to attestation.

The load-bearing invariant is the **binding rule**: the JWK in `signing_key` MUST appear bound in the platform user-data slot of `attestation_document` alongside the nonce, and verifiers MUST reject when the bound key doesn't byte-match the envelope's `signing_key` (RFC 7638 thumbprint comparison is the acceptable form). This rule is what makes the router's existing per-provider `X-AdCP-Signature`/`X-AdCP-Key-Id` signature path cryptographically anchored to the attested binary instead of to an out-of-band-deployed key.

Scope is wire shape only. Out of scope: reproducible-build pipeline, KMS provisioning, `adcp-go` implementation, conformance scenarios, verifier-kit implementations, measurement allowlists. The `attestation_format` enum starts with four canonical externally-defined formats (`aws_nitro_cose_sign1_v1`, `intel_tdx_quote_v4`, `amd_sev_snp_attestation_v1`, `gcp_confidential_space_v1`) — same canonical-external-identifier pattern as `enums/feed-format.json`; entries added to the platform-agnostic lint allowlist with path-qualified justifications. Extension is via `ext` plus future enum additions through the normal change process.

Additive change to an experimental surface: existing TMP behavior is unchanged for participants that do not opt in (no `attestation_requirement` block on a provider's registration means routers do not attach `X-TMP-Attestation` and providers do not require it). Schemas: new `router-attestation.json`; `provider-registration.json` gains optional `attestation_requirement` (additive, not in `required`). Docs: new `docs/trusted-match/router-attestation.mdx` normative page; `router-architecture.mdx` and `privacy-architecture.mdx` keep their informative framing and point at the normative page for the wire shape. Design rationale in `specs/tmp-router-attestation.md`.
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1161,6 +1161,7 @@
"docs/trusted-match/context-and-identity",
"docs/trusted-match/specification",
"docs/trusted-match/router-architecture",
"docs/trusted-match/router-attestation",
"docs/trusted-match/privacy-architecture",
"docs/trusted-match/data-protection-roles",
"docs/trusted-match/migration-from-axe",
Expand Down
4 changes: 2 additions & 2 deletions docs/protocol/get_adcp_capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -596,14 +596,14 @@ Array of experimental AdCP surfaces this agent implements. A surface is experime

| Field | Type | Description |
|-------|------|-------------|
| `experimental_features` | string[] | Experimental feature ids (e.g., `["brand.rights_lifecycle", "governance.campaign", "measurement.core", "trusted_match.core", "sponsored_intelligence.core"]`) |
| `experimental_features` | string[] | Experimental feature ids (e.g., `["brand.rights_lifecycle", "governance.campaign", "measurement.core", "trusted_match.core", "trusted_match.router_attestation", "sponsored_intelligence.core"]`) |

Buyers should inspect `experimental_features` before relying on an experimental surface. A seller that does not list a surface is asserting it does not implement it — there is no "silently experimental" mode.

**Example:**
```json
{
"experimental_features": ["brand.rights_lifecycle", "measurement.core", "trusted_match.core"]
"experimental_features": ["brand.rights_lifecycle", "measurement.core", "trusted_match.core", "trusted_match.router_attestation"]
}
```

Expand Down
20 changes: 6 additions & 14 deletions docs/trusted-match/privacy-architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -126,32 +126,24 @@ Temporal decorrelation is defense in depth. It is not the primary separation mec

## TEE Attestation Details

TMP's reference architecture targets AWS Nitro Enclaves, though the protocol is TEE-agnostic. Any TEE that produces verifiable attestation documents is compatible.
TMP is TEE-agnostic; the experimental [Router Attestation](/docs/trusted-match/router-attestation) surface (`trusted_match.router_attestation`) defines the normative wire shape (endpoint, envelope schema, nonce policy, signing-key binding rule, verification flow, `X-TMP-Attestation` per-request carrier, and provider-side `attestation_requirement` opt-in). The treatment in this section is informative — what attestation does and does not prove, and how it relates to TMP's regulatory and audit posture. See the normative page for the format-version enum, the verification flow, and the failure modes.

### What attestation proves

- The router binary running inside the enclave matches the published, audited source code.
- The code paths for context and identity are structurally separate, with no shared state.
- The router binary running inside the enclave matches the published, audited source code (subject to the verifier's local measurement allowlist).
- The code paths for context and identity are structurally separate, with no shared state, on the running binary — not only on the published source.
- The binary has not been modified by the operator, the hosting provider, or any runtime process.
- The signing key the provider already verifies request signatures against is held by the attested binary — see the [binding rule](/docs/trusted-match/router-attestation#binding-rule). Without this binding, attestation proves that *some* binary is attested but says nothing about whether that binary is what produced the signatures the provider trusts.

### What attestation does not prove

- That buyer agents handle the data they receive responsibly. TMP limits what buyers receive; it does not control what they do with it.
- That the publisher's join logic is correct. The publisher is the first party and is not constrained by TMP's separation model.
- That the code is free of bugs. Attestation proves the code matches the published source. Whether that source is correct is a separate question, addressed by open-source audit.

### Attestation measurements
### Attestation measurements (informative)

Each attestation document includes cryptographic hashes of the running environment:

| Measurement | What it covers |
|---|---|
| **Image hash** | Hash of the enclave image. Confirms the binary matches the expected build. |
| **Kernel hash** | Hash of the operating environment. |
| **Application hash** | Hash of the application-level code. |
| **Role hash** | Confirms the enclave's permissions match expectations (e.g., no access to external databases). |

A publisher or auditor can verify these measurements against the published build artifacts. This verification can be automated and performed continuously.
Platform attestation documents carry cryptographic hashes of the running environment — image hash, kernel hash, application hash, and role/permissions measurements. The exact set, names, and semantics are format-specific and live in each verifier kit; the normative envelope is opaque to AdCP. A publisher or auditor verifies these measurements against the published build artifacts; this verification can be automated and performed continuously. AdCP does not maintain a normative measurement allowlist — see the rationale's "[No measurement allowlist in the spec](https://github.com/adcontextprotocol/adcp/blob/main/specs/tmp-router-attestation.md)" section for why this is a deploy-side decision.

## Comparison to OpenRTB

Expand Down
4 changes: 2 additions & 2 deletions docs/trusted-match/router-architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The router is a single Go binary with two structurally separate code paths: one

The separation is in the code and auditable. The context path cannot read identity data because it is not passed to it, not stored in any reachable location, and not referenced in any data structure the context path processes. The same applies in reverse for the identity path. The router is open-source — anyone can verify this by reading the source.

TEE attestation is an upgrade path. Without TEE, you trust that the operator deployed the published binary. With TEE, attestation proves the deployed binary matches the audited source, removing that trust requirement.
TEE attestation is an upgrade path. Without TEE, you trust that the operator deployed the published binary; with TEE-attested operation, the router exposes a verifiable envelope at `/.well-known/tmp-router-attestation` and providers MAY require it via `attestation_requirement` on their registration. The wire shape, binding rule, and verification flow are defined in [Router Attestation](/docs/trusted-match/router-attestation) (experimental, `trusted_match.router_attestation`).

## Provider Registration

Expand Down Expand Up @@ -197,7 +197,7 @@ The TMP Router replaces this with a multi-provider, multi-surface, protocol-stan
| Discovery | Publisher configuration | Publisher configuration |
| Surfaces | Web (Prebid Server) | Web, AI, mobile, CTV, retail media |
| Request format | Full OpenRTB BidRequest (~2-10KB JSON) | TMP ContextMatchRequest (~200-600 bytes JSON) |
| Privacy | Data masking before sending | Structural separation (TEE-ready) |
| Privacy | Data masking before sending | Structural separation; TEE-attested operation available via [Router Attestation](/docs/trusted-match/router-attestation) (experimental) |
| Identity handling | User ID in bid request | Separate Identity Match operation |

For existing Prebid Server deployments, the TMP module replaces vendor-specific RTD modules with a generic TMP client. For surfaces without Prebid, the router's HTTP/2 API provides the same functionality.
Expand Down
Loading
Loading