@adcp/sdk 16.0.0-beta.7 → 16.0.0-beta.8
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.
- package/README.md +17 -0
- package/dist/lib/conformance/index.d.mts +2 -0
- package/dist/lib/conformance/index.d.ts +2 -0
- package/dist/lib/conformance/index.js +3 -0
- package/dist/lib/conformance/index.mjs +2 -0
- package/dist/lib/conformance/property-lists.d.mts +14 -0
- package/dist/lib/conformance/property-lists.d.ts +14 -0
- package/dist/lib/conformance/property-lists.js +45 -0
- package/dist/lib/conformance/property-lists.mjs +21 -0
- package/dist/lib/conformance/runConformance.js +20 -1
- package/dist/lib/conformance/runConformance.mjs +20 -1
- package/dist/lib/conformance/types.d.mts +3 -0
- package/dist/lib/conformance/types.d.ts +3 -0
- package/dist/lib/core/SingleAgentClient.d.mts +13 -3
- package/dist/lib/core/SingleAgentClient.d.ts +13 -3
- package/dist/lib/core/SingleAgentClient.js +109 -21
- package/dist/lib/core/SingleAgentClient.mjs +112 -22
- package/dist/lib/identifiers.d.mts +53 -0
- package/dist/lib/identifiers.d.ts +53 -0
- package/dist/lib/identifiers.js +212 -0
- package/dist/lib/identifiers.mjs +163 -0
- package/dist/lib/index.d.mts +3 -1
- package/dist/lib/index.d.ts +3 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +1 -0
- package/dist/lib/media-buy/index.d.mts +1 -1
- package/dist/lib/media-buy/index.d.ts +1 -1
- package/dist/lib/media-buy/property-policy.d.mts +15 -1
- package/dist/lib/media-buy/property-policy.d.ts +15 -1
- package/dist/lib/media-buy/property-policy.js +135 -3
- package/dist/lib/media-buy/property-policy.mjs +134 -3
- package/dist/lib/registry/index.d.mts +12 -0
- package/dist/lib/registry/index.d.ts +12 -0
- package/dist/lib/registry/index.js +159 -5
- package/dist/lib/registry/index.mjs +156 -4
- package/dist/lib/registry/types.d.mts +23 -0
- package/dist/lib/registry/types.d.ts +23 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/specialisms/lists.d.mts +4 -4
- package/dist/lib/server/decisioning/specialisms/lists.d.ts +4 -4
- package/dist/lib/server/index.d.mts +3 -0
- package/dist/lib/server/index.d.ts +3 -0
- package/dist/lib/server/index.js +8 -1
- package/dist/lib/server/index.mjs +4 -0
- package/dist/lib/server/property-lists.d.mts +36 -0
- package/dist/lib/server/property-lists.d.ts +36 -0
- package/dist/lib/server/property-lists.js +154 -0
- package/dist/lib/server/property-lists.mjs +129 -0
- package/dist/lib/server/targeting-helpers.d.mts +2 -0
- package/dist/lib/server/targeting-helpers.d.ts +2 -0
- package/dist/lib/server/targeting-helpers.js +28 -1
- package/dist/lib/server/targeting-helpers.mjs +18 -1
- package/dist/lib/signing/parser.js +2 -2
- package/dist/lib/signing/parser.mjs +2 -2
- package/dist/lib/signing/server.d.mts +1 -1
- package/dist/lib/signing/server.d.ts +1 -1
- package/dist/lib/signing/server.mjs +5 -1
- package/dist/lib/signing/webhook-verifier.d.mts +11 -0
- package/dist/lib/signing/webhook-verifier.d.ts +11 -0
- package/dist/lib/signing/webhook-verifier.js +11 -3
- package/dist/lib/signing/webhook-verifier.mjs +11 -3
- package/dist/lib/supply-path/verify.js +12 -2
- package/dist/lib/supply-path/verify.mjs +2 -2
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/PROPERTY-LISTS.md +264 -0
- package/docs/guides/SIGNING-GUIDE.md +25 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var verify_exports = {};
|
|
20
30
|
__export(verify_exports, {
|
|
@@ -25,7 +35,6 @@ module.exports = __toCommonJS(verify_exports);
|
|
|
25
35
|
var import_abort = require('../protocols/abort.js');
|
|
26
36
|
var import_publisher_property_selector = require('../discovery/publisher-property-selector.js');
|
|
27
37
|
var import_validation = require('./validation.js');
|
|
28
|
-
var import_registry = require('../registry/index.js');
|
|
29
38
|
var import_fetch_evidence = require('./fetch-evidence.js');
|
|
30
39
|
var import_evaluate = require('./evaluate.js');
|
|
31
40
|
var import_validation2 = require('./validation.js');
|
|
@@ -34,7 +43,8 @@ const MAX_PROPERTY_SELECTOR_EXPANSIONS = 4096;
|
|
|
34
43
|
async function verifySupplyPath(request, options = { source: "authoritative" }) {
|
|
35
44
|
const normalized = (0, import_validation2.validateSupplyPathRequest)(request);
|
|
36
45
|
if (options.source === "registry") {
|
|
37
|
-
const
|
|
46
|
+
const registry = options.registry ?? new (await import("../registry/index.js")).RegistryClient();
|
|
47
|
+
const result = await registry.verifySupplyPath(normalized);
|
|
38
48
|
(0, import_validation2.assertRegistrySupplyPathResult)(result, normalized);
|
|
39
49
|
return result;
|
|
40
50
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
expandPublisherPropertySelector
|
|
5
5
|
} from "../discovery/publisher-property-selector.mjs";
|
|
6
6
|
import { domain, records, strings } from "./validation.mjs";
|
|
7
|
-
import { RegistryClient } from "../registry/index.mjs";
|
|
8
7
|
import { SupplyPathEvidenceSession } from "./fetch-evidence.mjs";
|
|
9
8
|
import {
|
|
10
9
|
isUnqualifiedPropertySelector,
|
|
@@ -20,7 +19,8 @@ const MAX_PROPERTY_SELECTOR_EXPANSIONS = 4096;
|
|
|
20
19
|
async function verifySupplyPath(request, options = { source: "authoritative" }) {
|
|
21
20
|
const normalized = validateSupplyPathRequest(request);
|
|
22
21
|
if (options.source === "registry") {
|
|
23
|
-
const
|
|
22
|
+
const registry = options.registry ?? new (await import("../registry/index.mjs")).RegistryClient();
|
|
23
|
+
const result = await registry.verifySupplyPath(normalized);
|
|
24
24
|
assertRegistrySupplyPathResult(result, normalized);
|
|
25
25
|
return result;
|
|
26
26
|
}
|
|
@@ -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 = "16.0.0-beta.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.0.0-beta.8";
|
|
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 = "16.0.0-beta.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.0.0-beta.8";
|
|
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
|
/**
|
package/dist/lib/version.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "16.0.0-beta.
|
|
4
|
+
export declare const LIBRARY_VERSION = "16.0.0-beta.8";
|
|
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: "16.0.0-beta.
|
|
36
|
+
readonly library: "16.0.0-beta.8";
|
|
37
37
|
readonly adcp: "3.2.5";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "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.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-18T01:21:23.594Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "16.0.0-beta.
|
|
4
|
+
export declare const LIBRARY_VERSION = "16.0.0-beta.8";
|
|
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: "16.0.0-beta.
|
|
36
|
+
readonly library: "16.0.0-beta.8";
|
|
37
37
|
readonly adcp: "3.2.5";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "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.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-18T01:21:23.594Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.js
CHANGED
|
@@ -31,7 +31,7 @@ __export(version_exports, {
|
|
|
31
31
|
toReleasePrecisionVersion: () => toReleasePrecisionVersion
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(version_exports);
|
|
34
|
-
const LIBRARY_VERSION = "16.0.0-beta.
|
|
34
|
+
const LIBRARY_VERSION = "16.0.0-beta.8";
|
|
35
35
|
const ADCP_VERSION = "3.2.5";
|
|
36
36
|
const ADCP_MAJOR_VERSION = 3;
|
|
37
37
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -104,10 +104,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
104
104
|
"3.2.5"
|
|
105
105
|
];
|
|
106
106
|
const VERSION_INFO = {
|
|
107
|
-
library: "16.0.0-beta.
|
|
107
|
+
library: "16.0.0-beta.8",
|
|
108
108
|
adcp: "3.2.5",
|
|
109
109
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
110
|
-
generatedAt: "2026-10-
|
|
110
|
+
generatedAt: "2026-10-18T01:21:23.594Z"
|
|
111
111
|
};
|
|
112
112
|
function getAdcpVersion() {
|
|
113
113
|
return ADCP_VERSION;
|
package/dist/lib/version.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LIBRARY_VERSION = "16.0.0-beta.
|
|
1
|
+
const LIBRARY_VERSION = "16.0.0-beta.8";
|
|
2
2
|
const ADCP_VERSION = "3.2.5";
|
|
3
3
|
const ADCP_MAJOR_VERSION = 3;
|
|
4
4
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -71,10 +71,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
71
71
|
"3.2.5"
|
|
72
72
|
];
|
|
73
73
|
const VERSION_INFO = {
|
|
74
|
-
library: "16.0.0-beta.
|
|
74
|
+
library: "16.0.0-beta.8",
|
|
75
75
|
adcp: "3.2.5",
|
|
76
76
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
77
|
-
generatedAt: "2026-10-
|
|
77
|
+
generatedAt: "2026-10-18T01:21:23.594Z"
|
|
78
78
|
};
|
|
79
79
|
function getAdcpVersion() {
|
|
80
80
|
return ADCP_VERSION;
|
package/docs/TYPE-SUMMARY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AdCP Type Summary
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> @adcp/sdk v16.0.0-beta.
|
|
3
|
+
> Generated at: 2026-10-18
|
|
4
|
+
> @adcp/sdk v16.0.0-beta.8
|
|
5
5
|
|
|
6
6
|
Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
|
|
7
7
|
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Property lists: matching, registry contribution, and serving
|
|
2
|
+
|
|
3
|
+
## Buyer enforcement
|
|
4
|
+
|
|
5
|
+
`validation.productPropertyPolicy` reads `get_products.filters.property_list`
|
|
6
|
+
and the deprecated top-level `property_list`. When both are present they must
|
|
7
|
+
have the same `agent_url`, `list_id`, and `auth_token`; conflicting references
|
|
8
|
+
fail closed with `property_list_conflicting_references`. A malformed nested
|
|
9
|
+
reference never falls back to the top-level field. The same reference is kept
|
|
10
|
+
for polling, tracking, and webhook completions.
|
|
11
|
+
|
|
12
|
+
These location and mixed-identifier fixes ship together. As before, request
|
|
13
|
+
list enforcement defaults to enabled. Set `enforceRequestPropertyList: false`
|
|
14
|
+
to disable local resolution, or `productPropertyPolicy: false` to disable the
|
|
15
|
+
policy entirely. Resolution errors (including a non-MCP list URL) fail closed.
|
|
16
|
+
|
|
17
|
+
Lists may mix domains, app bundles, and CTV store IDs. Non-domain types no
|
|
18
|
+
longer cause an unconditional response failure. A product's
|
|
19
|
+
`publisher_properties` contains publisher selectors, not app IDs: `property_ids`
|
|
20
|
+
are opaque names scoped to a publisher. Supply complete catalogs to match
|
|
21
|
+
their real identifiers:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { AdCPClient, type ProductPolicyResolvedProperty } from '@adcp/sdk';
|
|
25
|
+
|
|
26
|
+
declare const loadPublisherCatalog: (
|
|
27
|
+
domain: string
|
|
28
|
+
) => Promise<readonly ProductPolicyResolvedProperty[] | undefined>;
|
|
29
|
+
|
|
30
|
+
const client = new AdCPClient(agents, {
|
|
31
|
+
validation: {
|
|
32
|
+
productPropertyPolicy: {
|
|
33
|
+
enforceRequestPropertyList: true,
|
|
34
|
+
unknownSelectorBehavior: 'flag',
|
|
35
|
+
resolvePublisherProperties: loadPublisherCatalog,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The resolver receives normalized, untrusted publisher hostnames and an optional
|
|
42
|
+
`{ signal }` argument. It returns the complete
|
|
43
|
+
catalog of `{ property_id?, identifiers: [{ type, value }], tags? }` records
|
|
44
|
+
from your publisher metadata store or discovery layer. Alternatively provide
|
|
45
|
+
`publisherProperties: { [publisherDomain]: catalog }` directly. Keys use the exact
|
|
46
|
+
normalized publisher hostname, including `www.` when present; catalogs are not
|
|
47
|
+
shared across host aliases. When catalogs are configured, missing or failed
|
|
48
|
+
lookups mean unknown metadata; `[]` means a known empty catalog. This hook does
|
|
49
|
+
not initiate any additional registry or publisher lookups unless you implement
|
|
50
|
+
them. Identifier type and value must match exactly for non-domain identifiers;
|
|
51
|
+
bundle casing is preserved. `all`, `by_id`, and `by_tag` selectors are resolved
|
|
52
|
+
against these records. Products with `property_targeting_allowed: true` may
|
|
53
|
+
retain a proven eligible subset; other products must satisfy the policy for
|
|
54
|
+
every selected property.
|
|
55
|
+
|
|
56
|
+
Catalog loading is limited to 100 distinct lookups per response, 10 seconds
|
|
57
|
+
per lookup, and a 10-second total budget by default (`maxPublisherLookups`,
|
|
58
|
+
`publisherLookupTimeoutMs`, `publisherLookupBudgetMs`).
|
|
59
|
+
Overflow and failed/timed-out lookups stay unknown even when a domain matches.
|
|
60
|
+
Literal IP and localhost inputs do not reach the hook. For network discovery,
|
|
61
|
+
use the SDK's SSRF-safe networking utilities to protect DNS resolution too;
|
|
62
|
+
catalog identity/ownership verification remains the catalog provider's job.
|
|
63
|
+
|
|
64
|
+
Products whose membership cannot be judged follow `unknownSelectorBehavior`
|
|
65
|
+
(`allow`, `flag`, or `reject`). Request-derived policies remain strict by
|
|
66
|
+
default, so the default unknown behavior is `reject`; choose `flag` explicitly
|
|
67
|
+
to retain uncertain products. Known disallowed properties still reject even
|
|
68
|
+
when another property is unknown. Diagnostics appear under
|
|
69
|
+
`metadata.productPropertyPolicy`, including per-product
|
|
70
|
+
`unresolved_property_identifiers` / `identifier_types` and
|
|
71
|
+
`request_property_list.unsupported_identifier_types` for unrecognized types.
|
|
72
|
+
|
|
73
|
+
## Identifier normalization and registration
|
|
74
|
+
|
|
75
|
+
`normalizePropertyIdentifier(type, value)` (also exported as
|
|
76
|
+
`validatePropertyIdentifier`) returns either `{ ok: true, value, rewrite? }`
|
|
77
|
+
or `{ ok: false, error: IdentifierValidationError }`. Named normalizers cover
|
|
78
|
+
domain, subdomain, iOS/Android bundles, Apple/Google/Roku/Samsung store IDs,
|
|
79
|
+
Fire TV ASINs, and Apple TV/generic bundles. Each normalizer validates too.
|
|
80
|
+
|
|
81
|
+
Domain normalization accepts HTTP(S) URLs and reports their reduction to a
|
|
82
|
+
hostname, lowercases IDNs, and preserves wildcards. It preserves `www.` and
|
|
83
|
+
`m.` because removing those labels would broaden an explicit allowlist.
|
|
84
|
+
`subdomain` rejects wildcards. Platform names preserve case; numeric IDs stay
|
|
85
|
+
strings without losing precision. Formats for app/store identifiers are SDK
|
|
86
|
+
input hygiene rules, not assertions of registration, ownership, or existence.
|
|
87
|
+
Opaque identifier families retain their spelling (including station names
|
|
88
|
+
with spaces). Use these opt-in helpers before storing or matching values:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { normalizePropertyIdentifier } from '@adcp/sdk';
|
|
92
|
+
|
|
93
|
+
const checked = normalizePropertyIdentifier('domain', submittedValue);
|
|
94
|
+
if (!checked.ok) throw checked.error;
|
|
95
|
+
await identifierStore.save({ type: 'domain', value: checked.value });
|
|
96
|
+
// checked.rewrite, when present, records { from, to } for your review/audit UI.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`validatePublisherDomain(value)` is deliberately stricter: a publisher
|
|
100
|
+
registration must already be a lowercase bare hostname. URLs, wildcards,
|
|
101
|
+
ports, whitespace, trailing dots, malformed labels, and IP literals reject
|
|
102
|
+
with `IdentifierValidationError.code === 'invalid_publisher_domain'`.
|
|
103
|
+
`RegistryClient.saveProperty()` always performs this validation before HTTP.
|
|
104
|
+
`saveProperties()` uses the same check for every record; failed records retain
|
|
105
|
+
the existing `error` string and expose the typed error as `cause`.
|
|
106
|
+
|
|
107
|
+
## Bulk catalog contribution
|
|
108
|
+
|
|
109
|
+
`resolveIdentifiers()` in default `resolve` mode is the primary bulk catalog
|
|
110
|
+
registration path: it contributes provenance, creates missing entries, and
|
|
111
|
+
returns stable `property_rid` handles. Use `mode: 'lookup'` for read-only lookup.
|
|
112
|
+
A RID is a join handle and does not grant advertising authorization.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { RegistryClient, isRegistryRequestError } from '@adcp/sdk';
|
|
116
|
+
|
|
117
|
+
const registry = new RegistryClient({ apiKey: process.env.ADCP_REGISTRY_API_KEY });
|
|
118
|
+
const outcomes = await registry.resolveIdentifiersAll({
|
|
119
|
+
identifiers,
|
|
120
|
+
provenance: { type: 'agency_allowlist', context: campaignId },
|
|
121
|
+
// Omit mode to register/contribute. Use mode: 'lookup' for a pure read.
|
|
122
|
+
}, {
|
|
123
|
+
batchSize: 10_000,
|
|
124
|
+
maxRequestBytes: 1024 * 1024,
|
|
125
|
+
concurrency: 2,
|
|
126
|
+
maxRetries: 3,
|
|
127
|
+
maxRetryDelayMs: 60_000,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
for (const outcome of outcomes) {
|
|
131
|
+
if (outcome.success) useCatalogHandle(outcome.identifier, outcome.result.property_rid);
|
|
132
|
+
else if (isRegistryRequestError(outcome.error)) {
|
|
133
|
+
reportRegistryFailure(outcome.index, outcome.error.status, outcome.error.retryAfterMs);
|
|
134
|
+
} else reportInputFailure(outcome.index, outcome.error);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The helper caps each request at 10,000 identifiers and the configured UTF-8
|
|
139
|
+
JSON byte limit, including provenance. It limits concurrency, honors
|
|
140
|
+
`retryAfterMs` on HTTP 429, and returns an outcome for each input in input order,
|
|
141
|
+
including duplicates. Oversized individual items, missing/malformed response
|
|
142
|
+
entries, and failed batches become per-input errors; successful batches remain
|
|
143
|
+
available. Inputs should already use canonical identifier spelling so registry
|
|
144
|
+
results can be correlated by type and value. Empty input returns `[]`.
|
|
145
|
+
|
|
146
|
+
Only rate limits are retried automatically. A server delay exceeding
|
|
147
|
+
`maxRetryDelayMs` stops pending requests and returns the typed 429 (including
|
|
148
|
+
its `retryAfterMs`) for callers to reschedule, without retrying early.
|
|
149
|
+
Network and 5xx failures may have
|
|
150
|
+
already contributed activity: identifier-to-RID resolution is idempotent, but
|
|
151
|
+
the activity log is additive. The single-call API guards the 10,000-item limit;
|
|
152
|
+
use the helper for byte-based splitting. `/api/registry/resolve` accepts responses
|
|
153
|
+
up to 16 MiB by default; explicit `RegistryClientConfig.maxBodyBytes` still wins.
|
|
154
|
+
|
|
155
|
+
Use `saveProperty()` when publishing or updating hosted publisher
|
|
156
|
+
configuration (names, property identities, tags), rather than contributing a
|
|
157
|
+
large identifier catalog. `saveProperties()` is a bounded client-side fan-out
|
|
158
|
+
over that endpoint, intended for configuration updates. Its results are keyed
|
|
159
|
+
by publisher domain; submit one configuration per domain.
|
|
160
|
+
|
|
161
|
+
Registry HTTP failures use the exported `RegistryRequestError` /
|
|
162
|
+
`isRegistryRequestError` contract, with `status`, `method`, `retryAfterMs`, and
|
|
163
|
+
bounded untrusted `details`. Do not parse `error.message` for status or retry
|
|
164
|
+
timing. Input validation and transport failures are separate errors.
|
|
165
|
+
|
|
166
|
+
## Serve buyer-issued references over MCP
|
|
167
|
+
|
|
168
|
+
`registerPropertyListTool` registers a real MCP `get_property_list` tool using
|
|
169
|
+
the official MCP server. The reference's `auth_token` must authorize its exact
|
|
170
|
+
`list_id`. It arrives in `Authorization: Bearer` or `x-adcp-auth`, never as a
|
|
171
|
+
tool argument. The verifier runs before storage is read, on every page.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
175
|
+
import { serve } from '@adcp/sdk';
|
|
176
|
+
import { registerPropertyListTool } from '@adcp/sdk/server';
|
|
177
|
+
|
|
178
|
+
serve(() => {
|
|
179
|
+
const server = new McpServer({ name: 'Buyer property lists', version: '1.0.0' });
|
|
180
|
+
registerPropertyListTool(server, {
|
|
181
|
+
verifyToken: ({ listId, token }) => listStore.verifyListToken(listId, token),
|
|
182
|
+
loadPage: (request, principal) => listStore.loadAuthorizedPage(request, principal),
|
|
183
|
+
});
|
|
184
|
+
return server;
|
|
185
|
+
}, {
|
|
186
|
+
path: '/property-lists/mcp',
|
|
187
|
+
publicUrl: 'https://buyer.example/property-lists/mcp',
|
|
188
|
+
authenticate: listEndpointAuthenticator,
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Use your list endpoint's authenticator to validate list tokens globally and
|
|
193
|
+
return `{ principal, token }`; the per-tool verifier still checks exact list
|
|
194
|
+
access. Mount this read-only endpoint separately if your normal platform auth
|
|
195
|
+
only accepts account bearers. Its proxy/auth middleware must allow the list
|
|
196
|
+
token through. Ordinary MCP initialization needs no list ID. The helper also
|
|
197
|
+
supports raw HTTP headers when a transport does not populate `authInfo`.
|
|
198
|
+
It denies conflicting credentials and does not expose verifier/storage errors.
|
|
199
|
+
|
|
200
|
+
`loadPage` receives a verified principal and the validated request, including
|
|
201
|
+
`resolve` and `pagination`. Return `{ list, identifiers, pagination?,
|
|
202
|
+
resolved_at?, cache_valid_until? }`. The list includes at least `list_id` and
|
|
203
|
+
`name`; `identifiers` must be an array when resolving, including `[]` for an
|
|
204
|
+
empty list. For `resolve: false`, return metadata without resolving identifiers.
|
|
205
|
+
Honor the requested page limit (default 1,000; maximum 10,000). Provide a
|
|
206
|
+
nonempty continuation cursor only when `has_more` is true, and bind cursors to
|
|
207
|
+
the list, principal, and catalog revision. `list.property_count` is the total
|
|
208
|
+
property count, not the current page's identifier count. Return coherent
|
|
209
|
+
`cache_valid_until` timestamps across pages. The helper adds completion status
|
|
210
|
+
and echoes request context on success and errors.
|
|
211
|
+
|
|
212
|
+
Issue references whose `agent_url` points at this MCP endpoint. A plain REST
|
|
213
|
+
URL returning JSON does not implement `get_property_list`.
|
|
214
|
+
|
|
215
|
+
## Signed change notifications and certification
|
|
216
|
+
|
|
217
|
+
Use your configured SDK `WebhookEmitter` (or the emitter from
|
|
218
|
+
`createPostgresWebhookRuntime`) so signing, bounded retries, durable delivery
|
|
219
|
+
bindings, and crash recovery use the same infrastructure as other webhooks:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { sendPropertyListChanged } from '@adcp/sdk/server';
|
|
223
|
+
|
|
224
|
+
const result = await sendPropertyListChanged(
|
|
225
|
+
webhooks.emitter.forTenantScope(trustedTenantId),
|
|
226
|
+
{
|
|
227
|
+
url: subscriber.webhookUrl,
|
|
228
|
+
delivery_id: persistedDeliveryId,
|
|
229
|
+
notification: {
|
|
230
|
+
list_id: changedListId,
|
|
231
|
+
resolved_at: resolvedAt.toISOString(),
|
|
232
|
+
change_summary: { properties_added: added, properties_removed: removed, total_properties: total },
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Retain the same delivery ID and exact notification for retries. Each distinct
|
|
239
|
+
event/subscriber delivery needs its own ID. The helper selects RFC 9421,
|
|
240
|
+
includes the compatibility marker `signature: 'rfc9421'`, and lets the emitter
|
|
241
|
+
bind a stable cryptographic `idempotency_key`. It sends a summary; receivers
|
|
242
|
+
refresh through `get_property_list`. Configure production delivery storage,
|
|
243
|
+
recovery, signing keys, and per-attempt subscription authorization on the
|
|
244
|
+
emitter; see [the runtime reference](../TYPE-SUMMARY.md#postgresql-webhook-runtime).
|
|
245
|
+
|
|
246
|
+
Before certifying a buyer, resolve references it actually issued:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
import { runPropertyListConformance, runConformance } from '@adcp/sdk/conformance';
|
|
250
|
+
|
|
251
|
+
const report = await runPropertyListConformance(issuedReferences);
|
|
252
|
+
if (report.totalFailures) throw new Error('Buyer-issued property lists are not resolvable');
|
|
253
|
+
|
|
254
|
+
// Or include them in the main certification report/failure count:
|
|
255
|
+
const fullReport = await runConformance(buyerAgentUrl, {
|
|
256
|
+
propertyListReferences: issuedReferences,
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Certification disables caches, validates each resolved page, checks list
|
|
261
|
+
identity, rejects failure envelopes/oversized pages/cursor cycles, and uses
|
|
262
|
+
the same MCP resolver as sellers. Reports identify inputs by index and never
|
|
263
|
+
echo the reference token, URL, or remote exception. Empty lists are valid;
|
|
264
|
+
unresolvable references fail the report rather than silently certifying.
|
|
@@ -503,6 +503,31 @@ app.post('/webhook', async (req, res) => {
|
|
|
503
503
|
});
|
|
504
504
|
```
|
|
505
505
|
|
|
506
|
+
Webhook-v1 uses unpadded Base64URL for `Signature` throughout AdCP 3.x,
|
|
507
|
+
including 3.2. Its URL canonicalization follows AdCP 3.2 independently of
|
|
508
|
+
that encoding. The 3.2 request-signing migration to padded standard Base64
|
|
509
|
+
does not change the webhook-v1 profile. Python senders should use
|
|
510
|
+
`adcp.signing.webhook_signer.sign_webhook` rather than a generic
|
|
511
|
+
`sign_request` call with `signing_profile_version="3.2"` and the webhook tag.
|
|
512
|
+
See the [protocol's binary-value encoding rules](https://github.com/adcontextprotocol/adcp/blob/v3.2.5/docs/building/by-layer/L1/security.mdx#adcp-rfc-9421-profile).
|
|
513
|
+
|
|
514
|
+
When a known peer uses a generic RFC 9421 signer that emits standard padded
|
|
515
|
+
Base64, configure that receiver route explicitly:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
await verifyWebhookSignature(req, {
|
|
519
|
+
jwks,
|
|
520
|
+
replayStore,
|
|
521
|
+
revocationStore,
|
|
522
|
+
signatureEncoding: 'rfc8941-base64',
|
|
523
|
+
});
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
`createWebhookVerifier` accepts the same option. Each mode strictly parses
|
|
527
|
+
its configured encoding; neither retries the other encoding. Select this
|
|
528
|
+
option from trusted integration configuration, independently of incoming
|
|
529
|
+
headers or webhook payloads.
|
|
530
|
+
|
|
506
531
|
## Step 6: Sign Outbound Webhooks (Seller)
|
|
507
532
|
|
|
508
533
|
Configure `createAdcpServerFromPlatform` with a webhook signing key:
|
package/docs/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ad Context Protocol (AdCP)
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> Library: @adcp/sdk v16.0.0-beta.
|
|
3
|
+
> Generated at: 2026-10-18
|
|
4
|
+
> Library: @adcp/sdk v16.0.0-beta.8
|
|
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.
|
|
@@ -16,8 +16,8 @@ pin using `ADCP_VERSION` inside that tarball.
|
|
|
16
16
|
|
|
17
17
|
| Fact | Value |
|
|
18
18
|
| --- | --- |
|
|
19
|
-
| Checkout `package.json` version | `@adcp/sdk@16.0.0-beta.
|
|
20
|
-
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@16.0.0-beta.
|
|
19
|
+
| Checkout `package.json` version | `@adcp/sdk@16.0.0-beta.8` |
|
|
20
|
+
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@16.0.0-beta.8 dist.integrity` |
|
|
21
21
|
| Node.js runtime | `^20.19.0 || >=22.12.0` |
|
|
22
22
|
| Default AdCP wire release | `3.2.5` |
|
|
23
23
|
| Maintained wire releases | `v2.5`, `v2.6`, `v3`, `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.1.19`, `3.1.20`, `3.1.21`, `3.1.22`, `3.1.23`, `3.1.24`, `3.1.25`, `3.1.26`, `3.1.27`, `3.1.28`, `3.1.29`, `3.2.1`, `3.2`, `3.2.2`, `3.2.3`, `3.2.4`, `3.2.5` |
|
|
@@ -26,8 +26,8 @@ pin using `ADCP_VERSION` inside that tarball.
|
|
|
26
26
|
For a checkout at the published release commit, install the exact package version:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install --save-exact '@adcp/sdk@16.0.0-beta.
|
|
30
|
-
npm view '@adcp/sdk@16.0.0-beta.
|
|
29
|
+
npm install --save-exact '@adcp/sdk@16.0.0-beta.8'
|
|
30
|
+
npm view '@adcp/sdk@16.0.0-beta.8' dist.integrity
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
### Required and optional peers
|