@adcp/sdk 14.0.0-rc.39 → 14.0.0-rc.40

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 (81) hide show
  1. package/README.md +2 -0
  2. package/dist/lib/core/AgentClient.d.mts +4 -3
  3. package/dist/lib/core/AgentClient.d.ts +4 -3
  4. package/dist/lib/core/AsyncHandler.d.mts +3 -0
  5. package/dist/lib/core/AsyncHandler.d.ts +3 -0
  6. package/dist/lib/core/AsyncHandler.js +3 -0
  7. package/dist/lib/core/AsyncHandler.mjs +3 -0
  8. package/dist/lib/core/SingleAgentClient.d.mts +6 -1
  9. package/dist/lib/core/SingleAgentClient.d.ts +6 -1
  10. package/dist/lib/core/SingleAgentClient.js +57 -17
  11. package/dist/lib/core/SingleAgentClient.mjs +59 -17
  12. package/dist/lib/discovery/adagents-redirects.d.mts +5 -1
  13. package/dist/lib/discovery/adagents-redirects.d.ts +5 -1
  14. package/dist/lib/discovery/adagents-redirects.js +10 -3
  15. package/dist/lib/discovery/adagents-redirects.mjs +10 -3
  16. package/dist/lib/discovery/types.d.mts +42 -0
  17. package/dist/lib/discovery/types.d.ts +42 -0
  18. package/dist/lib/index.d.mts +3 -1
  19. package/dist/lib/index.d.ts +3 -1
  20. package/dist/lib/index.js +3 -1
  21. package/dist/lib/index.mjs +1 -0
  22. package/dist/lib/net/ssrf-fetch.js +47 -21
  23. package/dist/lib/net/ssrf-fetch.mjs +47 -21
  24. package/dist/lib/registry/index.d.mts +3 -0
  25. package/dist/lib/registry/index.d.ts +3 -0
  26. package/dist/lib/registry/index.js +8 -0
  27. package/dist/lib/registry/index.mjs +8 -0
  28. package/dist/lib/registry/types.d.mts +2 -1
  29. package/dist/lib/registry/types.d.ts +2 -1
  30. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  31. package/dist/lib/supply-path/evaluate.d.mts +17 -0
  32. package/dist/lib/supply-path/evaluate.d.ts +17 -0
  33. package/dist/lib/supply-path/evaluate.js +436 -0
  34. package/dist/lib/supply-path/evaluate.mjs +407 -0
  35. package/dist/lib/supply-path/fetch-evidence.d.mts +36 -0
  36. package/dist/lib/supply-path/fetch-evidence.d.ts +36 -0
  37. package/dist/lib/supply-path/fetch-evidence.js +293 -0
  38. package/dist/lib/supply-path/fetch-evidence.mjs +268 -0
  39. package/dist/lib/supply-path/index.d.mts +6 -0
  40. package/dist/lib/supply-path/index.d.ts +6 -0
  41. package/dist/lib/supply-path/index.js +49 -0
  42. package/dist/lib/supply-path/index.mjs +23 -0
  43. package/dist/lib/supply-path/products.d.mts +41 -0
  44. package/dist/lib/supply-path/products.d.ts +41 -0
  45. package/dist/lib/supply-path/products.js +228 -0
  46. package/dist/lib/supply-path/products.mjs +204 -0
  47. package/dist/lib/supply-path/revocations.d.mts +55 -0
  48. package/dist/lib/supply-path/revocations.d.ts +55 -0
  49. package/dist/lib/supply-path/revocations.js +127 -0
  50. package/dist/lib/supply-path/revocations.mjs +99 -0
  51. package/dist/lib/supply-path/types.d.mts +168 -0
  52. package/dist/lib/supply-path/types.d.ts +168 -0
  53. package/dist/lib/supply-path/types.js +16 -0
  54. package/dist/lib/supply-path/types.mjs +0 -0
  55. package/dist/lib/supply-path/validation.d.mts +10 -0
  56. package/dist/lib/supply-path/validation.d.ts +10 -0
  57. package/dist/lib/supply-path/validation.js +152 -0
  58. package/dist/lib/supply-path/validation.mjs +122 -0
  59. package/dist/lib/supply-path/verify.d.mts +25 -0
  60. package/dist/lib/supply-path/verify.d.ts +25 -0
  61. package/dist/lib/supply-path/verify.js +218 -0
  62. package/dist/lib/supply-path/verify.mjs +203 -0
  63. package/dist/lib/testing/storyboard/request-signing/grader.js +19 -9
  64. package/dist/lib/testing/storyboard/request-signing/grader.mjs +19 -9
  65. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  66. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  67. package/dist/lib/v2/projection/creative-delivery.d.mts +1 -1
  68. package/dist/lib/v2/projection/creative-delivery.d.ts +1 -1
  69. package/dist/lib/validation/schema-loader.js +7 -5
  70. package/dist/lib/validation/schema-loader.mjs +7 -5
  71. package/dist/lib/version.d.mts +3 -3
  72. package/dist/lib/version.d.ts +3 -3
  73. package/dist/lib/version.js +3 -3
  74. package/dist/lib/version.mjs +3 -3
  75. package/docs/TYPE-SUMMARY.md +2 -2
  76. package/docs/guides/SUPPLY-PATH-VERIFICATION.md +101 -0
  77. package/docs/llms.txt +2 -2
  78. package/docs/migration-14.x-rc-worksheet.md +4 -4
  79. package/examples/README.md +2 -0
  80. package/examples/supply-path-verification.ts +29 -0
  81. package/package.json +2 -1
@@ -15,13 +15,14 @@ class AdAgentsRedirectRefusedError extends Error {
15
15
  this.location = meta.location;
16
16
  }
17
17
  }
18
- async function ssrfSafeFetchAdAgents(url, options, policy) {
18
+ async function ssrfSafeFetchAdAgents(url, options, policy, onResponse) {
19
19
  let currentUrl = url;
20
20
  let redirects = 0;
21
- const originUrl = policy.mode === "same-registrable-domain" ? policy.originUrl : url;
22
- const maxRedirects = policy.mode === "same-registrable-domain" ? policy.maxRedirects ?? DEFAULT_WELL_KNOWN_REDIRECT_HOPS : 0;
21
+ const originUrl = policy.mode !== "none" ? policy.originUrl : url;
22
+ const maxRedirects = policy.mode !== "none" ? policy.maxRedirects ?? DEFAULT_WELL_KNOWN_REDIRECT_HOPS : 0;
23
23
  while (true) {
24
24
  const result = await ssrfSafeFetch(currentUrl, options);
25
+ onResponse?.(result);
25
26
  if (!REDIRECT_STATUSES.has(result.status)) return result;
26
27
  const location = result.headers["location"];
27
28
  if (!location) {
@@ -61,6 +62,12 @@ async function ssrfSafeFetchAdAgents(url, options, policy) {
61
62
  { url: currentUrl, location: scrubUrl(next) }
62
63
  );
63
64
  }
65
+ if (policy.mode === "same-origin" && new URL(originUrl).origin !== next.origin) {
66
+ throw new AdAgentsRedirectRefusedError("redirect_refused", "Authoritative evidence redirect changed origin", {
67
+ url: currentUrl,
68
+ location: scrubUrl(next)
69
+ });
70
+ }
64
71
  validateSameRegistrableDomainRedirect(originUrl, currentUrl, nextUrl);
65
72
  redirects++;
66
73
  currentUrl = nextUrl;
@@ -81,6 +81,45 @@ export type CompactPublisherPropertySelector = {
81
81
  publisher_domains: string[];
82
82
  property_tags: string[];
83
83
  };
84
+ /** Authorization-scoped omission grants all collections in this publisher namespace. */
85
+ export interface AuthorizationCollectionSelector {
86
+ publisher_domain: string;
87
+ collection_ids?: string[];
88
+ }
89
+ /** Products always select concrete collection IDs; omission is not a product wildcard. */
90
+ export interface ProductCollectionSelector extends AuthorizationCollectionSelector {
91
+ collection_ids: [string, ...string[]];
92
+ }
93
+ /** Carriage entries can carry host property IDs, catalog identifiers, or both. */
94
+ export type CollectionDistribution = {
95
+ publisher_domain: string;
96
+ } & ({
97
+ property_ids: [string, ...string[]];
98
+ identifiers?: [{
99
+ type: string;
100
+ value: string;
101
+ }, ...Array<{
102
+ type: string;
103
+ value: string;
104
+ }>];
105
+ } | {
106
+ property_ids?: [string, ...string[]];
107
+ identifiers: [{
108
+ type: string;
109
+ value: string;
110
+ }, ...Array<{
111
+ type: string;
112
+ value: string;
113
+ }>];
114
+ });
115
+ export interface DiscoveryCollection {
116
+ /** Required when a shared cross-origin document declares this publisher-scoped collection. */
117
+ publisher_domain?: string;
118
+ collection_id: string;
119
+ name: string;
120
+ kind?: string;
121
+ distribution?: CollectionDistribution[];
122
+ }
84
123
  /**
85
124
  * Entry in `adagents.json` `authorized_agents[]`. The schema requires
86
125
  * every entry to carry `authorization_type` plus the matching selector
@@ -94,6 +133,8 @@ export type CompactPublisherPropertySelector = {
94
133
  export interface AuthorizedAgent {
95
134
  url: string;
96
135
  authorized_for: string;
136
+ collections?: AuthorizationCollectionSelector[];
137
+ delegation_type?: string;
97
138
  /** Discriminator. Required by the schema; absent in pre-schema-3 files. */
98
139
  authorization_type?: AuthorizationType;
99
140
  /** Selector for `authorization_type: 'property_ids'`. */
@@ -169,6 +210,7 @@ export interface AdAgentsJson {
169
210
  authoritative_location?: string;
170
211
  authorized_agents?: AuthorizedAgent[];
171
212
  properties?: Property[];
213
+ collections?: DiscoveryCollection[];
172
214
  /**
173
215
  * Publisher-published format catalog (AdCP 3.1). Each entry declares
174
216
  * a v2 `ProductFormatDeclaration` (or v1 named-format ref) the
@@ -81,6 +81,45 @@ export type CompactPublisherPropertySelector = {
81
81
  publisher_domains: string[];
82
82
  property_tags: string[];
83
83
  };
84
+ /** Authorization-scoped omission grants all collections in this publisher namespace. */
85
+ export interface AuthorizationCollectionSelector {
86
+ publisher_domain: string;
87
+ collection_ids?: string[];
88
+ }
89
+ /** Products always select concrete collection IDs; omission is not a product wildcard. */
90
+ export interface ProductCollectionSelector extends AuthorizationCollectionSelector {
91
+ collection_ids: [string, ...string[]];
92
+ }
93
+ /** Carriage entries can carry host property IDs, catalog identifiers, or both. */
94
+ export type CollectionDistribution = {
95
+ publisher_domain: string;
96
+ } & ({
97
+ property_ids: [string, ...string[]];
98
+ identifiers?: [{
99
+ type: string;
100
+ value: string;
101
+ }, ...Array<{
102
+ type: string;
103
+ value: string;
104
+ }>];
105
+ } | {
106
+ property_ids?: [string, ...string[]];
107
+ identifiers: [{
108
+ type: string;
109
+ value: string;
110
+ }, ...Array<{
111
+ type: string;
112
+ value: string;
113
+ }>];
114
+ });
115
+ export interface DiscoveryCollection {
116
+ /** Required when a shared cross-origin document declares this publisher-scoped collection. */
117
+ publisher_domain?: string;
118
+ collection_id: string;
119
+ name: string;
120
+ kind?: string;
121
+ distribution?: CollectionDistribution[];
122
+ }
84
123
  /**
85
124
  * Entry in `adagents.json` `authorized_agents[]`. The schema requires
86
125
  * every entry to carry `authorization_type` plus the matching selector
@@ -94,6 +133,8 @@ export type CompactPublisherPropertySelector = {
94
133
  export interface AuthorizedAgent {
95
134
  url: string;
96
135
  authorized_for: string;
136
+ collections?: AuthorizationCollectionSelector[];
137
+ delegation_type?: string;
97
138
  /** Discriminator. Required by the schema; absent in pre-schema-3 files. */
98
139
  authorization_type?: AuthorizationType;
99
140
  /** Selector for `authorization_type: 'property_ids'`. */
@@ -169,6 +210,7 @@ export interface AdAgentsJson {
169
210
  authoritative_location?: string;
170
211
  authorized_agents?: AuthorizedAgent[];
171
212
  properties?: Property[];
213
+ collections?: DiscoveryCollection[];
172
214
  /**
173
215
  * Publisher-published format catalog (AdCP 3.1). Each entry declares
174
216
  * a v2 `ProductFormatDeclaration` (or v1 named-format ref) the
@@ -42,7 +42,7 @@ export { createCanonicalReferenceCache, createCanonicalReferenceResolver, canoni
42
42
  export type { BuildGovernanceExecutionRequestInput, BuildGovernanceIntentRequestInput, BuildHumanReviewPlanInput, BuildHumanOverrideInput, DataSubjectContestation, GovernanceAuthorizationClaims, GovernanceAuthorizationCriticalClaim, GovernanceAuthorizationErrorCode, GovernanceAuthorizationFailure, GovernanceAuthorizationResult, GovernanceAuthorizationSuccess, GovernanceCommitment, GovernanceEnforcementMiddleware, GovernanceEnforcementMiddlewareConfig, GovernanceEnforcementMiddlewareInput, GovernanceEnforcementMode, GovernanceEnforcementTask, GovernancePlan, GovernanceReplayStore, GovernanceReplayBinding, GovernanceRevocationResolver, GovernanceRevocationStatus, GovernanceValidationIssue, HumanOverride, InMemoryGovernanceReplayStoreOptions, PlanBudget, ReallocationAutonomy, VerifyGovernanceAuthorizationOptions, } from './governance/index.mjs';
43
43
  export type { BaseTaskEvent, ProtocolRequestEvent, ProtocolResponseEvent, TaskStatusEvent, ObjectEvent, TaskEvent, TaskEventCallbacks, } from './core/TaskEventTypes.mjs';
44
44
  export { createOperationId } from './core/TaskEventTypes.mjs';
45
- export type { AsyncHandlerConfig, WebhookMetadata, Activity, NotificationMetadata, MediaBuyDeliveryNotification, CreateMediaBuyStatusChangeHandler, UpdateMediaBuyStatusChangeHandler, SyncCreativesStatusChangeHandler, GetProductsStatusChangeHandler, } from './core/AsyncHandler.mjs';
45
+ export type { AsyncHandlerConfig, WebhookMetadata, Activity, NotificationMetadata, MediaBuyDeliveryNotification, CreateMediaBuyStatusChangeHandler, UpdateMediaBuyStatusChangeHandler, SyncCreativesStatusChangeHandler, GetProductsStatusChangeHandler, ListProductsStatusChangeHandler, } from './core/AsyncHandler.mjs';
46
46
  export { AsyncHandler, WebhookDedupConflictError, WebhookDedupInputError, createAsyncHandler, } from './core/AsyncHandler.mjs';
47
47
  export { normalizeWholesaleFeedWebhookNotification, parseWholesaleFeedWebhookNotification, WholesaleFeedWebhookNotificationError, } from './wholesale-feed-sync/webhook-notification.mjs';
48
48
  export type { NormalizedWholesaleFeedWebhookNotification, WholesaleFeedWebhookAffectedEntityType, WholesaleFeedWebhookCacheScope, WholesaleFeedWebhookNotificationErrorCode, WholesaleFeedWebhookNotificationErrorDetails, WholesaleFeedWebhookNotificationType, } from './wholesale-feed-sync/webhook-notification.mjs';
@@ -266,3 +266,5 @@ export type { AccountChangeFeedCapabilities } from './utils/capabilities.mjs';
266
266
  export * from './media-buy/actions.mjs';
267
267
  export { mediaBuyActionResolver } from './server/media-buy-action-resolver.mjs';
268
268
  export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './server/media-buy-action-resolver.mjs';
269
+ export * from './supply-path/index.mjs';
270
+ export type { AuthorizationCollectionSelector, ProductCollectionSelector, CollectionDistribution, DiscoveryCollection, } from './discovery/types.mjs';
@@ -42,7 +42,7 @@ export { createCanonicalReferenceCache, createCanonicalReferenceResolver, canoni
42
42
  export type { BuildGovernanceExecutionRequestInput, BuildGovernanceIntentRequestInput, BuildHumanReviewPlanInput, BuildHumanOverrideInput, DataSubjectContestation, GovernanceAuthorizationClaims, GovernanceAuthorizationCriticalClaim, GovernanceAuthorizationErrorCode, GovernanceAuthorizationFailure, GovernanceAuthorizationResult, GovernanceAuthorizationSuccess, GovernanceCommitment, GovernanceEnforcementMiddleware, GovernanceEnforcementMiddlewareConfig, GovernanceEnforcementMiddlewareInput, GovernanceEnforcementMode, GovernanceEnforcementTask, GovernancePlan, GovernanceReplayStore, GovernanceReplayBinding, GovernanceRevocationResolver, GovernanceRevocationStatus, GovernanceValidationIssue, HumanOverride, InMemoryGovernanceReplayStoreOptions, PlanBudget, ReallocationAutonomy, VerifyGovernanceAuthorizationOptions, } from './governance';
43
43
  export type { BaseTaskEvent, ProtocolRequestEvent, ProtocolResponseEvent, TaskStatusEvent, ObjectEvent, TaskEvent, TaskEventCallbacks, } from './core/TaskEventTypes';
44
44
  export { createOperationId } from './core/TaskEventTypes';
45
- export type { AsyncHandlerConfig, WebhookMetadata, Activity, NotificationMetadata, MediaBuyDeliveryNotification, CreateMediaBuyStatusChangeHandler, UpdateMediaBuyStatusChangeHandler, SyncCreativesStatusChangeHandler, GetProductsStatusChangeHandler, } from './core/AsyncHandler';
45
+ export type { AsyncHandlerConfig, WebhookMetadata, Activity, NotificationMetadata, MediaBuyDeliveryNotification, CreateMediaBuyStatusChangeHandler, UpdateMediaBuyStatusChangeHandler, SyncCreativesStatusChangeHandler, GetProductsStatusChangeHandler, ListProductsStatusChangeHandler, } from './core/AsyncHandler';
46
46
  export { AsyncHandler, WebhookDedupConflictError, WebhookDedupInputError, createAsyncHandler, } from './core/AsyncHandler';
47
47
  export { normalizeWholesaleFeedWebhookNotification, parseWholesaleFeedWebhookNotification, WholesaleFeedWebhookNotificationError, } from './wholesale-feed-sync/webhook-notification';
48
48
  export type { NormalizedWholesaleFeedWebhookNotification, WholesaleFeedWebhookAffectedEntityType, WholesaleFeedWebhookCacheScope, WholesaleFeedWebhookNotificationErrorCode, WholesaleFeedWebhookNotificationErrorDetails, WholesaleFeedWebhookNotificationType, } from './wholesale-feed-sync/webhook-notification';
@@ -266,3 +266,5 @@ export type { AccountChangeFeedCapabilities } from './utils/capabilities';
266
266
  export * from './media-buy/actions';
267
267
  export { mediaBuyActionResolver } from './server/media-buy-action-resolver';
268
268
  export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './server/media-buy-action-resolver';
269
+ export * from './supply-path';
270
+ export type { AuthorizationCollectionSelector, ProductCollectionSelector, CollectionDistribution, DiscoveryCollection, } from './discovery/types';
package/dist/lib/index.js CHANGED
@@ -815,6 +815,7 @@ __reExport(index_exports, require('./client/account-change-subscription.js'), mo
815
815
  __reExport(index_exports, require('./notifications/account-change-recorded.js'), module.exports);
816
816
  __reExport(index_exports, require('./media-buy/actions.js'), module.exports);
817
817
  var import_media_buy_action_resolver = require('./server/media-buy-action-resolver.js');
818
+ __reExport(index_exports, require('./supply-path/index.js'), module.exports);
818
819
  const wireVersion = {
819
820
  isSupported: import_protocols2.bundleSupportsAdcpVersionField,
820
821
  normalize: import_schema_loader2.toReleasePrecisionWire,
@@ -1521,5 +1522,6 @@ function createAdCPClientFromEnv() {
1521
1522
  ...require('./client/account-changes.js'),
1522
1523
  ...require('./client/account-change-subscription.js'),
1523
1524
  ...require('./notifications/account-change-recorded.js'),
1524
- ...require('./media-buy/actions.js')
1525
+ ...require('./media-buy/actions.js'),
1526
+ ...require('./supply-path/index.js')
1525
1527
  });
@@ -785,6 +785,7 @@ export * from "./client/account-change-subscription.mjs";
785
785
  export * from "./notifications/account-change-recorded.mjs";
786
786
  export * from "./media-buy/actions.mjs";
787
787
  import { mediaBuyActionResolver } from "./server/media-buy-action-resolver.mjs";
788
+ export * from "./supply-path/index.mjs";
788
789
  export {
789
790
  A2AInvocationError,
790
791
  A2A_CARD_PATHS,
@@ -102,6 +102,7 @@ async function ssrfSafeFetch(url, options = {}) {
102
102
  if (options.signal?.aborted) onExternalAbort();
103
103
  const timer = setTimeout(() => ac.abort(new Error("ssrf-fetch: timeout")), timeoutMs);
104
104
  let dispatcher;
105
+ let cancelBody;
105
106
  let pinned;
106
107
  let pinnedFamily;
107
108
  try {
@@ -167,20 +168,23 @@ async function ssrfSafeFetch(url, options = {}) {
167
168
  }
168
169
  });
169
170
  }
170
- const res = options.trustedFetchFn ? await options.trustedFetchFn(checkedUrl, {
171
- method: options.method ?? "GET",
172
- redirect: "manual",
173
- signal: ac.signal,
174
- headers: options.headers,
175
- ...options.body !== void 0 && { body: options.body }
176
- }) : await (0, import_undici.fetch)(checkedUrl, {
177
- method: options.method ?? "GET",
178
- redirect: "manual",
179
- signal: ac.signal,
180
- headers: options.headers,
181
- dispatcher,
182
- ...options.body !== void 0 && { body: options.body }
183
- });
171
+ const res = await raceWithAbort(
172
+ options.trustedFetchFn ? options.trustedFetchFn(checkedUrl, {
173
+ method: options.method ?? "GET",
174
+ redirect: "manual",
175
+ signal: ac.signal,
176
+ headers: options.headers,
177
+ ...options.body !== void 0 && { body: options.body }
178
+ }) : (0, import_undici.fetch)(checkedUrl, {
179
+ method: options.method ?? "GET",
180
+ redirect: "manual",
181
+ signal: ac.signal,
182
+ headers: options.headers,
183
+ dispatcher,
184
+ ...options.body !== void 0 && { body: options.body }
185
+ }),
186
+ ac.signal
187
+ );
184
188
  const headers = {};
185
189
  res.headers.forEach((v, k) => {
186
190
  headers[k.toLowerCase()] = v;
@@ -196,14 +200,19 @@ async function ssrfSafeFetch(url, options = {}) {
196
200
  connectionPinned: pinned !== void 0
197
201
  };
198
202
  }
203
+ cancelBody = () => {
204
+ void reader.cancel().catch(() => {
205
+ });
206
+ };
199
207
  const chunks = [];
200
208
  let bytes = 0;
201
209
  while (true) {
202
- const { done, value } = await reader.read();
210
+ const { done, value } = await raceWithAbort(reader.read(), ac.signal);
203
211
  if (done) break;
204
212
  bytes += value.byteLength;
205
213
  if (bytes > maxBodyBytes) {
206
- await reader.cancel();
214
+ void reader.cancel().catch(() => {
215
+ });
207
216
  throw new SsrfRefusedError("body_exceeds_limit", `Response body exceeded ${maxBodyBytes} bytes`, {
208
217
  url,
209
218
  hostname: parsed.hostname,
@@ -229,16 +238,33 @@ async function ssrfSafeFetch(url, options = {}) {
229
238
  } finally {
230
239
  clearTimeout(timer);
231
240
  options.signal?.removeEventListener("abort", onExternalAbort);
232
- await dispatcher?.close().catch(() => {
241
+ if (ac.signal.aborted) {
242
+ cancelBody?.();
243
+ await dispatcher?.destroy().catch(() => {
244
+ });
245
+ } else await dispatcher?.close().catch(() => {
233
246
  });
234
247
  }
235
248
  }
236
249
  function raceWithAbort(operation, signal) {
237
- throwIfSignalAborted(signal);
238
250
  return new Promise((resolve, reject) => {
239
- const onAbort = () => reject(signalAbortError(signal));
240
- signal.addEventListener("abort", onAbort, { once: true });
241
- operation.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
251
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
252
+ const onAbort = () => {
253
+ cleanup();
254
+ reject(signalAbortError(signal));
255
+ };
256
+ operation.then(
257
+ (value) => {
258
+ cleanup();
259
+ resolve(value);
260
+ },
261
+ (error) => {
262
+ cleanup();
263
+ reject(error);
264
+ }
265
+ );
266
+ if (signal.aborted) onAbort();
267
+ else signal.addEventListener("abort", onAbort, { once: true });
242
268
  });
243
269
  }
244
270
  function signalAbortError(signal) {
@@ -76,6 +76,7 @@ async function ssrfSafeFetch(url, options = {}) {
76
76
  if (options.signal?.aborted) onExternalAbort();
77
77
  const timer = setTimeout(() => ac.abort(new Error("ssrf-fetch: timeout")), timeoutMs);
78
78
  let dispatcher;
79
+ let cancelBody;
79
80
  let pinned;
80
81
  let pinnedFamily;
81
82
  try {
@@ -141,20 +142,23 @@ async function ssrfSafeFetch(url, options = {}) {
141
142
  }
142
143
  });
143
144
  }
144
- const res = options.trustedFetchFn ? await options.trustedFetchFn(checkedUrl, {
145
- method: options.method ?? "GET",
146
- redirect: "manual",
147
- signal: ac.signal,
148
- headers: options.headers,
149
- ...options.body !== void 0 && { body: options.body }
150
- }) : await undiciFetch(checkedUrl, {
151
- method: options.method ?? "GET",
152
- redirect: "manual",
153
- signal: ac.signal,
154
- headers: options.headers,
155
- dispatcher,
156
- ...options.body !== void 0 && { body: options.body }
157
- });
145
+ const res = await raceWithAbort(
146
+ options.trustedFetchFn ? options.trustedFetchFn(checkedUrl, {
147
+ method: options.method ?? "GET",
148
+ redirect: "manual",
149
+ signal: ac.signal,
150
+ headers: options.headers,
151
+ ...options.body !== void 0 && { body: options.body }
152
+ }) : undiciFetch(checkedUrl, {
153
+ method: options.method ?? "GET",
154
+ redirect: "manual",
155
+ signal: ac.signal,
156
+ headers: options.headers,
157
+ dispatcher,
158
+ ...options.body !== void 0 && { body: options.body }
159
+ }),
160
+ ac.signal
161
+ );
158
162
  const headers = {};
159
163
  res.headers.forEach((v, k) => {
160
164
  headers[k.toLowerCase()] = v;
@@ -170,14 +174,19 @@ async function ssrfSafeFetch(url, options = {}) {
170
174
  connectionPinned: pinned !== void 0
171
175
  };
172
176
  }
177
+ cancelBody = () => {
178
+ void reader.cancel().catch(() => {
179
+ });
180
+ };
173
181
  const chunks = [];
174
182
  let bytes = 0;
175
183
  while (true) {
176
- const { done, value } = await reader.read();
184
+ const { done, value } = await raceWithAbort(reader.read(), ac.signal);
177
185
  if (done) break;
178
186
  bytes += value.byteLength;
179
187
  if (bytes > maxBodyBytes) {
180
- await reader.cancel();
188
+ void reader.cancel().catch(() => {
189
+ });
181
190
  throw new SsrfRefusedError("body_exceeds_limit", `Response body exceeded ${maxBodyBytes} bytes`, {
182
191
  url,
183
192
  hostname: parsed.hostname,
@@ -203,16 +212,33 @@ async function ssrfSafeFetch(url, options = {}) {
203
212
  } finally {
204
213
  clearTimeout(timer);
205
214
  options.signal?.removeEventListener("abort", onExternalAbort);
206
- await dispatcher?.close().catch(() => {
215
+ if (ac.signal.aborted) {
216
+ cancelBody?.();
217
+ await dispatcher?.destroy().catch(() => {
218
+ });
219
+ } else await dispatcher?.close().catch(() => {
207
220
  });
208
221
  }
209
222
  }
210
223
  function raceWithAbort(operation, signal) {
211
- throwIfSignalAborted(signal);
212
224
  return new Promise((resolve, reject) => {
213
- const onAbort = () => reject(signalAbortError(signal));
214
- signal.addEventListener("abort", onAbort, { once: true });
215
- operation.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
225
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
226
+ const onAbort = () => {
227
+ cleanup();
228
+ reject(signalAbortError(signal));
229
+ };
230
+ operation.then(
231
+ (value) => {
232
+ cleanup();
233
+ resolve(value);
234
+ },
235
+ (error) => {
236
+ cleanup();
237
+ reject(error);
238
+ }
239
+ );
240
+ if (signal.aborted) onAbort();
241
+ else signal.addEventListener("abort", onAbort, { once: true });
216
242
  });
217
243
  }
218
244
  function signalAbortError(signal) {
@@ -1,3 +1,4 @@
1
+ import type { SupplyPathRequest, RegistrySupplyPathResult } from '../supply-path/types.mjs';
1
2
  import type { ResolvedBrand, LookupBrandOptions, ResolvedProperty, RegistryClientConfig, SaveBrandRequest, SaveBrandResponse, ListBrandLogosOptions, ListBrandLogosResponse, SaveBrandLogoInput, SaveBrandLogoResponse, UploadBrandLogoInput, UploadBrandLogoResponse, SavePropertyRequest, SavePropertyResponse, ResolveIdentifiersRequest, ResolveIdentifiersResponse, FileCatalogDisputeRequest, FileCatalogDisputeResponse, GetCatalogDisputeResponse, ClaimHostedPropertyDomainResponse, VerifyHostedPropertyOriginResponse, PropertyRegistryItem, ValidationResult, DomainLookupResult, ListBrandsOptions, ListBrandsResponse, GetBrandJsonResponse, ListOptions, ListAgentsOptions, ListAgentsResponse, ListPublishersResponse, ValidateAdagentsResponse, CreateAdagentsRequest, CreateAdagentsResponse, CommunityMirrorAdagentsConfig, CreateCommunityMirrorAdagentsConfig, CommunityMirrorAdagentsCatalog, PublishCommunityMirrorAdagentsResponse, ListCommunityMirrorAdagentsResponse, DeleteCommunityMirrorAdagentsResponse, PublisherPropertySelector, FindCompanyResult, FeedQuery, FeedResponse, AgentSearchQuery, AgentSearchResponse, CrawlRequestResponse, ManagerRevalidationResponse, ListPoliciesQuery, ListPoliciesResponse, ResolvePolicyQuery, ResolvePolicyResponse, ResolvePoliciesBulkRequest, ResolvePoliciesBulkResponse, GetPolicyHistoryQuery, GetPolicyHistoryResponse, SavePolicyRequest, SavePolicyResponse, GetBrandHistoryQuery, GetBrandHistoryResponse, GetPropertyHistoryQuery, GetPropertyHistoryResponse, AgentComplianceDetail, OperatorLookupResult, PublisherLookupResult, GetAgentStoryboardStatusResponse, GetAgentStoryboardStatusBulkResponse } from './types.mjs';
2
3
  import type { FeedStreamQuery, FeedStreamMessage } from './feed-stream.mjs';
3
4
  export type { ResolvedBrand, LookupBrandOptions, ResolvedProperty, PropertyInfo, RegistryClientConfig, SaveBrandRequest, SaveBrandResponse, BrandLogoReviewStatus, ApprovedBrandLogoAsset, PendingBrandLogoAsset, ReviewedBrandLogoAsset, BrandLogoAsset, ListBrandLogosOptions, ListBrandLogosResponse, SaveBrandLogoInput, SaveBrandLogoResponse, UploadBrandLogoInput, UploadBrandLogoResponse, SavePropertyIdentity, RegistryPropertyIdentity, SavePropertyRequest, SavePropertyResponse, ResolveIdentifiersRequest, ResolveIdentifiersResponse, FileCatalogDisputeRequest, FileCatalogDisputeResponse, GetCatalogDisputeResponse, ClaimHostedPropertyDomainResponse, VerifyHostedPropertyOriginResponse, BrandRegistryItem, PropertyRegistryItem, ValidationResult, FederatedAgentWithDetails, FederatedPublisher, DomainLookupResult, ListBrandsOptions, ListBrandsResponse, GetBrandJsonResponse, ListOptions, ListAgentsOptions, ListAgentsResponse, ListPublishersResponse, ValidateAdagentsRequest, ValidateAdagentsResponse, CreateAdagentsRequest, CreateAdagentsResponse, AdagentsAuthorizedAgent, AdagentsCatalogFormat, AdagentsPlacementDefinition, AdagentsPlacementFormatReference, AdagentsPlacementFormatOption, AdagentsPlacementTag, CreatedAdagentsJson, CommunityMirrorAdagentsConfig, CreateCommunityMirrorAdagentsConfig, CommunityMirrorAdagentsCatalog, PublishCommunityMirrorAdagentsResponse, CommunityMirrorAdagentsSummary, ListCommunityMirrorAdagentsResponse, GetCommunityMirrorAdagentsResponse, PublishCommunityMirrorAdagentsRequest, PublishCommunityMirrorAdagentsError, DeleteCommunityMirrorAdagentsResponse, ValidateProductAuthorizationRequest, ExpandProductIdentifiersRequest, PublisherPropertySelector, CompanySearchResult, FindCompanyResult, FeedQuery, AgentSearchQuery, CrawlRequest, ManagerRevalidationRequest, ManagerRevalidationResponse, ListPoliciesQuery, ListPoliciesResponse, ResolvePolicyQuery, ResolvePolicyResponse, ResolvePoliciesBulkRequest, ResolvePoliciesBulkResponse, GetPolicyHistoryQuery, GetPolicyHistoryResponse, SavePolicyRequest, SavePolicyResponse, GetBrandHistoryQuery, GetBrandHistoryResponse, GetPropertyHistoryQuery, GetPropertyHistoryResponse, AgentComplianceDetail, StoryboardStatus, OperatorLookupResult, PublisherLookupResult, ComplianceChangedPayload, GetAgentStoryboardStatusResponse, GetAgentStoryboardStatusBulkResponse, } from './types.mjs';
@@ -251,6 +252,8 @@ export declare class RegistryClient {
251
252
  authorized: boolean;
252
253
  checked_at: string;
253
254
  }>;
255
+ /** Cached registry verdict. Fetch authoritative evidence for enforcement. */
256
+ verifySupplyPath(request: SupplyPathRequest): Promise<RegistrySupplyPathResult>;
254
257
  /** Validate product authorization for an agent across publisher properties. */
255
258
  validateProductAuthorization(agentUrl: string, publisherProperties: PublisherPropertySelector[]): Promise<Record<string, unknown>>;
256
259
  /** Expand product identifiers for an agent across publisher properties. */
@@ -1,3 +1,4 @@
1
+ import type { SupplyPathRequest, RegistrySupplyPathResult } from '../supply-path/types';
1
2
  import type { ResolvedBrand, LookupBrandOptions, ResolvedProperty, RegistryClientConfig, SaveBrandRequest, SaveBrandResponse, ListBrandLogosOptions, ListBrandLogosResponse, SaveBrandLogoInput, SaveBrandLogoResponse, UploadBrandLogoInput, UploadBrandLogoResponse, SavePropertyRequest, SavePropertyResponse, ResolveIdentifiersRequest, ResolveIdentifiersResponse, FileCatalogDisputeRequest, FileCatalogDisputeResponse, GetCatalogDisputeResponse, ClaimHostedPropertyDomainResponse, VerifyHostedPropertyOriginResponse, PropertyRegistryItem, ValidationResult, DomainLookupResult, ListBrandsOptions, ListBrandsResponse, GetBrandJsonResponse, ListOptions, ListAgentsOptions, ListAgentsResponse, ListPublishersResponse, ValidateAdagentsResponse, CreateAdagentsRequest, CreateAdagentsResponse, CommunityMirrorAdagentsConfig, CreateCommunityMirrorAdagentsConfig, CommunityMirrorAdagentsCatalog, PublishCommunityMirrorAdagentsResponse, ListCommunityMirrorAdagentsResponse, DeleteCommunityMirrorAdagentsResponse, PublisherPropertySelector, FindCompanyResult, FeedQuery, FeedResponse, AgentSearchQuery, AgentSearchResponse, CrawlRequestResponse, ManagerRevalidationResponse, ListPoliciesQuery, ListPoliciesResponse, ResolvePolicyQuery, ResolvePolicyResponse, ResolvePoliciesBulkRequest, ResolvePoliciesBulkResponse, GetPolicyHistoryQuery, GetPolicyHistoryResponse, SavePolicyRequest, SavePolicyResponse, GetBrandHistoryQuery, GetBrandHistoryResponse, GetPropertyHistoryQuery, GetPropertyHistoryResponse, AgentComplianceDetail, OperatorLookupResult, PublisherLookupResult, GetAgentStoryboardStatusResponse, GetAgentStoryboardStatusBulkResponse } from './types';
2
3
  import type { FeedStreamQuery, FeedStreamMessage } from './feed-stream';
3
4
  export type { ResolvedBrand, LookupBrandOptions, ResolvedProperty, PropertyInfo, RegistryClientConfig, SaveBrandRequest, SaveBrandResponse, BrandLogoReviewStatus, ApprovedBrandLogoAsset, PendingBrandLogoAsset, ReviewedBrandLogoAsset, BrandLogoAsset, ListBrandLogosOptions, ListBrandLogosResponse, SaveBrandLogoInput, SaveBrandLogoResponse, UploadBrandLogoInput, UploadBrandLogoResponse, SavePropertyIdentity, RegistryPropertyIdentity, SavePropertyRequest, SavePropertyResponse, ResolveIdentifiersRequest, ResolveIdentifiersResponse, FileCatalogDisputeRequest, FileCatalogDisputeResponse, GetCatalogDisputeResponse, ClaimHostedPropertyDomainResponse, VerifyHostedPropertyOriginResponse, BrandRegistryItem, PropertyRegistryItem, ValidationResult, FederatedAgentWithDetails, FederatedPublisher, DomainLookupResult, ListBrandsOptions, ListBrandsResponse, GetBrandJsonResponse, ListOptions, ListAgentsOptions, ListAgentsResponse, ListPublishersResponse, ValidateAdagentsRequest, ValidateAdagentsResponse, CreateAdagentsRequest, CreateAdagentsResponse, AdagentsAuthorizedAgent, AdagentsCatalogFormat, AdagentsPlacementDefinition, AdagentsPlacementFormatReference, AdagentsPlacementFormatOption, AdagentsPlacementTag, CreatedAdagentsJson, CommunityMirrorAdagentsConfig, CreateCommunityMirrorAdagentsConfig, CommunityMirrorAdagentsCatalog, PublishCommunityMirrorAdagentsResponse, CommunityMirrorAdagentsSummary, ListCommunityMirrorAdagentsResponse, GetCommunityMirrorAdagentsResponse, PublishCommunityMirrorAdagentsRequest, PublishCommunityMirrorAdagentsError, DeleteCommunityMirrorAdagentsResponse, ValidateProductAuthorizationRequest, ExpandProductIdentifiersRequest, PublisherPropertySelector, CompanySearchResult, FindCompanyResult, FeedQuery, AgentSearchQuery, CrawlRequest, ManagerRevalidationRequest, ManagerRevalidationResponse, ListPoliciesQuery, ListPoliciesResponse, ResolvePolicyQuery, ResolvePolicyResponse, ResolvePoliciesBulkRequest, ResolvePoliciesBulkResponse, GetPolicyHistoryQuery, GetPolicyHistoryResponse, SavePolicyRequest, SavePolicyResponse, GetBrandHistoryQuery, GetBrandHistoryResponse, GetPropertyHistoryQuery, GetPropertyHistoryResponse, AgentComplianceDetail, StoryboardStatus, OperatorLookupResult, PublisherLookupResult, ComplianceChangedPayload, GetAgentStoryboardStatusResponse, GetAgentStoryboardStatusBulkResponse, } from './types';
@@ -251,6 +252,8 @@ export declare class RegistryClient {
251
252
  authorized: boolean;
252
253
  checked_at: string;
253
254
  }>;
255
+ /** Cached registry verdict. Fetch authoritative evidence for enforcement. */
256
+ verifySupplyPath(request: SupplyPathRequest): Promise<RegistrySupplyPathResult>;
254
257
  /** Validate product authorization for an agent across publisher properties. */
255
258
  validateProductAuthorization(agentUrl: string, publisherProperties: PublisherPropertySelector[]): Promise<Record<string, unknown>>;
256
259
  /** Expand product identifiers for an agent across publisher properties. */
@@ -37,6 +37,7 @@ __export(registry_exports, {
37
37
  sanitizeStreamText: () => import_feed_stream2.sanitizeStreamText
38
38
  });
39
39
  module.exports = __toCommonJS(registry_exports);
40
+ var import_validation = require('../supply-path/validation.js');
40
41
  var import_feed_stream = require('./feed-stream.js');
41
42
  var import_sync = require('./sync.js');
42
43
  var import_feed_stream2 = require('./feed-stream.js');
@@ -548,6 +549,13 @@ class RegistryClient {
548
549
  });
549
550
  return this.get(`${this.baseUrl}/api/registry/validate/property-authorization?${params}`);
550
551
  }
552
+ /** Cached registry verdict. Fetch authoritative evidence for enforcement. */
553
+ async verifySupplyPath(request) {
554
+ const normalized = (0, import_validation.validateSupplyPathRequest)(request);
555
+ const response = await this.post(`${this.baseUrl}/api/registry/verify/supply-path`, normalized);
556
+ (0, import_validation.assertRegistrySupplyPathResult)(response, normalized);
557
+ return response;
558
+ }
551
559
  /** Validate product authorization for an agent across publisher properties. */
552
560
  async validateProductAuthorization(agentUrl, publisherProperties) {
553
561
  return this.post(`${this.baseUrl}/api/registry/validate/product-authorization`, {
@@ -1,3 +1,4 @@
1
+ import { validateSupplyPathRequest, assertRegistrySupplyPathResult } from "../supply-path/validation.mjs";
1
2
  import { openFeedStream } from "./feed-stream.mjs";
2
3
  import { RegistrySync } from "./sync.mjs";
3
4
  import {
@@ -519,6 +520,13 @@ class RegistryClient {
519
520
  });
520
521
  return this.get(`${this.baseUrl}/api/registry/validate/property-authorization?${params}`);
521
522
  }
523
+ /** Cached registry verdict. Fetch authoritative evidence for enforcement. */
524
+ async verifySupplyPath(request) {
525
+ const normalized = validateSupplyPathRequest(request);
526
+ const response = await this.post(`${this.baseUrl}/api/registry/verify/supply-path`, normalized);
527
+ assertRegistrySupplyPathResult(response, normalized);
528
+ return response;
529
+ }
522
530
  /** Validate product authorization for an agent across publisher properties. */
523
531
  async validateProductAuthorization(agentUrl, publisherProperties) {
524
532
  return this.post(`${this.baseUrl}/api/registry/validate/product-authorization`, {
@@ -169,7 +169,8 @@ type RegistryCreateAdagentsRequest = NonNullable<operations['createAdagents']['r
169
169
  /** Response from POST /api/adagents/create (200) */
170
170
  type RegistryCreateAdagentsResponse = operations['createAdagents']['responses']['200']['content']['application/json'];
171
171
  /** Agent authorization entry accepted by the registry adagents.json generator. */
172
- export type AdagentsAuthorizedAgent = RegistryCreateAdagentsRequest['authorized_agents'][number] & {
172
+ export type AdagentsAuthorizedAgent = Omit<RegistryCreateAdagentsRequest['authorized_agents'][number], 'collections'> & {
173
+ collections?: import('../discovery/types.mjs').AuthorizationCollectionSelector[];
173
174
  [key: string]: unknown;
174
175
  };
175
176
  /**
@@ -169,7 +169,8 @@ type RegistryCreateAdagentsRequest = NonNullable<operations['createAdagents']['r
169
169
  /** Response from POST /api/adagents/create (200) */
170
170
  type RegistryCreateAdagentsResponse = operations['createAdagents']['responses']['200']['content']['application/json'];
171
171
  /** Agent authorization entry accepted by the registry adagents.json generator. */
172
- export type AdagentsAuthorizedAgent = RegistryCreateAdagentsRequest['authorized_agents'][number] & {
172
+ export type AdagentsAuthorizedAgent = Omit<RegistryCreateAdagentsRequest['authorized_agents'][number], 'collections'> & {
173
+ collections?: import('../discovery/types').AuthorizationCollectionSelector[];
173
174
  [key: string]: unknown;
174
175
  };
175
176
  /**
@@ -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-09-18T20:08:01.998Z"
7
+ "synced_at": "2026-09-19T13:45:09.361Z"
8
8
  }
@@ -0,0 +1,17 @@
1
+ import type { SupplyPathInput, SupplyPathVerdict } from './types.mjs';
2
+ export declare const SUPPLY_PATH_STATES: readonly ["unverified", "owner_attested", "host_delegated", "verified_owner_sold"];
3
+ export declare function parseInventoryPartnerDomains(content: string): string[];
4
+ export declare function isUnqualifiedPropertySelector(value: unknown): boolean;
5
+ /** Reject predicates that conflict with the selector discriminator. */
6
+ export declare function hasValidPropertySelectorPredicate(value: unknown): boolean;
7
+ /** Internal fail-closed result used when preprocessing reaches the same evaluation budget. */
8
+ export declare function evaluationLimitVerdict(): SupplyPathVerdict;
9
+ export declare function evaluateSupplyPath(input: SupplyPathInput): SupplyPathVerdict;
10
+ /** Choose applicable IAB files from the carried host properties, never from catalog channel identifiers. */
11
+ export declare function supplyPathAdsTxtPolicy(input: SupplyPathInput): {
12
+ files: Array<'ads.txt' | 'app-ads.txt'>;
13
+ requireAll: boolean;
14
+ };
15
+ export declare function combineInventoryPartnerDomains(contents: Array<string | null>, requireAll: boolean): string[] | null;
16
+ /** Select parsed IAB evidence for one complete path; called after bulk inquiry expansion. */
17
+ export declare function inventoryPartnersForInput(input: SupplyPathInput): string[] | null;
@@ -0,0 +1,17 @@
1
+ import type { SupplyPathInput, SupplyPathVerdict } from './types';
2
+ export declare const SUPPLY_PATH_STATES: readonly ["unverified", "owner_attested", "host_delegated", "verified_owner_sold"];
3
+ export declare function parseInventoryPartnerDomains(content: string): string[];
4
+ export declare function isUnqualifiedPropertySelector(value: unknown): boolean;
5
+ /** Reject predicates that conflict with the selector discriminator. */
6
+ export declare function hasValidPropertySelectorPredicate(value: unknown): boolean;
7
+ /** Internal fail-closed result used when preprocessing reaches the same evaluation budget. */
8
+ export declare function evaluationLimitVerdict(): SupplyPathVerdict;
9
+ export declare function evaluateSupplyPath(input: SupplyPathInput): SupplyPathVerdict;
10
+ /** Choose applicable IAB files from the carried host properties, never from catalog channel identifiers. */
11
+ export declare function supplyPathAdsTxtPolicy(input: SupplyPathInput): {
12
+ files: Array<'ads.txt' | 'app-ads.txt'>;
13
+ requireAll: boolean;
14
+ };
15
+ export declare function combineInventoryPartnerDomains(contents: Array<string | null>, requireAll: boolean): string[] | null;
16
+ /** Select parsed IAB evidence for one complete path; called after bulk inquiry expansion. */
17
+ export declare function inventoryPartnersForInput(input: SupplyPathInput): string[] | null;