@adcp/sdk 14.0.0-beta.21 → 14.0.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -682,8 +682,8 @@ export interface paths {
682
682
  get?: never;
683
683
  put?: never;
684
684
  /**
685
- * Validate product authorization
686
- * @description Check whether an agent is authorized to sell a product based on its publisher_properties.
685
+ * Validate product property coverage
686
+ * @description Checks whether an agent covers a product's publisher_properties. This endpoint does not validate collection, placement, country, or time qualifiers and must not be used as full product authorization proof; validate those qualifiers against the publisher's authoritative adagents.json.
687
687
  */
688
688
  post: operations["validateProductAuthorization"];
689
689
  delete?: never;
@@ -692,6 +692,26 @@ export interface paths {
692
692
  patch?: never;
693
693
  trace?: never;
694
694
  };
695
+ "/api/registry/verify/supply-path": {
696
+ parameters: {
697
+ query?: never;
698
+ header?: never;
699
+ path?: never;
700
+ cookie?: never;
701
+ };
702
+ get?: never;
703
+ put?: never;
704
+ /**
705
+ * Verify an owner-sold supply path
706
+ * @description Joins the owner's and host's cached adagents.json manifests (plus the host's ads.txt/app-ads.txt inventorypartnerdomain lines when needed) and returns the verification state of one owner-sold carriage path, leg by leg. States follow the documented ladder: verified_owner_sold (host adagents.json authorizes the agent for the host property, collection-scoped), host_delegated (ads.txt inventorypartnerdomain + owner-side declarations, policy-gated), owner_attested (owner distribution claim only — discovery, never authorization), unverified. The response is evidence-bearing so callers can reproduce the verdict from the authoritative files; the registry cache is a convenience, not the trust root. For a live-fetch check of a file you just changed, use POST /api/adagents/validate.
707
+ */
708
+ post: operations["verifySupplyPath"];
709
+ delete?: never;
710
+ options?: never;
711
+ head?: never;
712
+ patch?: never;
713
+ trace?: never;
714
+ };
695
715
  "/api/registry/expand/product-identifiers": {
696
716
  parameters: {
697
717
  query?: never;
@@ -2906,7 +2926,7 @@ export interface components {
2906
2926
  }[];
2907
2927
  collections?: {
2908
2928
  publisher_domain: string;
2909
- collection_ids: string[];
2929
+ collection_ids?: string[];
2910
2930
  }[];
2911
2931
  placement_ids?: string[];
2912
2932
  placement_tags?: string[];
@@ -3982,10 +4002,10 @@ export interface components {
3982
4002
  placement_tags?: string[];
3983
4003
  collections?: ({
3984
4004
  publisher_domain: string;
3985
- collection_ids: string[];
4005
+ collection_ids?: string[];
3986
4006
  } & {
3987
4007
  [key: string]: unknown;
3988
- })[];
4008
+ })[] | null;
3989
4009
  countries?: string[];
3990
4010
  delegation_type?: string;
3991
4011
  exclusive?: boolean;
@@ -4159,7 +4179,7 @@ export interface components {
4159
4179
  adcp_version: string;
4160
4180
  verified_at: string;
4161
4181
  /** @description Specialisms demonstrably passed (enums/specialism.json). Preview specialisms are excluded from stable badges. */
4162
- verified_specialisms: ("audience-sync" | "brand-rights" | "collection-lists" | "content-standards" | "creative-ad-server" | "creative-generative" | "creative-template" | "creative-transformers" | "governance-aware-seller" | "governance-delivery-monitor" | "governance-spend-authority" | "property-lists" | "sales-broadcast-tv" | "sales-catalog-driven" | "sales-guaranteed" | "sales-non-guaranteed" | "sales-proposal-mode" | "sales-social" | "signal-marketplace" | "signal-owned" | "signed-requests" | "sponsored-intelligence")[];
4182
+ verified_specialisms: ("audience-sync" | "brand-rights" | "collection-lists" | "content-standards" | "creative-ad-server" | "creative-generative" | "creative-template" | "creative-transformers" | "governance-aware-seller" | "governance-delivery-monitor" | "governance-spend-authority" | "property-lists" | "sales-broadcast-tv" | "sales-catalog-driven" | "sales-dooh" | "sales-guaranteed" | "sales-non-guaranteed" | "sales-proposal-mode" | "sales-social" | "signal-marketplace" | "signal-owned" | "signed-requests" | "sponsored-intelligence")[];
4163
4183
  /** @description Verification axes earned. 'spec' = AdCP storyboards pass for the declared specialisms. 'live' = AAO has observed real production traffic via canonical campaigns. Always non-empty when a badge is present; an absent badge is conveyed by the parent record being omitted, not by an empty array. */
4164
4184
  verification_modes: ("spec" | "live")[];
4165
4185
  verified_protocol_version: string | null;
@@ -6354,7 +6374,7 @@ export interface operations {
6354
6374
  };
6355
6375
  };
6356
6376
  responses: {
6357
- /** @description Authorization validation result */
6377
+ /** @description Publisher-property coverage result */
6358
6378
  200: {
6359
6379
  headers: {
6360
6380
  [name: string]: unknown;
@@ -6363,6 +6383,8 @@ export interface operations {
6363
6383
  "application/json": {
6364
6384
  agent_url: string;
6365
6385
  authorized: boolean;
6386
+ /** @enum {string} */
6387
+ validation_scope: "publisher_properties_only";
6366
6388
  checked_at: string;
6367
6389
  } & {
6368
6390
  [key: string]: unknown;
@@ -6371,6 +6393,109 @@ export interface operations {
6371
6393
  };
6372
6394
  };
6373
6395
  };
6396
+ verifySupplyPath: {
6397
+ parameters: {
6398
+ query?: never;
6399
+ header?: never;
6400
+ path?: never;
6401
+ cookie?: never;
6402
+ };
6403
+ requestBody?: {
6404
+ content: {
6405
+ "application/json": {
6406
+ /** @description Channel owner's publisher domain — where the canonical collection is declared. */
6407
+ owner_domain: string;
6408
+ /** @description Host publisher domain — where the carrying property (e.g. CTV app) is declared. */
6409
+ host_domain: string;
6410
+ /** @description Sales agent URL the buyer would transact with. Canonicalized server-side. */
6411
+ agent_url: string;
6412
+ /** @description Owner-assigned collection ID. Omit to verify the path at domain level (bulk deals). */
6413
+ collection_id?: string;
6414
+ };
6415
+ };
6416
+ };
6417
+ responses: {
6418
+ /** @description Supply-path verification verdict with per-leg evidence */
6419
+ 200: {
6420
+ headers: {
6421
+ [name: string]: unknown;
6422
+ };
6423
+ content: {
6424
+ "application/json": {
6425
+ /** @enum {string} */
6426
+ state: "verified_owner_sold" | "host_delegated" | "owner_attested" | "unverified";
6427
+ legs: {
6428
+ owner_collection_declared: {
6429
+ ok: boolean;
6430
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6431
+ failure?: string;
6432
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6433
+ detail?: string;
6434
+ } & {
6435
+ [key: string]: unknown;
6436
+ };
6437
+ owner_distribution_carriage: {
6438
+ ok: boolean;
6439
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6440
+ failure?: string;
6441
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6442
+ detail?: string;
6443
+ } & {
6444
+ [key: string]: unknown;
6445
+ };
6446
+ owner_agent_declared: {
6447
+ ok: boolean;
6448
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6449
+ failure?: string;
6450
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6451
+ detail?: string;
6452
+ } & {
6453
+ [key: string]: unknown;
6454
+ };
6455
+ host_authorization: {
6456
+ ok: boolean;
6457
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6458
+ failure?: string;
6459
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6460
+ detail?: string;
6461
+ } & {
6462
+ [key: string]: unknown;
6463
+ };
6464
+ inventory_partner_domain: {
6465
+ ok: boolean;
6466
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6467
+ failure?: string;
6468
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6469
+ detail?: string;
6470
+ } & {
6471
+ [key: string]: unknown;
6472
+ };
6473
+ };
6474
+ owner_domain: string;
6475
+ host_domain: string;
6476
+ agent_url: string;
6477
+ collection_id?: string;
6478
+ sources: {
6479
+ owner_adagents_url: string;
6480
+ host_adagents_url: string;
6481
+ /** @description true: manifests came from the registry's crawl cache. Re-derive from the URLs above for enforcement. */
6482
+ cached: boolean;
6483
+ };
6484
+ checked_at: string;
6485
+ } & {
6486
+ [key: string]: unknown;
6487
+ };
6488
+ };
6489
+ };
6490
+ /** @description Invalid request body or uncanonicalizable domain */
6491
+ 400: {
6492
+ headers: {
6493
+ [name: string]: unknown;
6494
+ };
6495
+ content?: never;
6496
+ };
6497
+ };
6498
+ };
6374
6499
  expandProductIdentifiers: {
6375
6500
  parameters: {
6376
6501
  query?: never;
@@ -7962,6 +8087,13 @@ export interface operations {
7962
8087
  updated_at: string;
7963
8088
  /** @description Publisher-pinned JWK set (authorized_agents[*].signing_keys) from the source adagents.json. Consumers verifying inbound TMP signatures key on kid → JWK. Null when the publisher declared no keys; consumers fall back to the agent-hosted JWKS per spec R-2 (docs/governance/property/adagents.mdx). */
7964
8089
  signing_keys: components["schemas"]["SigningKey"][] | null;
8090
+ /** @description Collection constraints (authorized_agents[*].collections) from the source adagents.json. Null when the entry is unconstrained. When set, the row does NOT authorize the property unqualified — consumers MUST scope it to these selectors. A selector without collection_ids is a bulk grant for all collections declared at that publisher_domain. */
8091
+ collections: ({
8092
+ publisher_domain: string;
8093
+ collection_ids?: string[];
8094
+ } & {
8095
+ [key: string]: unknown;
8096
+ })[] | null;
7965
8097
  override_applied: boolean;
7966
8098
  override_reason: string | null;
7967
8099
  }[];
@@ -682,8 +682,8 @@ export interface paths {
682
682
  get?: never;
683
683
  put?: never;
684
684
  /**
685
- * Validate product authorization
686
- * @description Check whether an agent is authorized to sell a product based on its publisher_properties.
685
+ * Validate product property coverage
686
+ * @description Checks whether an agent covers a product's publisher_properties. This endpoint does not validate collection, placement, country, or time qualifiers and must not be used as full product authorization proof; validate those qualifiers against the publisher's authoritative adagents.json.
687
687
  */
688
688
  post: operations["validateProductAuthorization"];
689
689
  delete?: never;
@@ -692,6 +692,26 @@ export interface paths {
692
692
  patch?: never;
693
693
  trace?: never;
694
694
  };
695
+ "/api/registry/verify/supply-path": {
696
+ parameters: {
697
+ query?: never;
698
+ header?: never;
699
+ path?: never;
700
+ cookie?: never;
701
+ };
702
+ get?: never;
703
+ put?: never;
704
+ /**
705
+ * Verify an owner-sold supply path
706
+ * @description Joins the owner's and host's cached adagents.json manifests (plus the host's ads.txt/app-ads.txt inventorypartnerdomain lines when needed) and returns the verification state of one owner-sold carriage path, leg by leg. States follow the documented ladder: verified_owner_sold (host adagents.json authorizes the agent for the host property, collection-scoped), host_delegated (ads.txt inventorypartnerdomain + owner-side declarations, policy-gated), owner_attested (owner distribution claim only — discovery, never authorization), unverified. The response is evidence-bearing so callers can reproduce the verdict from the authoritative files; the registry cache is a convenience, not the trust root. For a live-fetch check of a file you just changed, use POST /api/adagents/validate.
707
+ */
708
+ post: operations["verifySupplyPath"];
709
+ delete?: never;
710
+ options?: never;
711
+ head?: never;
712
+ patch?: never;
713
+ trace?: never;
714
+ };
695
715
  "/api/registry/expand/product-identifiers": {
696
716
  parameters: {
697
717
  query?: never;
@@ -2906,7 +2926,7 @@ export interface components {
2906
2926
  }[];
2907
2927
  collections?: {
2908
2928
  publisher_domain: string;
2909
- collection_ids: string[];
2929
+ collection_ids?: string[];
2910
2930
  }[];
2911
2931
  placement_ids?: string[];
2912
2932
  placement_tags?: string[];
@@ -3982,10 +4002,10 @@ export interface components {
3982
4002
  placement_tags?: string[];
3983
4003
  collections?: ({
3984
4004
  publisher_domain: string;
3985
- collection_ids: string[];
4005
+ collection_ids?: string[];
3986
4006
  } & {
3987
4007
  [key: string]: unknown;
3988
- })[];
4008
+ })[] | null;
3989
4009
  countries?: string[];
3990
4010
  delegation_type?: string;
3991
4011
  exclusive?: boolean;
@@ -4159,7 +4179,7 @@ export interface components {
4159
4179
  adcp_version: string;
4160
4180
  verified_at: string;
4161
4181
  /** @description Specialisms demonstrably passed (enums/specialism.json). Preview specialisms are excluded from stable badges. */
4162
- verified_specialisms: ("audience-sync" | "brand-rights" | "collection-lists" | "content-standards" | "creative-ad-server" | "creative-generative" | "creative-template" | "creative-transformers" | "governance-aware-seller" | "governance-delivery-monitor" | "governance-spend-authority" | "property-lists" | "sales-broadcast-tv" | "sales-catalog-driven" | "sales-guaranteed" | "sales-non-guaranteed" | "sales-proposal-mode" | "sales-social" | "signal-marketplace" | "signal-owned" | "signed-requests" | "sponsored-intelligence")[];
4182
+ verified_specialisms: ("audience-sync" | "brand-rights" | "collection-lists" | "content-standards" | "creative-ad-server" | "creative-generative" | "creative-template" | "creative-transformers" | "governance-aware-seller" | "governance-delivery-monitor" | "governance-spend-authority" | "property-lists" | "sales-broadcast-tv" | "sales-catalog-driven" | "sales-dooh" | "sales-guaranteed" | "sales-non-guaranteed" | "sales-proposal-mode" | "sales-social" | "signal-marketplace" | "signal-owned" | "signed-requests" | "sponsored-intelligence")[];
4163
4183
  /** @description Verification axes earned. 'spec' = AdCP storyboards pass for the declared specialisms. 'live' = AAO has observed real production traffic via canonical campaigns. Always non-empty when a badge is present; an absent badge is conveyed by the parent record being omitted, not by an empty array. */
4164
4184
  verification_modes: ("spec" | "live")[];
4165
4185
  verified_protocol_version: string | null;
@@ -6354,7 +6374,7 @@ export interface operations {
6354
6374
  };
6355
6375
  };
6356
6376
  responses: {
6357
- /** @description Authorization validation result */
6377
+ /** @description Publisher-property coverage result */
6358
6378
  200: {
6359
6379
  headers: {
6360
6380
  [name: string]: unknown;
@@ -6363,6 +6383,8 @@ export interface operations {
6363
6383
  "application/json": {
6364
6384
  agent_url: string;
6365
6385
  authorized: boolean;
6386
+ /** @enum {string} */
6387
+ validation_scope: "publisher_properties_only";
6366
6388
  checked_at: string;
6367
6389
  } & {
6368
6390
  [key: string]: unknown;
@@ -6371,6 +6393,109 @@ export interface operations {
6371
6393
  };
6372
6394
  };
6373
6395
  };
6396
+ verifySupplyPath: {
6397
+ parameters: {
6398
+ query?: never;
6399
+ header?: never;
6400
+ path?: never;
6401
+ cookie?: never;
6402
+ };
6403
+ requestBody?: {
6404
+ content: {
6405
+ "application/json": {
6406
+ /** @description Channel owner's publisher domain — where the canonical collection is declared. */
6407
+ owner_domain: string;
6408
+ /** @description Host publisher domain — where the carrying property (e.g. CTV app) is declared. */
6409
+ host_domain: string;
6410
+ /** @description Sales agent URL the buyer would transact with. Canonicalized server-side. */
6411
+ agent_url: string;
6412
+ /** @description Owner-assigned collection ID. Omit to verify the path at domain level (bulk deals). */
6413
+ collection_id?: string;
6414
+ };
6415
+ };
6416
+ };
6417
+ responses: {
6418
+ /** @description Supply-path verification verdict with per-leg evidence */
6419
+ 200: {
6420
+ headers: {
6421
+ [name: string]: unknown;
6422
+ };
6423
+ content: {
6424
+ "application/json": {
6425
+ /** @enum {string} */
6426
+ state: "verified_owner_sold" | "host_delegated" | "owner_attested" | "unverified";
6427
+ legs: {
6428
+ owner_collection_declared: {
6429
+ ok: boolean;
6430
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6431
+ failure?: string;
6432
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6433
+ detail?: string;
6434
+ } & {
6435
+ [key: string]: unknown;
6436
+ };
6437
+ owner_distribution_carriage: {
6438
+ ok: boolean;
6439
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6440
+ failure?: string;
6441
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6442
+ detail?: string;
6443
+ } & {
6444
+ [key: string]: unknown;
6445
+ };
6446
+ owner_agent_declared: {
6447
+ ok: boolean;
6448
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6449
+ failure?: string;
6450
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6451
+ detail?: string;
6452
+ } & {
6453
+ [key: string]: unknown;
6454
+ };
6455
+ host_authorization: {
6456
+ ok: boolean;
6457
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6458
+ failure?: string;
6459
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6460
+ detail?: string;
6461
+ } & {
6462
+ [key: string]: unknown;
6463
+ };
6464
+ inventory_partner_domain: {
6465
+ ok: boolean;
6466
+ /** @description Machine-readable reason this leg failed. Absent when ok. */
6467
+ failure?: string;
6468
+ /** @description Human-readable diagnosis for the failing (or notable) leg. */
6469
+ detail?: string;
6470
+ } & {
6471
+ [key: string]: unknown;
6472
+ };
6473
+ };
6474
+ owner_domain: string;
6475
+ host_domain: string;
6476
+ agent_url: string;
6477
+ collection_id?: string;
6478
+ sources: {
6479
+ owner_adagents_url: string;
6480
+ host_adagents_url: string;
6481
+ /** @description true: manifests came from the registry's crawl cache. Re-derive from the URLs above for enforcement. */
6482
+ cached: boolean;
6483
+ };
6484
+ checked_at: string;
6485
+ } & {
6486
+ [key: string]: unknown;
6487
+ };
6488
+ };
6489
+ };
6490
+ /** @description Invalid request body or uncanonicalizable domain */
6491
+ 400: {
6492
+ headers: {
6493
+ [name: string]: unknown;
6494
+ };
6495
+ content?: never;
6496
+ };
6497
+ };
6498
+ };
6374
6499
  expandProductIdentifiers: {
6375
6500
  parameters: {
6376
6501
  query?: never;
@@ -7962,6 +8087,13 @@ export interface operations {
7962
8087
  updated_at: string;
7963
8088
  /** @description Publisher-pinned JWK set (authorized_agents[*].signing_keys) from the source adagents.json. Consumers verifying inbound TMP signatures key on kid → JWK. Null when the publisher declared no keys; consumers fall back to the agent-hosted JWKS per spec R-2 (docs/governance/property/adagents.mdx). */
7964
8089
  signing_keys: components["schemas"]["SigningKey"][] | null;
8090
+ /** @description Collection constraints (authorized_agents[*].collections) from the source adagents.json. Null when the entry is unconstrained. When set, the row does NOT authorize the property unqualified — consumers MUST scope it to these selectors. A selector without collection_ids is a bulk grant for all collections declared at that publisher_domain. */
8091
+ collections: ({
8092
+ publisher_domain: string;
8093
+ collection_ids?: string[];
8094
+ } & {
8095
+ [key: string]: unknown;
8096
+ })[] | null;
7965
8097
  override_applied: boolean;
7966
8098
  override_reason: string | null;
7967
8099
  }[];
@@ -4,5 +4,5 @@
4
4
  "source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
5
5
  "source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
6
6
  "upstream_adcp_version": "2.5.3",
7
- "synced_at": "2026-08-30T07:58:59.416Z"
7
+ "synced_at": "2026-08-30T13:02:45.461Z"
8
8
  }
@@ -1221,19 +1221,20 @@ function asProductResponseForWire(canonicalResponse, wireMode, canonicalFormatLe
1221
1221
  );
1222
1222
  }
1223
1223
  if (!Array.isArray(canonicalResponse.products)) return canonicalResponse;
1224
- const products = canonicalResponse.products.map((product) => {
1224
+ const products = [];
1225
+ const diagnostics = [];
1226
+ for (const product of canonicalResponse.products) {
1225
1227
  const projected = (0, import_v2_to_v1.projectV2ProductToV1)(product, { canonicalFormatLegacyResolver });
1226
- if (projected.diagnostics.length > 0) {
1227
- const first = projected.diagnostics[0];
1228
- throw new import_async_outcome.AdcpError("INVALID_REQUEST", {
1229
- message: "get_products returned a canonical format that cannot be represented on the configured legacy wire.",
1230
- field: first.field,
1231
- suggestion: "Add an explicit legacy format mapping to the canonical declaration, or configure this server for AdCP 3.1 or newer."
1232
- });
1233
- }
1234
- return projected.v1;
1235
- });
1236
- return { ...canonicalResponse, products };
1228
+ diagnostics.push(...projected.diagnostics);
1229
+ if (projected.v1.format_ids.length > 0) products.push(projected.v1);
1230
+ }
1231
+ const responseErrors = canonicalResponse.errors;
1232
+ const errors = Array.isArray(responseErrors) ? [...responseErrors, ...diagnostics.map(import_augment_response.projectionDiagnosticToError)] : responseErrors === void 0 ? diagnostics.map(import_augment_response.projectionDiagnosticToError) : responseErrors;
1233
+ return {
1234
+ ...canonicalResponse,
1235
+ products,
1236
+ ...Array.isArray(errors) && errors.length > 0 ? { errors } : {}
1237
+ };
1237
1238
  }
1238
1239
  function refuseInlineAccountIdWhenForbidden(resolution, ref) {
1239
1240
  if (resolution !== "implicit" && resolution !== "derived") return;
@@ -90,7 +90,7 @@ import {
90
90
  import {
91
91
  legacyFormatConverterFromCatalogSnapshots
92
92
  } from "../../../v2/projection/catalog-snapshot.mjs";
93
- import { toCanonicalOnlyResponse } from "../../../v2/projection/augment-response.mjs";
93
+ import { projectionDiagnosticToError, toCanonicalOnlyResponse } from "../../../v2/projection/augment-response.mjs";
94
94
  import {
95
95
  CanonicalFormatLegacyResolutionError,
96
96
  projectV2ProductToV1,
@@ -1244,19 +1244,20 @@ function asProductResponseForWire(canonicalResponse, wireMode, canonicalFormatLe
1244
1244
  );
1245
1245
  }
1246
1246
  if (!Array.isArray(canonicalResponse.products)) return canonicalResponse;
1247
- const products = canonicalResponse.products.map((product) => {
1247
+ const products = [];
1248
+ const diagnostics = [];
1249
+ for (const product of canonicalResponse.products) {
1248
1250
  const projected = projectV2ProductToV1(product, { canonicalFormatLegacyResolver });
1249
- if (projected.diagnostics.length > 0) {
1250
- const first = projected.diagnostics[0];
1251
- throw new AdcpError("INVALID_REQUEST", {
1252
- message: "get_products returned a canonical format that cannot be represented on the configured legacy wire.",
1253
- field: first.field,
1254
- suggestion: "Add an explicit legacy format mapping to the canonical declaration, or configure this server for AdCP 3.1 or newer."
1255
- });
1256
- }
1257
- return projected.v1;
1258
- });
1259
- return { ...canonicalResponse, products };
1251
+ diagnostics.push(...projected.diagnostics);
1252
+ if (projected.v1.format_ids.length > 0) products.push(projected.v1);
1253
+ }
1254
+ const responseErrors = canonicalResponse.errors;
1255
+ const errors = Array.isArray(responseErrors) ? [...responseErrors, ...diagnostics.map(projectionDiagnosticToError)] : responseErrors === void 0 ? diagnostics.map(projectionDiagnosticToError) : responseErrors;
1256
+ return {
1257
+ ...canonicalResponse,
1258
+ products,
1259
+ ...Array.isArray(errors) && errors.length > 0 ? { errors } : {}
1260
+ };
1260
1261
  }
1261
1262
  function refuseInlineAccountIdWhenForbidden(resolution, ref) {
1262
1263
  if (resolution !== "implicit" && resolution !== "derived") return;
@@ -60,7 +60,6 @@ const TOOL_PROTOCOL_MAP = {
60
60
  get_creative_delivery: "creative",
61
61
  list_creative_formats: "creative",
62
62
  list_creatives: "creative",
63
- sync_creatives: "creative",
64
63
  // brand
65
64
  get_brand_identity: "brand",
66
65
  search_brands: "brand",
@@ -79,6 +78,10 @@ const TOOL_PROTOCOL_MAP = {
79
78
  sync_agent_notification_configs: "media-buy",
80
79
  create_media_buy: "media-buy",
81
80
  update_media_buy: "media-buy",
81
+ // The task-type schemas through AdCP 3.2 classify this dual-domain tool as
82
+ // media-buy. Keep lifecycle routing compatible even when a creative agent
83
+ // also implements the operation.
84
+ sync_creatives: "media-buy",
82
85
  media_buy_delivery: "media-buy",
83
86
  get_media_buy_delivery: "media-buy",
84
87
  sync_event_sources: "media-buy",
@@ -35,7 +35,6 @@ const TOOL_PROTOCOL_MAP = {
35
35
  get_creative_delivery: "creative",
36
36
  list_creative_formats: "creative",
37
37
  list_creatives: "creative",
38
- sync_creatives: "creative",
39
38
  // brand
40
39
  get_brand_identity: "brand",
41
40
  search_brands: "brand",
@@ -54,6 +53,10 @@ const TOOL_PROTOCOL_MAP = {
54
53
  sync_agent_notification_configs: "media-buy",
55
54
  create_media_buy: "media-buy",
56
55
  update_media_buy: "media-buy",
56
+ // The task-type schemas through AdCP 3.2 classify this dual-domain tool as
57
+ // media-buy. Keep lifecycle routing compatible even when a creative agent
58
+ // also implements the operation.
59
+ sync_creatives: "media-buy",
57
60
  media_buy_delivery: "media-buy",
58
61
  get_media_buy_delivery: "media-buy",
59
62
  sync_event_sources: "media-buy",
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "14.0.0-beta.21";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "14.0.0-beta.23";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "14.0.0-beta.21";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "14.0.0-beta.23";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "14.0.0-beta.21";
4
+ export declare const LIBRARY_VERSION = "14.0.0-beta.23";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "14.0.0-beta.21";
36
+ readonly library: "14.0.0-beta.23";
37
37
  readonly adcp: "3.2.0-beta.9";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0-beta.1", "3.0-beta.1", "3.0-beta", "3.0.0-beta.3", "3.0-beta.3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.2.0-beta.9", "3.2-beta.9"];
39
- readonly generatedAt: "2026-08-30T07:43:44.925Z";
39
+ readonly generatedAt: "2026-08-30T12:48:08.618Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "14.0.0-beta.21";
4
+ export declare const LIBRARY_VERSION = "14.0.0-beta.23";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "14.0.0-beta.21";
36
+ readonly library: "14.0.0-beta.23";
37
37
  readonly adcp: "3.2.0-beta.9";
38
38
  readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0-beta.1", "3.0-beta.1", "3.0-beta", "3.0.0-beta.3", "3.0-beta.3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.2.0-beta.9", "3.2-beta.9"];
39
- readonly generatedAt: "2026-08-30T07:43:44.925Z";
39
+ readonly generatedAt: "2026-08-30T12:48:08.618Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -31,7 +31,7 @@ __export(version_exports, {
31
31
  toReleasePrecisionVersion: () => toReleasePrecisionVersion
32
32
  });
33
33
  module.exports = __toCommonJS(version_exports);
34
- const LIBRARY_VERSION = "14.0.0-beta.21";
34
+ const LIBRARY_VERSION = "14.0.0-beta.23";
35
35
  const ADCP_VERSION = "3.2.0-beta.9";
36
36
  const ADCP_MAJOR_VERSION = 3;
37
37
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -94,10 +94,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
94
94
  "3.2-beta.9"
95
95
  ];
96
96
  const VERSION_INFO = {
97
- library: "14.0.0-beta.21",
97
+ library: "14.0.0-beta.23",
98
98
  adcp: "3.2.0-beta.9",
99
99
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
100
- generatedAt: "2026-08-30T07:43:44.925Z"
100
+ generatedAt: "2026-08-30T12:48:08.618Z"
101
101
  };
102
102
  function getAdcpVersion() {
103
103
  return ADCP_VERSION;
@@ -1,4 +1,4 @@
1
- const LIBRARY_VERSION = "14.0.0-beta.21";
1
+ const LIBRARY_VERSION = "14.0.0-beta.23";
2
2
  const ADCP_VERSION = "3.2.0-beta.9";
3
3
  const ADCP_MAJOR_VERSION = 3;
4
4
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -61,10 +61,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
61
61
  "3.2-beta.9"
62
62
  ];
63
63
  const VERSION_INFO = {
64
- library: "14.0.0-beta.21",
64
+ library: "14.0.0-beta.23",
65
65
  adcp: "3.2.0-beta.9",
66
66
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
67
- generatedAt: "2026-08-30T07:43:44.925Z"
67
+ generatedAt: "2026-08-30T12:48:08.618Z"
68
68
  };
69
69
  function getAdcpVersion() {
70
70
  return ADCP_VERSION;
package/docs/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ad Context Protocol (AdCP)
2
2
 
3
3
  > Generated at: 2026-08-30
4
- > Library: @adcp/sdk v14.0.0-beta.21
4
+ > Library: @adcp/sdk v14.0.0-beta.23
5
5
  > AdCP major version: 3
6
6
  > Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
7
7
  > Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcp/sdk",
3
- "version": "14.0.0-beta.21",
3
+ "version": "14.0.0-beta.23",
4
4
  "description": "AdCP SDK — client, server, and compliance harnesses for the AdContext Protocol (MCP + A2A)",
5
5
  "workspaces": [
6
6
  ".",