@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.
Files changed (75) hide show
  1. package/README.md +17 -0
  2. package/dist/lib/conformance/index.d.mts +2 -0
  3. package/dist/lib/conformance/index.d.ts +2 -0
  4. package/dist/lib/conformance/index.js +3 -0
  5. package/dist/lib/conformance/index.mjs +2 -0
  6. package/dist/lib/conformance/property-lists.d.mts +14 -0
  7. package/dist/lib/conformance/property-lists.d.ts +14 -0
  8. package/dist/lib/conformance/property-lists.js +45 -0
  9. package/dist/lib/conformance/property-lists.mjs +21 -0
  10. package/dist/lib/conformance/runConformance.js +20 -1
  11. package/dist/lib/conformance/runConformance.mjs +20 -1
  12. package/dist/lib/conformance/types.d.mts +3 -0
  13. package/dist/lib/conformance/types.d.ts +3 -0
  14. package/dist/lib/core/SingleAgentClient.d.mts +13 -3
  15. package/dist/lib/core/SingleAgentClient.d.ts +13 -3
  16. package/dist/lib/core/SingleAgentClient.js +109 -21
  17. package/dist/lib/core/SingleAgentClient.mjs +112 -22
  18. package/dist/lib/identifiers.d.mts +53 -0
  19. package/dist/lib/identifiers.d.ts +53 -0
  20. package/dist/lib/identifiers.js +212 -0
  21. package/dist/lib/identifiers.mjs +163 -0
  22. package/dist/lib/index.d.mts +3 -1
  23. package/dist/lib/index.d.ts +3 -1
  24. package/dist/lib/index.js +2 -0
  25. package/dist/lib/index.mjs +1 -0
  26. package/dist/lib/media-buy/index.d.mts +1 -1
  27. package/dist/lib/media-buy/index.d.ts +1 -1
  28. package/dist/lib/media-buy/property-policy.d.mts +15 -1
  29. package/dist/lib/media-buy/property-policy.d.ts +15 -1
  30. package/dist/lib/media-buy/property-policy.js +135 -3
  31. package/dist/lib/media-buy/property-policy.mjs +134 -3
  32. package/dist/lib/registry/index.d.mts +12 -0
  33. package/dist/lib/registry/index.d.ts +12 -0
  34. package/dist/lib/registry/index.js +159 -5
  35. package/dist/lib/registry/index.mjs +156 -4
  36. package/dist/lib/registry/types.d.mts +23 -0
  37. package/dist/lib/registry/types.d.ts +23 -0
  38. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  39. package/dist/lib/server/decisioning/specialisms/lists.d.mts +4 -4
  40. package/dist/lib/server/decisioning/specialisms/lists.d.ts +4 -4
  41. package/dist/lib/server/index.d.mts +3 -0
  42. package/dist/lib/server/index.d.ts +3 -0
  43. package/dist/lib/server/index.js +8 -1
  44. package/dist/lib/server/index.mjs +4 -0
  45. package/dist/lib/server/property-lists.d.mts +36 -0
  46. package/dist/lib/server/property-lists.d.ts +36 -0
  47. package/dist/lib/server/property-lists.js +154 -0
  48. package/dist/lib/server/property-lists.mjs +129 -0
  49. package/dist/lib/server/targeting-helpers.d.mts +2 -0
  50. package/dist/lib/server/targeting-helpers.d.ts +2 -0
  51. package/dist/lib/server/targeting-helpers.js +28 -1
  52. package/dist/lib/server/targeting-helpers.mjs +18 -1
  53. package/dist/lib/signing/parser.js +2 -2
  54. package/dist/lib/signing/parser.mjs +2 -2
  55. package/dist/lib/signing/server.d.mts +1 -1
  56. package/dist/lib/signing/server.d.ts +1 -1
  57. package/dist/lib/signing/server.mjs +5 -1
  58. package/dist/lib/signing/webhook-verifier.d.mts +11 -0
  59. package/dist/lib/signing/webhook-verifier.d.ts +11 -0
  60. package/dist/lib/signing/webhook-verifier.js +11 -3
  61. package/dist/lib/signing/webhook-verifier.mjs +11 -3
  62. package/dist/lib/supply-path/verify.js +12 -2
  63. package/dist/lib/supply-path/verify.mjs +2 -2
  64. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  65. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  66. package/dist/lib/version.d.mts +3 -3
  67. package/dist/lib/version.d.ts +3 -3
  68. package/dist/lib/version.js +3 -3
  69. package/dist/lib/version.mjs +3 -3
  70. package/docs/TYPE-SUMMARY.md +2 -2
  71. package/docs/guides/PROPERTY-LISTS.md +264 -0
  72. package/docs/guides/SIGNING-GUIDE.md +25 -0
  73. package/docs/llms.txt +2 -2
  74. package/docs/migration-14.x-rc-worksheet.md +4 -4
  75. package/package.json +1 -1
@@ -1,3 +1,5 @@
1
+ import { validatePublisherDomain, IdentifierValidationError } from "../identifiers.mjs";
2
+ export * from "../identifiers.mjs";
1
3
  import { validateSupplyPathRequest, assertRegistrySupplyPathResult } from "../supply-path/validation.mjs";
2
4
  import { openFeedStream } from "./feed-stream.mjs";
3
5
  import { RegistrySync } from "./sync.mjs";
@@ -22,6 +24,9 @@ const ERROR_BODY_PREVIEW_CHARS = 200;
22
24
  const MAX_BRAND_BULK_DOMAINS = 25;
23
25
  const MAX_BULK_DOMAINS = 100;
24
26
  const MAX_CHECK_DOMAINS = 1e4;
27
+ const MAX_RESOLVE_IDENTIFIERS = 1e4;
28
+ const DEFAULT_RESOLVE_REQUEST_BYTES = 1024 * 1024;
29
+ const DEFAULT_RESOLVE_RESPONSE_BYTES = 16 * 1024 * 1024;
25
30
  const COMMUNITY_MIRROR_PLATFORM_RE = /^[a-z0-9_-]{1,64}$/;
26
31
  const MAX_REGISTRY_ERROR_DETAILS_BYTES = 64 * 1024;
27
32
  const MAX_RETRY_AFTER_MS = 2147483647;
@@ -274,7 +279,15 @@ class RegistryClient {
274
279
  }
275
280
  /** Save or update a hosted property. Requires authentication. */
276
281
  async saveProperty(property) {
277
- if (!property?.publisher_domain?.trim()) throw new Error("publisher_domain is required");
282
+ if (typeof property?.publisher_domain !== "string" || !property.publisher_domain.trim()) {
283
+ throw new IdentifierValidationError(
284
+ "invalid_publisher_domain",
285
+ "publisher_domain",
286
+ "publisher_domain is required"
287
+ );
288
+ }
289
+ const domain = validatePublisherDomain(property.publisher_domain);
290
+ if (!domain.ok) throw domain.error;
278
291
  if (!this.apiKey) throw new Error("apiKey is required for save operations");
279
292
  const payload = this.normalizeSavePropertyRequest(property);
280
293
  return this.post(`${this.baseUrl}/api/properties/save`, payload);
@@ -306,17 +319,19 @@ class RegistryClient {
306
319
  */
307
320
  async saveProperties(properties, options) {
308
321
  const concurrency = options?.concurrency ?? 5;
309
- const results = {};
322
+ if (!Number.isSafeInteger(concurrency) || concurrency < 1)
323
+ throw new RangeError("concurrency must be a positive integer");
324
+ const results = /* @__PURE__ */ Object.create(null);
310
325
  for (let i = 0; i < properties.length; i += concurrency) {
311
326
  const batch = properties.slice(i, i + concurrency);
312
327
  const settled = await Promise.allSettled(batch.map((p) => this.saveProperty(p)));
313
328
  for (let j = 0; j < batch.length; j++) {
314
329
  const domain = batch[j].publisher_domain;
315
330
  const s = settled[j];
316
- results[domain] = s.status === "fulfilled" ? s.value : { error: String(s.reason) };
331
+ results[domain] = s.status === "fulfilled" ? s.value : { error: String(s.reason), ...s.reason instanceof Error ? { cause: s.reason } : {} };
317
332
  }
318
333
  }
319
- return results;
334
+ return Object.fromEntries(Object.entries(results));
320
335
  }
321
336
  /**
322
337
  * Resolve catalog identifiers to stable property_rids.
@@ -325,11 +340,147 @@ class RegistryClient {
325
340
  */
326
341
  async resolveIdentifiers(request) {
327
342
  if (!request?.identifiers?.length) throw new Error("identifiers are required");
343
+ if (request.identifiers.length > MAX_RESOLVE_IDENTIFIERS) {
344
+ throw new RangeError("At most 10,000 identifiers are allowed; use resolveIdentifiersAll for larger lists");
345
+ }
328
346
  if ((request.mode ?? "resolve") !== "lookup" && !this.apiKey) {
329
347
  throw new Error("apiKey is required for resolveIdentifiers in resolve mode");
330
348
  }
331
349
  return this.post(`${this.baseUrl}/api/registry/resolve`, request);
332
350
  }
351
+ /**
352
+ * Bulk catalog registration (`resolve`, the default) or read-only `lookup`.
353
+ * Splits by identifier count and UTF-8 request bytes, bounds concurrency,
354
+ * and honors Retry-After on 429. Results retain input order and duplicates.
355
+ * Network/5xx failures are not retried: resolve contributions have additive
356
+ * activity logs even though identifier-to-RID mapping is idempotent.
357
+ */
358
+ async resolveIdentifiersAll(request, options = {}) {
359
+ const {
360
+ batchSize = MAX_RESOLVE_IDENTIFIERS,
361
+ maxRequestBytes = DEFAULT_RESOLVE_REQUEST_BYTES,
362
+ concurrency = 2,
363
+ maxRetries = 3,
364
+ maxRetryDelayMs = 6e4
365
+ } = options;
366
+ for (const [name, value, minimum] of [
367
+ ["batchSize", batchSize, 1],
368
+ ["maxRequestBytes", maxRequestBytes, 1],
369
+ ["concurrency", concurrency, 1],
370
+ ["maxRetries", maxRetries, 0],
371
+ ["maxRetryDelayMs", maxRetryDelayMs, 0]
372
+ ]) {
373
+ if (!Number.isSafeInteger(value) || value < minimum)
374
+ throw new RangeError(`${name} must be an integer >= ${minimum}`);
375
+ }
376
+ if (batchSize > MAX_RESOLVE_IDENTIFIERS) throw new RangeError("batchSize must not exceed 10,000");
377
+ if (!Array.isArray(request?.identifiers)) throw new TypeError("identifiers are required");
378
+ if ((request.mode ?? "resolve") !== "lookup" && !this.apiKey)
379
+ throw new Error("apiKey is required for resolveIdentifiers in resolve mode");
380
+ const { identifiers, ...envelope } = request;
381
+ const envelopeBytes = Buffer.byteLength(JSON.stringify({ ...envelope, identifiers: [] }), "utf8");
382
+ const outcomes = new Array(identifiers.length);
383
+ const batches = [];
384
+ let batch = { indexes: [], identifiers: [] };
385
+ let bytes = envelopeBytes;
386
+ for (const [index, identifier] of identifiers.entries()) {
387
+ if (!identifier || typeof identifier !== "object" || typeof identifier.type !== "string" || typeof identifier.value !== "string") {
388
+ outcomes[index] = {
389
+ index,
390
+ identifier,
391
+ success: false,
392
+ error: new TypeError("Identifier must contain string type and value")
393
+ };
394
+ continue;
395
+ }
396
+ const size = Buffer.byteLength(JSON.stringify(identifier), "utf8");
397
+ if (envelopeBytes + size > maxRequestBytes) {
398
+ outcomes[index] = {
399
+ index,
400
+ identifier,
401
+ success: false,
402
+ error: new RangeError("Identifier and provenance exceed maxRequestBytes")
403
+ };
404
+ continue;
405
+ }
406
+ if (batch.indexes.length && (batch.indexes.length >= batchSize || bytes + size + 1 > maxRequestBytes)) {
407
+ batches.push(batch);
408
+ batch = { indexes: [], identifiers: [] };
409
+ bytes = envelopeBytes;
410
+ }
411
+ bytes += size + (batch.indexes.length ? 1 : 0);
412
+ batch.indexes.push(index);
413
+ batch.identifiers.push(identifier);
414
+ }
415
+ if (batch.indexes.length) batches.push(batch);
416
+ let nextBatch = 0;
417
+ let retryNotBefore = 0;
418
+ let rateLimitFailure;
419
+ const worker = async () => {
420
+ while (nextBatch < batches.length) {
421
+ const current = batches[nextBatch++];
422
+ let response;
423
+ let failure;
424
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
425
+ if (rateLimitFailure) {
426
+ failure = rateLimitFailure;
427
+ break;
428
+ }
429
+ while (!rateLimitFailure && retryNotBefore > Date.now())
430
+ await new Promise(
431
+ (resolve) => setTimeout(resolve, Math.min(retryNotBefore - Date.now(), MAX_RETRY_AFTER_MS))
432
+ );
433
+ if (rateLimitFailure) {
434
+ failure = rateLimitFailure;
435
+ break;
436
+ }
437
+ try {
438
+ response = await this.resolveIdentifiers({ ...envelope, identifiers: current.identifiers });
439
+ if (!response || !Array.isArray(response.resolved)) {
440
+ throw new TypeError("Registry returned an invalid identifier resolution response");
441
+ }
442
+ break;
443
+ } catch (error) {
444
+ response = void 0;
445
+ failure = error instanceof Error ? error : new Error("Registry resolution failed");
446
+ if (!isRegistryRequestError(error) || error.status !== 429) break;
447
+ const delay = typeof error.retryAfterMs === "number" && Number.isFinite(error.retryAfterMs) && error.retryAfterMs >= 0 ? error.retryAfterMs : Math.min(1e3 * 2 ** attempt, 3e4);
448
+ if (delay > maxRetryDelayMs) {
449
+ rateLimitFailure = error;
450
+ break;
451
+ }
452
+ retryNotBefore = Math.max(retryNotBefore, Date.now() + delay);
453
+ if (attempt === maxRetries) break;
454
+ }
455
+ }
456
+ const entries = /* @__PURE__ */ new Map();
457
+ let malformedEntries = false;
458
+ for (const entry of response?.resolved ?? []) {
459
+ if (!entry || typeof entry !== "object" || !entry.identifier || typeof entry.identifier.type !== "string" || typeof entry.identifier.value !== "string" || entry.property_rid !== null && typeof entry.property_rid !== "string" || !["existing", "created", "excluded"].includes(entry.status)) {
460
+ malformedEntries = true;
461
+ continue;
462
+ }
463
+ const key = JSON.stringify([entry.identifier.type, entry.identifier.value]);
464
+ const group = entries.get(key) ?? [];
465
+ group.push(entry);
466
+ entries.set(key, group);
467
+ }
468
+ for (const index of current.indexes) {
469
+ const identifier = identifiers[index];
470
+ const group = entries.get(JSON.stringify([identifier.type, identifier.value]));
471
+ const entry = group && (group.length > 1 ? group.shift() : group[0]);
472
+ outcomes[index] = entry ? { index, identifier, success: true, result: entry } : {
473
+ index,
474
+ identifier,
475
+ success: false,
476
+ error: response ? malformedEntries ? new TypeError("Registry returned an invalid identifier resolution response") : new Error("Registry response omitted identifier") : failure
477
+ };
478
+ }
479
+ }
480
+ };
481
+ await Promise.all(Array.from({ length: Math.min(concurrency, batches.length) }, worker));
482
+ return outcomes;
483
+ }
333
484
  /** File a catalog fact dispute. Requires authentication. */
334
485
  async fileCatalogDispute(request) {
335
486
  if (!request?.subject_type?.trim()) throw new Error("subject_type is required");
@@ -1101,6 +1252,7 @@ class RegistryClient {
1101
1252
  bodyLimitForUrl(url) {
1102
1253
  if (this.hasCustomMaxBodyBytes) return this.maxBodyBytes;
1103
1254
  const path = new URL(url).pathname;
1255
+ if (path === "/api/registry/resolve") return DEFAULT_RESOLVE_RESPONSE_BYTES;
1104
1256
  if (path === "/api/brands/registry" || path === "/api/brands/resolve/bulk" || path === "/api/properties/registry" || path === "/api/properties/resolve/bulk" || path === "/api/registry/agents" || path === "/api/registry/publishers" || path === "/api/registry/feed" || path === "/api/registry/mirrors" || path === "/api/registry/agents/search" || path === "/api/registry/authorizations" || path === "/api/registry/authorizations/snapshot" || path === "/api/search" || path === "/api/policies/registry" || path === "/api/policies/resolve/bulk" || path === "/api/public/discover-agent" || path === "/api/public/agent-formats" || path === "/api/public/agent-products" || path === "/api/public/validate-publisher" || path === "/api/registry/agents/storyboard-status" || path.startsWith("/api/registry/agents/") && path.endsWith("/storyboard-status") || path.startsWith("/api/registry/mirrors/") || path.startsWith("/api/properties/check")) {
1105
1257
  return DEFAULT_LARGE_RESPONSE_MAX_BODY_BYTES;
1106
1258
  }
@@ -150,6 +150,29 @@ export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest,
150
150
  };
151
151
  /** Response from POST /api/registry/resolve (200) */
152
152
  export type ResolveIdentifiersResponse = operations['resolveIdentifiers']['responses']['200']['content']['application/json'];
153
+ export interface ResolveIdentifiersAllOptions {
154
+ /** Per-request identifier cap, from 1 through the registry limit of 10,000. */
155
+ batchSize?: number;
156
+ /** UTF-8 JSON request cap including provenance and envelope. Default: 1 MiB. */
157
+ maxRequestBytes?: number;
158
+ /** Maximum simultaneous requests. Default: 2. */
159
+ concurrency?: number;
160
+ /** Retries for HTTP 429 only. Other failures are returned without retrying contributions. Default: 3. */
161
+ maxRetries?: number;
162
+ /** Maximum server-requested retry delay. Default: 60 seconds; longer rate limits return errors without early retries. */
163
+ maxRetryDelayMs?: number;
164
+ }
165
+ /** One outcome per input, in input order (including duplicates). */
166
+ export type ResolveIdentifierOutcome = {
167
+ index: number;
168
+ identifier: ResolveIdentifiersRequest['identifiers'][number];
169
+ } & ({
170
+ success: true;
171
+ result: ResolveIdentifiersResponse['resolved'][number];
172
+ } | {
173
+ success: false;
174
+ error: Error;
175
+ });
153
176
  /** Request body for POST /api/registry/catalog/disputes */
154
177
  export type FileCatalogDisputeRequest = NonNullable<operations['fileCatalogDispute']['requestBody']>['content']['application/json'];
155
178
  /** Response from POST /api/registry/catalog/disputes (200) */
@@ -150,6 +150,29 @@ export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest,
150
150
  };
151
151
  /** Response from POST /api/registry/resolve (200) */
152
152
  export type ResolveIdentifiersResponse = operations['resolveIdentifiers']['responses']['200']['content']['application/json'];
153
+ export interface ResolveIdentifiersAllOptions {
154
+ /** Per-request identifier cap, from 1 through the registry limit of 10,000. */
155
+ batchSize?: number;
156
+ /** UTF-8 JSON request cap including provenance and envelope. Default: 1 MiB. */
157
+ maxRequestBytes?: number;
158
+ /** Maximum simultaneous requests. Default: 2. */
159
+ concurrency?: number;
160
+ /** Retries for HTTP 429 only. Other failures are returned without retrying contributions. Default: 3. */
161
+ maxRetries?: number;
162
+ /** Maximum server-requested retry delay. Default: 60 seconds; longer rate limits return errors without early retries. */
163
+ maxRetryDelayMs?: number;
164
+ }
165
+ /** One outcome per input, in input order (including duplicates). */
166
+ export type ResolveIdentifierOutcome = {
167
+ index: number;
168
+ identifier: ResolveIdentifiersRequest['identifiers'][number];
169
+ } & ({
170
+ success: true;
171
+ result: ResolveIdentifiersResponse['resolved'][number];
172
+ } | {
173
+ success: false;
174
+ error: Error;
175
+ });
153
176
  /** Request body for POST /api/registry/catalog/disputes */
154
177
  export type FileCatalogDisputeRequest = NonNullable<operations['fileCatalogDispute']['requestBody']>['content']['application/json'];
155
178
  /** Response from POST /api/registry/catalog/disputes (200) */
@@ -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-10-17T14:29:51.574Z"
7
+ "synced_at": "2026-10-18T02:15:53.357Z"
8
8
  }
@@ -21,7 +21,7 @@
21
21
  * one-time fetch token sellers store in their secret manager; `delete_*`
22
22
  * revokes the token. Tokens are scoped per-seller for revocation.
23
23
  *
24
- * Status: Preview / 6.0.
24
+ * For standalone list-token reads, use registerPropertyListTool from @adcp/sdk/server.
25
25
  *
26
26
  * @public
27
27
  */
@@ -42,19 +42,19 @@ export type ListCollectionListsPayload = ServerPayload<ListCollectionListsRespon
42
42
  export type DeleteCollectionListPayload = ServerPayload<DeleteCollectionListResponse>;
43
43
  export interface PropertyListsPlatform<TCtxMeta = Record<string, unknown>> {
44
44
  /**
45
- * Create a property list. Returns a `fetch_token` the buyer stores in
45
+ * Create a property list. Returns an `auth_token` the buyer stores in
46
46
  * their secret manager. Token is scoped to this list_id; MUST NOT be
47
47
  * reused across lists.
48
48
  */
49
49
  createPropertyList(req: CreatePropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<CreatePropertyListPayload>;
50
50
  /** Patch an existing property list. */
51
51
  updatePropertyList(req: UpdatePropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<UpdatePropertyListPayload>;
52
- /** Read a property list by id. Sellers call this with the fetch_token. */
52
+ /** Read a property list by id. Sellers call this with the auth_token. */
53
53
  getPropertyList(req: GetPropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<GetPropertyListPayload>;
54
54
  /** Discover property lists the caller is authorized to read. */
55
55
  listPropertyLists(req: ListPropertyListsRequest, ctx: Ctx<TCtxMeta>): Promise<ListPropertyListsPayload>;
56
56
  /**
57
- * Delete a property list. MUST revoke the fetch_token immediately and
57
+ * Delete a property list. MUST revoke the auth_token immediately and
58
58
  * signal cache invalidation to sellers (reduced cache_valid_until or
59
59
  * a list-changed webhook). Compromise-driven revocation MUST also
60
60
  * trigger this path.
@@ -21,7 +21,7 @@
21
21
  * one-time fetch token sellers store in their secret manager; `delete_*`
22
22
  * revokes the token. Tokens are scoped per-seller for revocation.
23
23
  *
24
- * Status: Preview / 6.0.
24
+ * For standalone list-token reads, use registerPropertyListTool from @adcp/sdk/server.
25
25
  *
26
26
  * @public
27
27
  */
@@ -42,19 +42,19 @@ export type ListCollectionListsPayload = ServerPayload<ListCollectionListsRespon
42
42
  export type DeleteCollectionListPayload = ServerPayload<DeleteCollectionListResponse>;
43
43
  export interface PropertyListsPlatform<TCtxMeta = Record<string, unknown>> {
44
44
  /**
45
- * Create a property list. Returns a `fetch_token` the buyer stores in
45
+ * Create a property list. Returns an `auth_token` the buyer stores in
46
46
  * their secret manager. Token is scoped to this list_id; MUST NOT be
47
47
  * reused across lists.
48
48
  */
49
49
  createPropertyList(req: CreatePropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<CreatePropertyListPayload>;
50
50
  /** Patch an existing property list. */
51
51
  updatePropertyList(req: UpdatePropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<UpdatePropertyListPayload>;
52
- /** Read a property list by id. Sellers call this with the fetch_token. */
52
+ /** Read a property list by id. Sellers call this with the auth_token. */
53
53
  getPropertyList(req: GetPropertyListRequest, ctx: Ctx<TCtxMeta>): Promise<GetPropertyListPayload>;
54
54
  /** Discover property lists the caller is authorized to read. */
55
55
  listPropertyLists(req: ListPropertyListsRequest, ctx: Ctx<TCtxMeta>): Promise<ListPropertyListsPayload>;
56
56
  /**
57
- * Delete a property list. MUST revoke the fetch_token immediately and
57
+ * Delete a property list. MUST revoke the auth_token immediately and
58
58
  * signal cache invalidation to sellers (reduced cache_valid_until or
59
59
  * a list-changed webhook). Compromise-driven revocation MUST also
60
60
  * trigger this path.
@@ -105,3 +105,6 @@ export { createDerivedAccountStore, type DerivedAccountStoreOptions, type Derive
105
105
  export { ConformanceClient, WebSocketTransport, type ConformanceClientOptions, type ConformanceStatus, } from './socket-mode/index.mjs';
106
106
  export { mediaBuyActionResolver } from './media-buy-action-resolver.mjs';
107
107
  export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './media-buy-action-resolver.mjs';
108
+ export * from '../identifiers.mjs';
109
+ export { registerPropertyListTool, sendPropertyListChanged } from './property-lists.mjs';
110
+ export type { PropertyListPage, PropertyListToolOptions, PropertyListChangedNotification, SendPropertyListChangedOptions, } from './property-lists.mjs';
@@ -105,3 +105,6 @@ export { createDerivedAccountStore, type DerivedAccountStoreOptions, type Derive
105
105
  export { ConformanceClient, WebSocketTransport, type ConformanceClientOptions, type ConformanceStatus, } from './socket-mode';
106
106
  export { mediaBuyActionResolver } from './media-buy-action-resolver';
107
107
  export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './media-buy-action-resolver';
108
+ export * from '../identifiers';
109
+ export { registerPropertyListTool, sendPropertyListChanged } from './property-lists';
110
+ export type { PropertyListPage, PropertyListToolOptions, PropertyListChangedNotification, SendPropertyListChangedOptions, } from './property-lists';
@@ -254,6 +254,7 @@ __export(server_exports, {
254
254
  redisWebhookDeliveryRecoveryBackend: () => import_webhook_delivery.redisWebhookDeliveryRecoveryBackend,
255
255
  redisWebhookDeliveryStore: () => import_webhook_delivery.redisWebhookDeliveryStore,
256
256
  registerAdcpTaskTool: () => import_tasks.registerAdcpTaskTool,
257
+ registerPropertyListTool: () => import_property_lists.registerPropertyListTool,
257
258
  registerTestController: () => import_test_controller.registerTestController,
258
259
  replaceAccountFinancialsIfSeeded: () => import_test_controller_bridge.replaceAccountFinancialsIfSeeded,
259
260
  requireAuthenticatedOrSigned: () => import_auth_signature.requireAuthenticatedOrSigned,
@@ -269,6 +270,7 @@ __export(server_exports, {
269
270
  scopeCtxMetadataKey: () => import_ctx_metadata.scopeCtxMetadataKey,
270
271
  scopedStore: () => import_state_store.scopedStore,
271
272
  scrubExtensions: () => import_wire_safe.scrubExtensions,
273
+ sendPropertyListChanged: () => import_property_lists.sendPropertyListChanged,
272
274
  serve: () => import_serve.serve,
273
275
  signatureErrorCodeFromCause: () => import_auth.signatureErrorCodeFromCause,
274
276
  stripCtxMetadata: () => import_ctx_metadata.stripCtxMetadata,
@@ -353,6 +355,8 @@ var import_keyed_account_backend = require('../adapters/keyed-account-backend.js
353
355
  var import_derived_account_store = require('../adapters/derived-account-store.js');
354
356
  var import_socket_mode = require('./socket-mode/index.js');
355
357
  var import_media_buy_action_resolver = require('./media-buy-action-resolver.js');
358
+ __reExport(server_exports, require('../identifiers.js'), module.exports);
359
+ var import_property_lists = require('./property-lists.js');
356
360
  // Annotate the CommonJS export names for ESM import in node:
357
361
  0 && (module.exports = {
358
362
  A2AInvocationError,
@@ -590,6 +594,7 @@ var import_media_buy_action_resolver = require('./media-buy-action-resolver.js')
590
594
  redisWebhookDeliveryRecoveryBackend,
591
595
  redisWebhookDeliveryStore,
592
596
  registerAdcpTaskTool,
597
+ registerPropertyListTool,
593
598
  registerTestController,
594
599
  replaceAccountFinancialsIfSeeded,
595
600
  requireAuthenticatedOrSigned,
@@ -605,6 +610,7 @@ var import_media_buy_action_resolver = require('./media-buy-action-resolver.js')
605
610
  scopeCtxMetadataKey,
606
611
  scopedStore,
607
612
  scrubExtensions,
613
+ sendPropertyListChanged,
608
614
  serve,
609
615
  signatureErrorCodeFromCause,
610
616
  stripCtxMetadata,
@@ -631,5 +637,6 @@ var import_media_buy_action_resolver = require('./media-buy-action-resolver.js')
631
637
  verifyProposalTermsDigest,
632
638
  verifySignatureAsAuthenticator,
633
639
  wrapEnvelope,
634
- ...require('./decisioning/index.js')
640
+ ...require('./decisioning/index.js'),
641
+ ...require('../identifiers.js')
635
642
  });
@@ -302,6 +302,8 @@ import {
302
302
  WebSocketTransport
303
303
  } from "./socket-mode/index.mjs";
304
304
  import { mediaBuyActionResolver } from "./media-buy-action-resolver.mjs";
305
+ export * from "../identifiers.mjs";
306
+ import { registerPropertyListTool, sendPropertyListChanged } from "./property-lists.mjs";
305
307
  export {
306
308
  A2AInvocationError,
307
309
  ACCOUNT_NOTIFICATION_TYPES,
@@ -538,6 +540,7 @@ export {
538
540
  redisWebhookDeliveryRecoveryBackend,
539
541
  redisWebhookDeliveryStore,
540
542
  registerAdcpTaskTool,
543
+ registerPropertyListTool,
541
544
  registerTestController,
542
545
  replaceAccountFinancialsIfSeeded,
543
546
  requireAuthenticatedOrSigned,
@@ -553,6 +556,7 @@ export {
553
556
  scopeCtxMetadataKey,
554
557
  scopedStore,
555
558
  scrubExtensions,
559
+ sendPropertyListChanged,
556
560
  serve,
557
561
  signatureErrorCodeFromCause,
558
562
  stripCtxMetadata,
@@ -0,0 +1,36 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { GetPropertyListRequest, GetPropertyListResponse } from '../types/tools.generated.mjs';
3
+ import type { WebhookEmitter, WebhookEmitParams, WebhookEmitResult } from './webhook-emitter.mjs';
4
+ export type PropertyListPage = Pick<GetPropertyListResponse, 'list' | 'identifiers' | 'pagination' | 'resolved_at' | 'cache_valid_until' | 'coverage_gaps'>;
5
+ export interface PropertyListToolOptions<TPrincipal> {
6
+ /** Verify this token's access to this exact list on every request/page. Return null/false to deny access. */
7
+ verifyToken: (input: {
8
+ listId: string;
9
+ token: string;
10
+ }) => TPrincipal | null | false | Promise<TPrincipal | null | false>;
11
+ /** Load an authorized page. Honor resolve:false without resolving identifiers. Cursors must be bound to the list and principal. */
12
+ loadPage: (request: GetPropertyListRequest, principal: TPrincipal) => Promise<PropertyListPage>;
13
+ }
14
+ /**
15
+ * Register a read-only MCP tool using per-list tokens, independently of normal
16
+ * platform account credentials. Tokens arrive through Authorization: Bearer
17
+ * or x-adcp-auth, never tool arguments. Mount on an MCP endpoint whose HTTP
18
+ * auth layer permits list tokens through to this verifier.
19
+ */
20
+ export declare function registerPropertyListTool<TPrincipal>(server: McpServer, options: PropertyListToolOptions<TPrincipal>): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredTool;
21
+ export interface PropertyListChangedNotification {
22
+ list_id: string;
23
+ list_name?: string;
24
+ resolved_at: string;
25
+ cache_valid_until?: string;
26
+ change_summary?: {
27
+ properties_added?: number;
28
+ properties_removed?: number;
29
+ total_properties?: number;
30
+ };
31
+ }
32
+ export type SendPropertyListChangedOptions = Pick<WebhookEmitParams, 'url' | 'delivery_id' | 'retries' | 'attemptAuthorizationContext'> & {
33
+ notification: PropertyListChangedNotification;
34
+ };
35
+ /** Send a summary-only notification through the SDK's signed, retrying delivery kernel. Reuse delivery_id and notification for retries. */
36
+ export declare function sendPropertyListChanged(emitter: WebhookEmitter, options: SendPropertyListChangedOptions): Promise<WebhookEmitResult>;
@@ -0,0 +1,36 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { GetPropertyListRequest, GetPropertyListResponse } from '../types/tools.generated';
3
+ import type { WebhookEmitter, WebhookEmitParams, WebhookEmitResult } from './webhook-emitter';
4
+ export type PropertyListPage = Pick<GetPropertyListResponse, 'list' | 'identifiers' | 'pagination' | 'resolved_at' | 'cache_valid_until' | 'coverage_gaps'>;
5
+ export interface PropertyListToolOptions<TPrincipal> {
6
+ /** Verify this token's access to this exact list on every request/page. Return null/false to deny access. */
7
+ verifyToken: (input: {
8
+ listId: string;
9
+ token: string;
10
+ }) => TPrincipal | null | false | Promise<TPrincipal | null | false>;
11
+ /** Load an authorized page. Honor resolve:false without resolving identifiers. Cursors must be bound to the list and principal. */
12
+ loadPage: (request: GetPropertyListRequest, principal: TPrincipal) => Promise<PropertyListPage>;
13
+ }
14
+ /**
15
+ * Register a read-only MCP tool using per-list tokens, independently of normal
16
+ * platform account credentials. Tokens arrive through Authorization: Bearer
17
+ * or x-adcp-auth, never tool arguments. Mount on an MCP endpoint whose HTTP
18
+ * auth layer permits list tokens through to this verifier.
19
+ */
20
+ export declare function registerPropertyListTool<TPrincipal>(server: McpServer, options: PropertyListToolOptions<TPrincipal>): import("@modelcontextprotocol/sdk/server/mcp.js").RegisteredTool;
21
+ export interface PropertyListChangedNotification {
22
+ list_id: string;
23
+ list_name?: string;
24
+ resolved_at: string;
25
+ cache_valid_until?: string;
26
+ change_summary?: {
27
+ properties_added?: number;
28
+ properties_removed?: number;
29
+ total_properties?: number;
30
+ };
31
+ }
32
+ export type SendPropertyListChangedOptions = Pick<WebhookEmitParams, 'url' | 'delivery_id' | 'retries' | 'attemptAuthorizationContext'> & {
33
+ notification: PropertyListChangedNotification;
34
+ };
35
+ /** Send a summary-only notification through the SDK's signed, retrying delivery kernel. Reuse delivery_id and notification for retries. */
36
+ export declare function sendPropertyListChanged(emitter: WebhookEmitter, options: SendPropertyListChangedOptions): Promise<WebhookEmitResult>;