Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
7b8c004
feat(creative): v2 Phase 1 — asset_group vocabulary, scenes, delivery…
bokelley Apr 26, 2026
8d090c0
fix(creative): address Phase 1 review catches — audio.mdx VAST bug + …
bokelley Apr 26, 2026
8fdc407
fix(docs): vast_version must be a single string, not an array
bokelley Apr 26, 2026
6324fba
chore(changeset): correct phase 1 bump from patch to minor
bokelley Apr 27, 2026
4df03c2
refactor(creative): replace delivery_type addition with zip asset type
bokelley Apr 27, 2026
77398b3
feat(creative): v2 Phase 2 — canonical format catalog, ProductFormatD…
bokelley Apr 27, 2026
4b0231a
docs(creative): add v2 overview with worked examples (Meta Reels, IAB…
bokelley Apr 27, 2026
170fa41
refactor(creative): collapse build_capability into format inputs; add…
bokelley Apr 27, 2026
8db52b9
docs(creative): drop "generative formats" framing in v2 overview; add…
bokelley Apr 28, 2026
5b74e25
refactor(creative): rename canonical formats — asset_pool_composed → …
bokelley Apr 28, 2026
202ce2e
feat(creative): v2 migration guide + 5 reference fixtures + product.j…
bokelley Apr 28, 2026
77d69b0
fix(creative): address review feedback — doc/schema mismatches, missi…
bokelley Apr 28, 2026
6dcf8dd
feat(creative): manifest inputs field; bundled extensions schema + fi…
bokelley Apr 28, 2026
53f8dbe
refactor(creative): drop inputs concept, add format_kind discriminato…
bokelley Apr 28, 2026
a7734e3
docs(creative): tighten style_reference description with brand.json r…
bokelley Apr 28, 2026
550b042
fix(creative): doc/schema cleanup; full canonical fixture coverage; n…
bokelley Apr 29, 2026
c5de39c
docs(creative): server-side implementation considerations for v2 sale…
bokelley Apr 29, 2026
32b4a7f
Merge remote-tracking branch 'origin/main' into bokelley/v2-phase1-vo…
bokelley Apr 30, 2026
19e6a30
feat(creative): v2 review-feedback round — format_options array, cano…
bokelley Apr 30, 2026
23c8bea
fix(creative): drop invented creative_agents field from v2 third-part…
bokelley Apr 30, 2026
6882b0c
feat(creative): add production-source axis (image_source / video_sour…
bokelley Apr 30, 2026
e074941
feat(creative): v2 red-team schema fixes — manifest v2 path, carousel…
bokelley Apr 30, 2026
55edddf
docs(creative): v2 red-team docs round — glossary, vocabulary table, …
bokelley Apr 30, 2026
601bd95
docs(creative): expand v2 creative-agent migration walkthrough
bokelley Apr 30, 2026
76f7990
Merge remote-tracking branch 'origin/main' into bokelley/v2-phase1-vo…
bokelley Apr 30, 2026
b3c29bc
feat(creative): runtime_status on ProductFormatDeclaration; align ite…
bokelley Apr 30, 2026
1cc7e20
feat(creative): custom format_kind + format_shape registry + format_s…
bokelley Apr 30, 2026
f0650d7
Merge remote-tracking branch 'origin/main' into bokelley/v2-phase1-vo…
bokelley May 1, 2026
a8228b6
feat(creative): A1 dual-emission of format_ids+format_options legal; …
bokelley May 1, 2026
fbb207b
fix(creative): R1-R7 review-line fixes — card-asset, validate_input r…
bokelley May 1, 2026
d7faae4
feat(schema): add optional display_name to ProductFormatDeclaration
claude May 3, 2026
4bbce58
docs(creative): drop per-canonical status differentiation pre-GA — ev…
bokelley May 3, 2026
90ea4bc
refactor(creative): rename v2 → canonical-formats throughout (path + …
bokelley May 16, 2026
5eba428
Merge remote-tracking branch 'origin/main' into bokelley/v2-phase1-vo…
bokelley May 16, 2026
de7a6f0
feat(canonical-formats): address SDK implementor review on PR #3307 —…
bokelley May 16, 2026
501df3f
refactor(canonical-formats): rename v2_only → canonical_formats_only …
bokelley May 16, 2026
d46f83c
feat(canonical-formats): second expert-review pass on PR #3307 — wire…
bokelley May 16, 2026
f29effd
docs(canonical-formats): v2-native seller v1-emission options (closes…
bokelley May 16, 2026
47a9995
fix(ci): correct changeset package name + add error-code drift dispos…
bokelley May 16, 2026
de074fd
refactor(creative): move brand_kit_override from CreativeManifest ont…
bokelley May 16, 2026
3bb819e
feat(canonical-formats): four inline tightenings from python-implemen…
bokelley May 16, 2026
ffbef21
feat(canonical-formats): v1_format_ref on ProductFormatDeclaration; d…
bokelley May 16, 2026
ef7693f
refactor(canonical-formats): collapse status/runtime_status to experi…
bokelley May 16, 2026
972a157
feat(canonical-formats): F+H — slot-constraint mutex + card-asset des…
bokelley May 16, 2026
c97e4bb
fix(canonical-formats): expert-review fixes — rename stragglers, semv…
bokelley May 16, 2026
9dff810
fix(canonical-formats): SDK-side fixes from 4th implementor review — …
bokelley May 17, 2026
762ba1f
fix(canonical-formats): tighten cross-boundary visibility prose on FO…
bokelley May 17, 2026
4c9f19b
feat(canonical-formats): format_shape promotion migration contract; v…
bokelley May 17, 2026
0786e35
fix(canonical-formats): registry globs use underscore namespace to ma…
bokelley May 17, 2026
f34bf5b
feat(canonical-formats): mandate errors[] augmentation as single surf…
bokelley May 17, 2026
7357e58
feat(canonical-formats): 5 upstream asks from adcp-client #1815 proto…
bokelley May 17, 2026
360d084
feat(canonical-formats): converge v1 wire namespace via AAO-hosted v1…
bokelley May 17, 2026
8e5b514
fix(canonical-formats): reconcile registry + fixtures + AAO catalog n…
bokelley May 17, 2026
50da682
fix(canonical-formats): replace fictional .adcp placeholder domains w…
bokelley May 17, 2026
44bd9d2
feat(canonical-formats): annotate 9 more catalog entries; document em…
bokelley May 17, 2026
9f56844
fix(canonical-formats): drop 17 per-size/per-duration registry litera…
bokelley May 17, 2026
f88522c
refactor(canonical-formats): drop meta_reels literal — registry is pu…
bokelley May 17, 2026
e2fae6b
feat(canonical-formats): publisher-scoped format catalog via adagents…
bokelley May 17, 2026
6b3438b
fix(canonical-formats): audit-driven hygiene + slot-param consistency…
bokelley May 17, 2026
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
53 changes: 53 additions & 0 deletions .changeset/canonical-formats-expert-review-round-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
"adcontextprotocol": minor
---

canonical-formats: second expert-review pass on PR #3307 — wire-level concerns, security hardening, auto-promote-stable, and narrowing semantics.

Triaged from 5 expert reviews (ad-tech-protocol-expert, adtech-product-expert, code-reviewer, docs-expert, security-reviewer) plus a second SDK-implementor review. Items merged into 4 blocks of inline fixes; 3 follow-up issues filed (#4591 scope extended, #4592, #4599).

## Block A — security hardening on `format_schema` fetch

- **SSRF deny-list** (normative): RFC 1918 / loopback / link-local / CGNAT / RFC 6761 special-use rejected; cloud metadata endpoints (169.254.169.254, metadata.google.internal, kubernetes.default.svc) explicitly forbidden; resolved IP pinning to defeat DNS rebinding.
- **No HTTP redirects** on these fetches — open redirects on same-origin paths are a free SSRF primitive.
- **1 MiB response cap**, enforced during streaming.
- **Schema-compile DoS controls**: keyword count ≤10 000, `$ref` count ≤256, `pattern` regex via re2 or per-pattern timeout, per-manifest validation budget ≤250 ms.
- **Digest format pinned**: `sha256:` + 64 lowercase hex.
- **`$ref` sandbox**: same-origin (after RFC 3986 §6 normalization) / AAO mirror / intra-document JSON Pointer only; cross-origin and `file://` rejected.
- **Transport rules apply to BOTH** `format_schema` (load-bearing) AND `platform_extensions` (informational) — shared fetch path can't drop to the weakest bar. `platform-extension-ref.json` `uri` gets `pattern: "^https://"` for defense-in-depth.

## Block B — wire-level load-bearing concerns

- **B1 per-slot `consumed_for_production` boolean** on `_base.json#slots`: dispatch hint for build_creative and v1↔v2 translators so they know which slots are render-verbatim vs production-consumed (host-read script vs MP3 file, brief vs generative video, catalog feed vs SKU placement). Without this the dispatch table lives in adopter code and every SDK gets it slightly different.
- **B2 SHOULD-warn surfaces via `errors[]` envelope**, not logger-only. Two new error codes added to `error-code.json`: `FORMAT_PROJECTION_FAILED` (v1 format can't project to canonical) and `FORMAT_DECLARATION_DIVERGENT` (dual-emitted format_ids + format_options disagree). Both non-fatal — sellers don't flip transport failure markers.
- **B3 open-enum guidance** on `canonical-format-kind.json`: consumers MUST treat the enum as open; unknown `format_kind` values MUST be retained on the in-memory object and SHOULD be treated as `runtime_status: declared_only` for routing. Prevents every future canonical from being a breaking change for older SDKs.
- **B4 `validate_input` request renamed to discriminated `targets[]`**, mirroring the response shape. Eliminates wire-shape collision between request `format_ids: string[]` and `Product.format_ids: FormatId[]`.

## Block C — auto-promote-stable + correctness + narrowing semantics

- **C1 6-canonical Track-A promotion to `stable` at 3.1 GA**: `image`, `display_tag`, `video_hosted`, `video_vast`, `audio_hosted`, `audio_daast` — re-encodings of IAB/VAST/DAAST that round-trip cleanly through `v1-canonical-mapping.json`. 5 canonicals stay Track-B preview (`html5` lossy round-trip, `image_carousel` no v1 mapping entry, `sponsored_placement` adapter-contract dependency #4592, `responsive_creative` algorithmic, `agent_placement` 3.2-track per IR8). Each Track-A canonical carries `default: "stable"` on its own `status` field overriding `_base.json`'s `default: "preview"`.
- **C2 negative-test AJV** now constructed with `discriminator: true` matching the positive suite's strict-mode config.
- **C3 new `format_kind: "custom"` fixture** (`nytimes_homepage_takeover_custom.json`) covers the riskiest oneOf branch with `canonical_formats_only: true` + `format_shape` + `format_schema`.
- **C5 positive controls** added for `canonical_formats_only` on non-custom branches (Track-B canonicals MAY ship as v2-only).
- **C6 (N1) formal "narrows" definition** in canonical-formats.mdx: parameter-by-parameter subsumption rules (scalar containment, enum subset, range inclusion, asymmetric narrowing, conflict detection) so SDKs implementing dual-emission divergence detection don't each invent their own.
- **C7 (N3) `canonical_parameters` drift contract**: hand-authored values MUST satisfy the narrows relation against v1 `requirements`; SDKs SHOULD lint-time check and emit `FORMAT_PROJECTION_FAILED` on divergence. Producers SHOULD prefer to omit and let SDKs derive the v2 shape from v1 `requirements` + `assets[*]` rather than hand-author both shapes.
- **C8 (N7) `asset_group_id` alias collision precedence**: v1 `assets[*]` declaration order is authoritative; first slot wins; subsequent collisions dropped and surfaced via `FORMAT_PROJECTION_FAILED` with structured `error.details`.
- **C9 (N8) `declared_only` SHOULD-filter by default** on buyer SDKs (opt-in to surface); without the default filter the value is a doc string adopters ignore.

## Block D — docs structural pass (selective)

- **TL;DR block hoisted to top of canonical-formats.mdx**: 6/11 stable at GA, v1 stays first-class, 71+ v1-only at GA, Phase 4 codegen is the gating dep. Cold-read reader gets the load-bearing facts in the first 60 seconds instead of buried at line 880.
- **Codegen-vs-runtime promoted to H2** (was buried as H3 under Migration).
- **Naming-note tightened**: doc body uses "canonical formats" consistently; "v1↔v2" reserved as schema-description shorthand only.

## Follow-up issues filed (GA-blocking but not 3.1-beta-merge-blocking)

- **#4591 extended** with the (canonical × production_source) storyboard matrix scope (N5 from second implementor review).
- **#4592** sponsored_placement adapter-contract docs (IR5 from first round).
- **#4599** v2→v1 demotion synthetic format_id docs note (N2 from second implementor review).

## Test coverage

- 14 positive canonical-formats fixtures (added 1 custom-shape fixture)
- 15 negative product-format-declaration fixtures (added 2 for `canonical_formats_only` semantics on non-custom)
- All schema tests pass under `discriminator: true` strict mode
16 changes: 16 additions & 0 deletions .changeset/canonical-formats-implementor-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"adcontextprotocol": minor
---

canonical-formats: address SDK-team implementor review on PR #3307 with inline normative tightening.

- **v2→v1 projection (IR1)**. Add `canonical_formats_only` boolean to `ProductFormatDeclaration`; required `true` for `format_kind: "custom"` declarations. Add normative producer/consumer rules for dual-emission (`format_ids` + `format_options`) and divergence detection in canonical-formats.mdx. Protocol does not mint synthetic v1 `format_id`s — explicit `canonical_formats_only` is the v2-only marker.
- **Non-projectable v1 SHOULD-warn (IR2)**. v1-canonical-mapping.json now normatively requires SDKs to emit a structured warning (carrying format_id, product_id, resolution-failure reason) when a v1 product can't project to a canonical. Prevents silent inventory shrinkage for v2-only buyers.
- **`format_schema` fetch contract (IR3)**. Pin normative fetch semantics on `format_schema`: https-only transport, hard-fail on digest mismatch, ≤5s timeout, `$ref` sandboxing (same-origin / AAO-mirror / intra-document only; no `file://`; transitive depth ≤8), graceful degradation on 404 / partition, schema-not-valid hard-fail. Documented in both the schema description and canonical-formats.mdx custom-formats section.
- **Codegen-vs-runtime asymmetry (IR6)**. Doc callout that generated TS/Pydantic types lose the `allOf/if/then` conditionals on `format_kind: "custom"` and `result_kind`; runtime Ajv (or equivalent) validation is the gate. Adopters MUST validate at runtime, not rely on the type system.
- **`agent_placement` 3.2-track (IR8)**. Explicit description-level stamp that the tracking macro vocabulary, postback shape, and dedup model are intentionally underspecified for 3.1. Adopters claiming the canonical SHOULD set `runtime_status: 'preview'` or `'declared_only'`. Wire contract for tracking events ships in 3.2.
- **Migration math reality (IR9)**. Realistic-coverage paragraph in canonical-formats.mdx: 15 registry entries at 3.1, ~76% of audited formats fit but require seller or registry action to project, 71+ v1-only out of gate. Dual-read codepath realistic through 3.3; v2-only realistic at 4.x earliest.

Negative-fixture suite expanded: `format_kind: "custom"` now rejects when `canonical_formats_only` is missing or `false`.

Conformance-storyboard track (IR4) and adopter-contract docs for `sponsored_placement` (IR5) filed as follow-up issues against 3.1 GA.
16 changes: 16 additions & 0 deletions .changeset/canonical-formats-publisher-catalog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
"adcontextprotocol": minor
---

canonical-formats: publisher-scoped format catalog via `adagents.json` `formats[]` + `placement-definition.json` `format_options[]`. Resolves #4620 in-PR (was filed as a follow-up; pulled in because the wire shape is the same vocabulary PR #3307 already establishes).

- **`adagents.json` top-level `formats[]`** carries publisher-authoritative `ProductFormatDeclaration` entries. Optional `applies_to_property_ids` / `applies_to_property_tags` scope each declaration to a subset of the file's `properties[]`. Single source of truth for "what formats does this publisher support" — eliminates the N-copies-on-N-products drift surface.
- **`placement-definition.json` `format_options[]`** lets a placement reference a `capability_id` from the file's top-level `formats[]` OR carry an inline `ProductFormatDeclaration`. Parallel to existing v1 `format_ids[]`; both supported during the migration window.
- **`list_creative_formats` (media-buy) gains `publisher_domain` + `property_id` filters**. SDKs resolve the question "what formats does Meta support" by fetching `<publisher_domain>/.well-known/adagents.json` first, then the AAO community-registry mirror at `https://creative.adcontextprotocol.org/translated/<platform>/adagents.json` as fallback, returning `formats[]` directly. No product traversal required.
- **Community-registry pattern (normative for unadopted platforms)**. For platforms that haven't adopted AdCP (Meta, TikTok, Snap, Pinterest, etc.), AAO publishes community-maintained `adagents.json` at the mirror namespace. When the platform later adopts AdCP and publishes its own `adagents.json` with `formats[]`, the platform-hosted file takes precedence and the mirror entry deprecates. Documented on `product-format-declaration.json#v1_format_ref` and reflected in the Meta Reels worked example.
- **Reference fixture** at `static/examples/adagents/community/meta.json`: Instagram + Facebook + WhatsApp properties, Meta Reels / Feed Image / Stories Video / Feed Carousel format declarations with `applies_to_property_ids` scoping, four placements wired to formats via `capability_id`.
- **Meta Reels worked example rewritten** in `docs/creative/canonical-formats.mdx` showing where each Reels feature lives (canonical params, slot narrowing, platform extensions, BrandRef brand_kit_override), the community-registry hosting pattern, and how a seller's product references the catalog declaration by `capability_id`.
- **Registry shrink**: `v1-canonical-mapping.json` drops the last literal entry (`meta_reels`). The registry is now seven pure-structural fallbacks; platform-specific formats project via the platform's own (or community-mirror) `adagents.json` `formats[]` rather than enumerated registry literals. Honors the canonical-formats parametrization principle.
- **`v1_format_ref.agent_url` convention extended**: IAB-standard → `https://creative.adcontextprotocol.org`; platform-adopted → platform's agent_url; platform-unadopted → `https://creative.adcontextprotocol.org/translated/<platform>`. Keeps v1 namespace converged regardless of which side hosts the catalog.

Closes #4620, #4652.
Loading
Loading