@adcp/sdk 14.0.0-rc.41 → 14.0.0-rc.43

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 (250) hide show
  1. package/CONTRIBUTING.md +7 -1
  2. package/README.md +13 -0
  3. package/bin/adcp-grade.js +4 -3
  4. package/bin/adcp-storyboard-summary.js +1 -1
  5. package/bin/adcp.js +85 -22
  6. package/dist/lib/acceptance-policy/index.d.mts +176 -0
  7. package/dist/lib/acceptance-policy/index.d.ts +176 -0
  8. package/dist/lib/acceptance-policy/index.js +1107 -0
  9. package/dist/lib/acceptance-policy/index.mjs +1080 -0
  10. package/dist/lib/canonical-references/index.d.mts +1 -1
  11. package/dist/lib/canonical-references/index.d.ts +1 -1
  12. package/dist/lib/canonical-references/index.js +60 -2
  13. package/dist/lib/canonical-references/index.mjs +60 -2
  14. package/dist/lib/client/core.d.mts +8 -0
  15. package/dist/lib/client/core.d.ts +8 -0
  16. package/dist/lib/client/core.js +57 -0
  17. package/dist/lib/client/core.mjs +38 -0
  18. package/dist/lib/conformance/index.d.mts +2 -0
  19. package/dist/lib/conformance/index.d.ts +2 -0
  20. package/dist/lib/conformance/index.js +7 -0
  21. package/dist/lib/conformance/index.mjs +8 -0
  22. package/dist/lib/conformance/targeting.d.mts +72 -0
  23. package/dist/lib/conformance/targeting.d.ts +72 -0
  24. package/dist/lib/conformance/targeting.js +163 -0
  25. package/dist/lib/conformance/targeting.mjs +137 -0
  26. package/dist/lib/core/ADCPMultiAgentClient.d.mts +5 -1
  27. package/dist/lib/core/ADCPMultiAgentClient.d.ts +5 -1
  28. package/dist/lib/core/ADCPMultiAgentClient.js +8 -0
  29. package/dist/lib/core/ADCPMultiAgentClient.mjs +8 -0
  30. package/dist/lib/core/AgentClient.d.mts +37 -3
  31. package/dist/lib/core/AgentClient.d.ts +37 -3
  32. package/dist/lib/core/AgentClient.js +69 -4
  33. package/dist/lib/core/AgentClient.mjs +56 -2
  34. package/dist/lib/core/AsyncHandler.d.mts +3 -1
  35. package/dist/lib/core/AsyncHandler.d.ts +3 -1
  36. package/dist/lib/core/AsyncHandler.js +6 -0
  37. package/dist/lib/core/AsyncHandler.mjs +6 -0
  38. package/dist/lib/core/SingleAgentClient.d.mts +5 -1
  39. package/dist/lib/core/SingleAgentClient.d.ts +5 -1
  40. package/dist/lib/core/SingleAgentClient.js +51 -10
  41. package/dist/lib/core/SingleAgentClient.mjs +56 -10
  42. package/dist/lib/errors/index.d.mts +4 -1
  43. package/dist/lib/errors/index.d.ts +4 -1
  44. package/dist/lib/errors/index.js +6 -1
  45. package/dist/lib/errors/index.mjs +6 -1
  46. package/dist/lib/index.d.mts +3 -1
  47. package/dist/lib/index.d.ts +3 -1
  48. package/dist/lib/index.js +13 -0
  49. package/dist/lib/index.mjs +14 -1
  50. package/dist/lib/media-buy/action-assessment.js +7 -0
  51. package/dist/lib/media-buy/action-assessment.mjs +7 -0
  52. package/dist/lib/media-buy/available-actions.d.mts +8 -1
  53. package/dist/lib/media-buy/available-actions.d.ts +8 -1
  54. package/dist/lib/media-buy/available-actions.js +18 -3
  55. package/dist/lib/media-buy/available-actions.mjs +15 -2
  56. package/dist/lib/media-buy/index.d.mts +1 -0
  57. package/dist/lib/media-buy/index.d.ts +1 -0
  58. package/dist/lib/media-buy/preflight.js +23 -12
  59. package/dist/lib/media-buy/preflight.mjs +25 -13
  60. package/dist/lib/net/ssrf-fetch.d.mts +1 -1
  61. package/dist/lib/net/ssrf-fetch.d.ts +1 -1
  62. package/dist/lib/net/ssrf-fetch.js +10 -1
  63. package/dist/lib/net/ssrf-fetch.mjs +10 -1
  64. package/dist/lib/principal/index.d.mts +1 -0
  65. package/dist/lib/principal/index.d.ts +1 -0
  66. package/dist/lib/principal/index.js +32 -0
  67. package/dist/lib/principal/index.mjs +10 -0
  68. package/dist/lib/principal/lifecycle.d.mts +77 -0
  69. package/dist/lib/principal/lifecycle.d.ts +77 -0
  70. package/dist/lib/principal/lifecycle.js +319 -0
  71. package/dist/lib/principal/lifecycle.mjs +293 -0
  72. package/dist/lib/protocols/transportDiagnostics.d.mts +2 -0
  73. package/dist/lib/protocols/transportDiagnostics.d.ts +2 -0
  74. package/dist/lib/protocols/transportDiagnostics.js +60 -20
  75. package/dist/lib/protocols/transportDiagnostics.mjs +61 -21
  76. package/dist/lib/registry/index.d.mts +3 -1
  77. package/dist/lib/registry/index.d.ts +3 -1
  78. package/dist/lib/registry/index.js +16 -3
  79. package/dist/lib/registry/index.mjs +16 -3
  80. package/dist/lib/registry/types.generated.d.mts +54 -20
  81. package/dist/lib/registry/types.generated.d.ts +54 -20
  82. package/dist/lib/reporting/core-reconciliation.d.mts +65 -0
  83. package/dist/lib/reporting/core-reconciliation.d.ts +65 -0
  84. package/dist/lib/reporting/core-reconciliation.js +148 -0
  85. package/dist/lib/reporting/core-reconciliation.mjs +124 -0
  86. package/dist/lib/reporting/index.d.mts +2 -0
  87. package/dist/lib/reporting/index.d.ts +2 -0
  88. package/dist/lib/reporting/index.js +5 -2
  89. package/dist/lib/reporting/index.mjs +3 -1
  90. package/dist/lib/reporting/ledger/handler.js +67 -11
  91. package/dist/lib/reporting/ledger/handler.mjs +69 -12
  92. package/dist/lib/reporting/ledger/health.d.mts +26 -2
  93. package/dist/lib/reporting/ledger/health.d.ts +26 -2
  94. package/dist/lib/reporting/ledger/health.js +3 -5
  95. package/dist/lib/reporting/ledger/health.mjs +3 -5
  96. package/dist/lib/reporting/ledger/producer.js +4 -9
  97. package/dist/lib/reporting/ledger/producer.mjs +4 -9
  98. package/dist/lib/reporting/ledger/status-ingest.js +1 -1
  99. package/dist/lib/reporting/ledger/status-ingest.mjs +1 -1
  100. package/dist/lib/reporting/reconciliation.d.mts +4 -9
  101. package/dist/lib/reporting/reconciliation.d.ts +4 -9
  102. package/dist/lib/reporting/reconciliation.js +5 -5
  103. package/dist/lib/reporting/reconciliation.mjs +5 -5
  104. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  105. package/dist/lib/server/create-adcp-server.d.mts +10 -11
  106. package/dist/lib/server/create-adcp-server.d.ts +10 -11
  107. package/dist/lib/server/create-adcp-server.js +39 -25
  108. package/dist/lib/server/create-adcp-server.mjs +44 -27
  109. package/dist/lib/server/decisioning/runtime/from-platform.js +16 -3
  110. package/dist/lib/server/decisioning/runtime/from-platform.mjs +16 -3
  111. package/dist/lib/server/index.d.mts +4 -1
  112. package/dist/lib/server/index.d.ts +4 -1
  113. package/dist/lib/server/index.js +9 -0
  114. package/dist/lib/server/index.mjs +10 -0
  115. package/dist/lib/server/mcp-app.d.mts +11 -24
  116. package/dist/lib/server/mcp-app.d.ts +11 -24
  117. package/dist/lib/server/mcp-app.js +30 -4
  118. package/dist/lib/server/mcp-app.mjs +30 -3
  119. package/dist/lib/server/mcp-modern-server.js +18 -14
  120. package/dist/lib/server/mcp-modern-server.mjs +25 -15
  121. package/dist/lib/server/media-buy-actions.js +3 -1
  122. package/dist/lib/server/media-buy-actions.mjs +3 -1
  123. package/dist/lib/server/notification-subscriptions/index.d.mts +1 -1
  124. package/dist/lib/server/notification-subscriptions/index.d.ts +1 -1
  125. package/dist/lib/server/notification-subscriptions/runtime.d.mts +3 -1
  126. package/dist/lib/server/notification-subscriptions/runtime.d.ts +3 -1
  127. package/dist/lib/server/notification-subscriptions/runtime.js +108 -64
  128. package/dist/lib/server/notification-subscriptions/runtime.mjs +107 -64
  129. package/dist/lib/server/notification-subscriptions/types.d.mts +41 -0
  130. package/dist/lib/server/notification-subscriptions/types.d.ts +41 -0
  131. package/dist/lib/server/principal/index.d.mts +5 -0
  132. package/dist/lib/server/principal/index.d.ts +5 -0
  133. package/dist/lib/server/principal/index.js +35 -0
  134. package/dist/lib/server/principal/index.mjs +12 -0
  135. package/dist/lib/server/principal/runtime.d.mts +57 -0
  136. package/dist/lib/server/principal/runtime.d.ts +57 -0
  137. package/dist/lib/server/principal/runtime.js +880 -0
  138. package/dist/lib/server/principal/runtime.mjs +861 -0
  139. package/dist/lib/server/principal/store.d.mts +16 -0
  140. package/dist/lib/server/principal/store.d.ts +16 -0
  141. package/dist/lib/server/principal/store.js +248 -0
  142. package/dist/lib/server/principal/store.mjs +223 -0
  143. package/dist/lib/server/principal/types.d.mts +142 -0
  144. package/dist/lib/server/principal/types.d.ts +142 -0
  145. package/dist/lib/server/principal/types.js +16 -0
  146. package/dist/lib/server/principal/types.mjs +0 -0
  147. package/dist/lib/signing/agent-resolver/strict-json.d.mts +11 -0
  148. package/dist/lib/signing/agent-resolver/strict-json.d.ts +11 -0
  149. package/dist/lib/signing/agent-resolver/strict-json.js +6 -4
  150. package/dist/lib/signing/agent-resolver/strict-json.mjs +4 -3
  151. package/dist/lib/testing/compliance/comply.js +44 -0
  152. package/dist/lib/testing/compliance/comply.mjs +43 -0
  153. package/dist/lib/testing/storyboard/agent-routing.d.mts +2 -0
  154. package/dist/lib/testing/storyboard/agent-routing.d.ts +2 -0
  155. package/dist/lib/testing/storyboard/agent-routing.js +31 -4
  156. package/dist/lib/testing/storyboard/agent-routing.mjs +30 -4
  157. package/dist/lib/testing/storyboard/junit.d.mts +1 -1
  158. package/dist/lib/testing/storyboard/junit.d.ts +1 -1
  159. package/dist/lib/testing/storyboard/junit.js +25 -10
  160. package/dist/lib/testing/storyboard/junit.mjs +23 -9
  161. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +118 -0
  162. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +118 -0
  163. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +180 -0
  164. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +144 -0
  165. package/dist/lib/testing/storyboard/request-signing/builder.d.mts +21 -1
  166. package/dist/lib/testing/storyboard/request-signing/builder.d.ts +21 -1
  167. package/dist/lib/testing/storyboard/request-signing/builder.js +22 -0
  168. package/dist/lib/testing/storyboard/request-signing/builder.mjs +22 -0
  169. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +5 -6
  170. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +5 -6
  171. package/dist/lib/testing/storyboard/request-signing/grader.js +79 -8
  172. package/dist/lib/testing/storyboard/request-signing/grader.mjs +79 -8
  173. package/dist/lib/testing/storyboard/request-signing/index.d.mts +1 -0
  174. package/dist/lib/testing/storyboard/request-signing/index.d.ts +1 -0
  175. package/dist/lib/testing/storyboard/request-signing/index.js +7 -0
  176. package/dist/lib/testing/storyboard/request-signing/index.mjs +8 -0
  177. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.mts +10 -29
  178. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.d.ts +10 -29
  179. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.js +49 -5
  180. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +39 -5
  181. package/dist/lib/testing/storyboard/runner.js +28 -2
  182. package/dist/lib/testing/storyboard/runner.mjs +18 -2
  183. package/dist/lib/testing/storyboard/types.d.mts +8 -19
  184. package/dist/lib/testing/storyboard/types.d.ts +8 -19
  185. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  186. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  187. package/dist/lib/types/index.d.mts +11 -2
  188. package/dist/lib/types/index.d.ts +11 -2
  189. package/dist/lib/types/schemas.generated.d.ts +8 -8
  190. package/dist/lib/types/schemas.generated.js +17 -0
  191. package/dist/lib/types/schemas.generated.mjs +17 -0
  192. package/dist/lib/utils/idempotency.d.mts +4 -2
  193. package/dist/lib/utils/idempotency.d.ts +4 -2
  194. package/dist/lib/utils/idempotency.js +41 -22
  195. package/dist/lib/utils/idempotency.mjs +41 -22
  196. package/dist/lib/utils/media-buy-status.js +3 -2
  197. package/dist/lib/utils/media-buy-status.mjs +3 -2
  198. package/dist/lib/utils/reporting-status-response.js +2 -2
  199. package/dist/lib/utils/reporting-status-response.mjs +2 -2
  200. package/dist/lib/utils/response-schema-cache.d.mts +3 -0
  201. package/dist/lib/utils/response-schema-cache.d.ts +3 -0
  202. package/dist/lib/utils/response-schema-cache.js +45 -0
  203. package/dist/lib/utils/response-schema-cache.mjs +20 -0
  204. package/dist/lib/utils/response-schemas.js +2 -0
  205. package/dist/lib/utils/response-schemas.mjs +2 -0
  206. package/dist/lib/utils/response-unwrapper.d.mts +1 -1
  207. package/dist/lib/utils/response-unwrapper.d.ts +1 -1
  208. package/dist/lib/utils/response-unwrapper.js +15 -8
  209. package/dist/lib/utils/response-unwrapper.mjs +14 -2
  210. package/dist/lib/v2/projection/v1-to-v2.js +2 -2
  211. package/dist/lib/v2/projection/v1-to-v2.mjs +6 -1
  212. package/dist/lib/validation/schema-loader.js +13 -6
  213. package/dist/lib/validation/schema-loader.mjs +13 -6
  214. package/dist/lib/version.d.mts +3 -3
  215. package/dist/lib/version.d.ts +3 -3
  216. package/dist/lib/version.js +3 -3
  217. package/dist/lib/version.mjs +3 -3
  218. package/dist/lib/wholesale-feed-sync/index.d.mts +3 -1
  219. package/dist/lib/wholesale-feed-sync/index.d.ts +3 -1
  220. package/dist/lib/wholesale-feed-sync/index.js +7 -2
  221. package/dist/lib/wholesale-feed-sync/index.mjs +4 -1
  222. package/dist/lib/wholesale-feed-sync/register.d.mts +49 -0
  223. package/dist/lib/wholesale-feed-sync/register.d.ts +49 -0
  224. package/dist/lib/wholesale-feed-sync/register.js +115 -0
  225. package/dist/lib/wholesale-feed-sync/register.mjs +90 -0
  226. package/dist/lib/wholesale-feed-sync/sync.d.mts +7 -0
  227. package/dist/lib/wholesale-feed-sync/sync.d.ts +7 -0
  228. package/dist/lib/wholesale-feed-sync/sync.js +161 -4
  229. package/dist/lib/wholesale-feed-sync/sync.mjs +161 -4
  230. package/dist/lib/wholesale-feed-sync/types.d.mts +51 -1
  231. package/dist/lib/wholesale-feed-sync/types.d.ts +51 -1
  232. package/docs/TYPE-SUMMARY.md +10 -2
  233. package/docs/guides/ACCEPTANCE-POLICY-DISCOVERY.md +104 -0
  234. package/docs/guides/BUILD-AN-AGENT.md +7 -5
  235. package/docs/guides/EXISTING-PLATFORM.md +61 -33
  236. package/docs/guides/MEDIA-BUY-3.2-COMPATIBILITY.md +27 -1
  237. package/docs/guides/PERSISTENT-NOTIFICATION-RUNTIME.md +7 -7
  238. package/docs/guides/PRINCIPAL-LIFECYCLE.md +236 -0
  239. package/docs/guides/PRODUCTION-DURABILITY.md +4 -0
  240. package/docs/guides/REPORTING-LEDGER.md +3 -1
  241. package/docs/guides/REPORTING-RECONCILIATION.md +96 -1
  242. package/docs/guides/VALIDATE-YOUR-AGENT.md +28 -4
  243. package/docs/llms.txt +3 -3
  244. package/docs/migration-14.x-rc-worksheet.md +4 -4
  245. package/examples/README.md +13 -0
  246. package/examples/existing-platform-thin.ts +29 -1
  247. package/examples/targeting-input-existing-platform.ts +2 -8
  248. package/examples/wholesale-feed-sync.ts +274 -0
  249. package/package.json +17 -1
  250. package/skills/build-seller-agent/specialisms/signed-requests.md +1 -1
@@ -0,0 +1,1107 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var acceptance_policy_exports = {};
20
+ __export(acceptance_policy_exports, {
21
+ createAcceptancePolicyCatalogResolver: () => createAcceptancePolicyCatalogResolver,
22
+ resolveAcceptancePolicyCatalog: () => resolveAcceptancePolicyCatalog,
23
+ resolveAcceptancePolicyProfiles: () => resolveAcceptancePolicyProfiles,
24
+ resolveVerifiedAcceptancePolicyProfiles: () => resolveVerifiedAcceptancePolicyProfiles
25
+ });
26
+ module.exports = __toCommonJS(acceptance_policy_exports);
27
+ var import_jcs = require('../utils/jcs.js');
28
+ var import_canonical_references = require('../canonical-references/index.js');
29
+ var import_schema_loader = require('../validation/schema-loader.js');
30
+ var import_version = require('../version.js');
31
+ var import_well_formed_unicode = require('../utils/well-formed-unicode.js');
32
+ const CATALOG_SCHEMA_REF = "media-buy/acceptance-policy-catalog.json";
33
+ const PROFILE_SCHEMA_REF = "media-buy/acceptance-policy-profile.json";
34
+ const DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
35
+ const DEFAULT_TIMEOUT_MS = 5e3;
36
+ const DEFAULT_MAX_BODY_BYTES = 1024 * 1024;
37
+ const MAX_TIMEOUT_MS = 3e4;
38
+ const MAX_BODY_BYTES = 1024 * 1024;
39
+ const MAX_CANONICAL_JSON_DEPTH = 128;
40
+ const MAX_CATALOG_JSON_DEPTH = 256;
41
+ const MAX_CATALOG_JSON_NODES = 1e5;
42
+ const MAX_CATALOG_JSON_STRING_CODE_UNITS = 1024 * 1024;
43
+ const DEFAULT_MAX_REGISTRY_PROFILES = 32;
44
+ const MAX_REGISTRY_PROFILES = 32;
45
+ const MAX_REGISTRY_CONCURRENCY = 4;
46
+ const MAX_SELECTED_PROFILE_IDS = 1024;
47
+ const MAX_REGISTRY_JSON_NODES = 5e4;
48
+ const MAX_REGISTRY_JSON_STRING_CODE_UNITS = 256 * 1024;
49
+ function issue(code, message, pointer, options = {}) {
50
+ return {
51
+ code,
52
+ message,
53
+ pointer,
54
+ ...options.keyword !== void 0 && { keyword: options.keyword },
55
+ ...options.retryable !== void 0 && { retryable: options.retryable },
56
+ ...options.httpStatus !== void 0 && { httpStatus: options.httpStatus }
57
+ };
58
+ }
59
+ function fail(error, issues) {
60
+ return { ok: false, fromCache: false, error, ...issues !== void 0 && { issues } };
61
+ }
62
+ function cloneJson(value) {
63
+ return JSON.parse(JSON.stringify(value));
64
+ }
65
+ function cloneCatalog(catalog) {
66
+ return cloneJson(catalog);
67
+ }
68
+ function cloneSuccess(result, fromCache) {
69
+ const catalog = cloneCatalog(result.catalog);
70
+ const sellerProfiles = new Map((catalog.profiles ?? []).map((profile) => [profile.profile_id, profile]));
71
+ const registryRefs = new Map((catalog.registry_profiles ?? []).map((ref) => [ref.profile_id, ref]));
72
+ const registryProfiles = /* @__PURE__ */ new Map();
73
+ return {
74
+ ok: true,
75
+ fromCache,
76
+ catalog,
77
+ ...result.issues !== void 0 && {
78
+ // cloneSuccess is used only by the capability-lifetime resolver. Its
79
+ // cached success cannot retry registry work until invalidate().
80
+ issues: cloneJson(
81
+ result.issues.map((value) => value.retryable === true ? { ...value, retryable: false } : value)
82
+ )
83
+ },
84
+ defaultProfiles: result.defaultProfiles.map((value) => {
85
+ if (value.source === "seller") {
86
+ return { ...value, profile: sellerProfiles.get(value.profileId) ?? cloneJson(value.profile) };
87
+ }
88
+ const ref = registryRefs.get(value.profileId) ?? cloneJson(value.ref);
89
+ if (value.resolution === "resolved") {
90
+ let profile = registryProfiles.get(value.profileId);
91
+ if (!profile) {
92
+ profile = cloneJson(value.profile);
93
+ registryProfiles.set(value.profileId, profile);
94
+ }
95
+ return { ...value, ref, profile };
96
+ }
97
+ return { ...value, ref };
98
+ })
99
+ };
100
+ }
101
+ function snapshotCapability(capability) {
102
+ const snapshot = { ...capability };
103
+ if (Array.isArray(snapshot.default_profile_ids)) {
104
+ snapshot.default_profile_ids = [...snapshot.default_profile_ids];
105
+ }
106
+ return snapshot;
107
+ }
108
+ function validateCapability(capability, options) {
109
+ if (!capability || typeof capability.catalog_url !== "string" || typeof capability.catalog_digest !== "string") {
110
+ return issue(
111
+ "invalid_capability",
112
+ "Acceptance-policy discovery must provide catalog_url and catalog_digest strings",
113
+ "/media_buy/acceptance_policy_discovery"
114
+ );
115
+ }
116
+ if (!DIGEST_RE.test(capability.catalog_digest)) {
117
+ return issue(
118
+ "invalid_capability",
119
+ "catalog_digest must be sha256 followed by 64 lowercase hexadecimal characters",
120
+ "/media_buy/acceptance_policy_discovery/catalog_digest"
121
+ );
122
+ }
123
+ let parsed;
124
+ try {
125
+ parsed = new URL(capability.catalog_url);
126
+ } catch {
127
+ return issue("unsafe_url", "catalog_url is not a valid URL", "/media_buy/acceptance_policy_discovery/catalog_url");
128
+ }
129
+ if (parsed.username !== "" || parsed.password !== "") {
130
+ return issue(
131
+ "unsafe_url",
132
+ "catalog_url must not contain URL credentials",
133
+ "/media_buy/acceptance_policy_discovery/catalog_url"
134
+ );
135
+ }
136
+ const unsafeHttpAllowed = options.allowUnsafeHttp === true && parsed.protocol === "http:";
137
+ if (parsed.protocol !== "https:" && !unsafeHttpAllowed) {
138
+ return issue("unsafe_url", "catalog_url must use HTTPS", "/media_buy/acceptance_policy_discovery/catalog_url");
139
+ }
140
+ const defaults = capability.default_profile_ids;
141
+ if (defaults !== void 0) {
142
+ if (!Array.isArray(defaults) || defaults.length === 0 || defaults.length > MAX_SELECTED_PROFILE_IDS || defaults.some((value) => typeof value !== "string" || value.length === 0)) {
143
+ return issue(
144
+ "invalid_capability",
145
+ `default_profile_ids must contain 1-${MAX_SELECTED_PROFILE_IDS} non-empty strings`,
146
+ "/media_buy/acceptance_policy_discovery/default_profile_ids"
147
+ );
148
+ }
149
+ if (new Set(defaults).size !== defaults.length) {
150
+ return issue(
151
+ "invalid_capability",
152
+ "default_profile_ids must be unique",
153
+ "/media_buy/acceptance_policy_discovery/default_profile_ids"
154
+ );
155
+ }
156
+ }
157
+ return void 0;
158
+ }
159
+ function validateOptions(options) {
160
+ if (options.registryResolver !== void 0 && (options.registryResolver === null || typeof options.registryResolver.resolvePolicy !== "function")) {
161
+ return issue(
162
+ "invalid_options",
163
+ "registryResolver must provide a resolvePolicy function",
164
+ "/options/registryResolver"
165
+ );
166
+ }
167
+ if (options.allowUnsafeHttp === true && options.allowPrivateNetwork !== true) {
168
+ return issue(
169
+ "invalid_options",
170
+ "allowUnsafeHttp requires allowPrivateNetwork and is only intended for local test fixtures",
171
+ "/options/allowUnsafeHttp"
172
+ );
173
+ }
174
+ if (options.timeoutMs !== void 0 && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > MAX_TIMEOUT_MS)) {
175
+ return issue(
176
+ "invalid_options",
177
+ `timeoutMs must be a positive safe integer no greater than ${MAX_TIMEOUT_MS}`,
178
+ "/options/timeoutMs"
179
+ );
180
+ }
181
+ if (options.registryTimeoutMs !== void 0 && (!Number.isSafeInteger(options.registryTimeoutMs) || options.registryTimeoutMs <= 0 || options.registryTimeoutMs > MAX_TIMEOUT_MS)) {
182
+ return issue(
183
+ "invalid_options",
184
+ `registryTimeoutMs must be a positive safe integer no greater than ${MAX_TIMEOUT_MS}`,
185
+ "/options/registryTimeoutMs"
186
+ );
187
+ }
188
+ if (options.maxRegistryProfiles !== void 0 && (!Number.isSafeInteger(options.maxRegistryProfiles) || options.maxRegistryProfiles <= 0 || options.maxRegistryProfiles > MAX_REGISTRY_PROFILES)) {
189
+ return issue(
190
+ "invalid_options",
191
+ `maxRegistryProfiles must be a positive safe integer no greater than ${MAX_REGISTRY_PROFILES}`,
192
+ "/options/maxRegistryProfiles"
193
+ );
194
+ }
195
+ if (options.maxBodyBytes !== void 0 && (!Number.isSafeInteger(options.maxBodyBytes) || options.maxBodyBytes <= 0 || options.maxBodyBytes > MAX_BODY_BYTES)) {
196
+ return issue(
197
+ "invalid_options",
198
+ `maxBodyBytes must be a positive safe integer no greater than ${MAX_BODY_BYTES}`,
199
+ "/options/maxBodyBytes"
200
+ );
201
+ }
202
+ return void 0;
203
+ }
204
+ function translateFetchFailure(result) {
205
+ const pointer = "/media_buy/acceptance_policy_discovery/catalog_url";
206
+ const transport = { retryable: result.error.retryable, httpStatus: result.httpStatus };
207
+ switch (result.error.code) {
208
+ case "redirect_blocked":
209
+ return fail(issue("redirect_blocked", "Acceptance-policy catalog redirects are disabled", pointer, transport));
210
+ case "body_too_large":
211
+ return fail(
212
+ issue("body_too_large", "Acceptance-policy catalog exceeded the configured byte limit", pointer, transport)
213
+ );
214
+ case "digest_mismatch":
215
+ return fail(
216
+ issue(
217
+ "digest_mismatch",
218
+ "Acceptance-policy catalog digest did not match the exact response bytes",
219
+ "/media_buy/acceptance_policy_discovery/catalog_digest",
220
+ transport
221
+ )
222
+ );
223
+ case "invalid_json":
224
+ return fail(issue("invalid_json", "Acceptance-policy catalog is not valid JSON", "/", transport));
225
+ case "document_too_deep":
226
+ return fail(
227
+ issue("catalog_document_invalid", "Acceptance-policy catalog exceeds the safe JSON depth limit", "/", transport)
228
+ );
229
+ case "http_error":
230
+ return fail(
231
+ issue("http_error", "Acceptance-policy catalog returned a non-success HTTP status", pointer, transport)
232
+ );
233
+ case "non_https_url":
234
+ case "unsafe_url":
235
+ case "invalid_ref":
236
+ return fail(
237
+ issue("unsafe_url", "Acceptance-policy catalog URL was blocked by remote-resolution policy", pointer, transport)
238
+ );
239
+ default:
240
+ return fail(issue("fetch_failed", "Acceptance-policy catalog could not be fetched", pointer, transport));
241
+ }
242
+ }
243
+ const SAFE_POINTER_SEGMENTS = /* @__PURE__ */ new Set([
244
+ "profiles",
245
+ "registry_profiles",
246
+ "catalog_version",
247
+ "generated_at",
248
+ "ext",
249
+ "profile_id",
250
+ "profile_version",
251
+ "profile_digest",
252
+ "version",
253
+ "content_digest",
254
+ "policy_id",
255
+ "policy_version",
256
+ "policy_digest",
257
+ "policy_refs",
258
+ "coverage",
259
+ "scope",
260
+ "region_aliases",
261
+ "description",
262
+ "rules",
263
+ "rule_id",
264
+ "subject_category",
265
+ "subject_categories",
266
+ "subject_facets",
267
+ "advertiser_roles",
268
+ "jurisdictions",
269
+ "jurisdiction_groups",
270
+ "all_jurisdictions",
271
+ "applies_to",
272
+ "disposition",
273
+ "requirements",
274
+ "policy_ids",
275
+ "effective_at",
276
+ "expires_at"
277
+ ]);
278
+ const ARRAY_POINTER_SEGMENTS = /* @__PURE__ */ new Set([
279
+ "profiles",
280
+ "registry_profiles",
281
+ "policy_refs",
282
+ "rules",
283
+ "subject_categories",
284
+ "subject_facets",
285
+ "advertiser_roles",
286
+ "jurisdictions",
287
+ "jurisdiction_groups",
288
+ "applies_to",
289
+ "policy_ids"
290
+ ]);
291
+ function sanitizePointer(pointer) {
292
+ if (!pointer || pointer === "/") return "/";
293
+ let numericIndexAllowed = false;
294
+ let regionAliasKeyExpected = false;
295
+ const sanitized = pointer.split("/").map((segment, index) => {
296
+ if (index === 0) return segment;
297
+ if (regionAliasKeyExpected) {
298
+ regionAliasKeyExpected = false;
299
+ numericIndexAllowed = true;
300
+ return "<property>";
301
+ }
302
+ if (/^\d+$/.test(segment)) {
303
+ const safe = numericIndexAllowed;
304
+ numericIndexAllowed = false;
305
+ return safe ? segment : "<property>";
306
+ }
307
+ if (SAFE_POINTER_SEGMENTS.has(segment)) {
308
+ regionAliasKeyExpected = segment === "region_aliases";
309
+ numericIndexAllowed = ARRAY_POINTER_SEGMENTS.has(segment);
310
+ return segment;
311
+ }
312
+ numericIndexAllowed = false;
313
+ return "<property>";
314
+ }).join("/");
315
+ return sanitized.length <= 256 ? sanitized : `${sanitized.slice(0, 244)}/<truncated>`;
316
+ }
317
+ function schemaIssues(errors) {
318
+ return (errors ?? []).map(
319
+ (error) => issue(
320
+ "schema_invalid",
321
+ `Acceptance-policy catalog failed schema validation: ${error.message ?? "validation failed"}`,
322
+ sanitizePointer(error.instancePath || "/"),
323
+ { keyword: error.keyword }
324
+ )
325
+ );
326
+ }
327
+ function semanticIssues(catalog, defaultProfileIds) {
328
+ const issues = [];
329
+ const record = (value) => {
330
+ if (issues.length < 32) issues.push(value);
331
+ };
332
+ const seenProfiles = /* @__PURE__ */ new Set();
333
+ const allProfiles = [
334
+ ...(catalog.profiles ?? []).map((profile, index) => ({ profile, pointer: `/profiles/${index}` })),
335
+ ...(catalog.registry_profiles ?? []).map((profile, index) => ({
336
+ profile,
337
+ pointer: `/registry_profiles/${index}`
338
+ }))
339
+ ];
340
+ for (const entry of allProfiles) {
341
+ if (seenProfiles.has(entry.profile.profile_id)) {
342
+ record(
343
+ issue(
344
+ "duplicate_profile_id",
345
+ "A profile_id must occur at most once across seller and registry profile lists",
346
+ `${entry.pointer}/profile_id`
347
+ )
348
+ );
349
+ }
350
+ seenProfiles.add(entry.profile.profile_id);
351
+ }
352
+ for (const [index, profileId] of defaultProfileIds.entries()) {
353
+ if (!seenProfiles.has(profileId)) {
354
+ record(
355
+ issue(
356
+ "unresolved_profile_id",
357
+ "An advertised default profile does not resolve in the catalog",
358
+ `/media_buy/acceptance_policy_discovery/default_profile_ids/${index}`
359
+ )
360
+ );
361
+ }
362
+ }
363
+ for (const [profileIndex, profile] of (catalog.profiles ?? []).entries()) {
364
+ const profilePointer = `/profiles/${profileIndex}`;
365
+ const { content_digest: _digest, ...digestInput } = profile;
366
+ const canonicalInputIssue = validateCanonicalJson(digestInput, profilePointer);
367
+ if (canonicalInputIssue) {
368
+ record(canonicalInputIssue);
369
+ continue;
370
+ }
371
+ let actualDigest;
372
+ try {
373
+ actualDigest = `sha256:${(0, import_jcs.canonicalJsonSha256)(digestInput)}`;
374
+ } catch {
375
+ record(
376
+ issue(
377
+ "profile_canonicalization_invalid",
378
+ "A seller profile cannot be canonicalized as RFC 8785 I-JSON",
379
+ profilePointer
380
+ )
381
+ );
382
+ continue;
383
+ }
384
+ if (actualDigest !== profile.content_digest) {
385
+ record(
386
+ issue(
387
+ "profile_digest_mismatch",
388
+ "A seller profile content_digest did not match its RFC 8785 canonical content",
389
+ `${profilePointer}/content_digest`
390
+ )
391
+ );
392
+ }
393
+ const policyIds = /* @__PURE__ */ new Set();
394
+ for (const [refIndex, reference] of profile.policy_refs.entries()) {
395
+ const policyId = reference.policy_id;
396
+ if (policyIds.has(policyId)) {
397
+ record(
398
+ issue(
399
+ "reference_invalid",
400
+ "A seller profile must reference each policy_id at most once",
401
+ `${profilePointer}/policy_refs/${refIndex}/policy_id`
402
+ )
403
+ );
404
+ }
405
+ policyIds.add(policyId);
406
+ }
407
+ const ruleIds = /* @__PURE__ */ new Set();
408
+ const regionAliases = new Set(Object.keys(profile.region_aliases ?? {}));
409
+ for (const [groupIndex, groupId] of (profile.scope?.jurisdiction_groups ?? []).entries()) {
410
+ if (!regionAliases.has(groupId)) {
411
+ record(
412
+ issue(
413
+ "reference_invalid",
414
+ "A scope jurisdiction group must resolve in the profile region_aliases",
415
+ `${profilePointer}/scope/jurisdiction_groups/${groupIndex}`
416
+ )
417
+ );
418
+ }
419
+ }
420
+ for (const [ruleIndex, rule] of profile.rules.entries()) {
421
+ const rulePointer = `${profilePointer}/rules/${ruleIndex}`;
422
+ if (ruleIds.has(rule.rule_id)) {
423
+ record(issue("reference_invalid", "A seller profile must use unique rule_id values", `${rulePointer}/rule_id`));
424
+ }
425
+ ruleIds.add(rule.rule_id);
426
+ for (const [policyIndex, policyId] of (rule.policy_ids ?? []).entries()) {
427
+ if (!policyIds.has(policyId)) {
428
+ record(
429
+ issue(
430
+ "reference_invalid",
431
+ "A rule policy_id must resolve to exactly one profile policy_refs entry",
432
+ `${rulePointer}/policy_ids/${policyIndex}`
433
+ )
434
+ );
435
+ }
436
+ }
437
+ for (const [groupIndex, groupId] of (rule.jurisdiction_groups ?? []).entries()) {
438
+ if (!regionAliases.has(groupId)) {
439
+ record(
440
+ issue(
441
+ "reference_invalid",
442
+ "A rule jurisdiction group must resolve in the profile region_aliases",
443
+ `${rulePointer}/jurisdiction_groups/${groupIndex}`
444
+ )
445
+ );
446
+ }
447
+ }
448
+ }
449
+ }
450
+ return issues;
451
+ }
452
+ function validateCanonicalJson(value, pointer, limits = {}) {
453
+ const pending = [{ value, depth: 0 }];
454
+ const ancestors = /* @__PURE__ */ new WeakSet();
455
+ let nodes = 0;
456
+ let stringCodeUnits = 0;
457
+ while (pending.length > 0) {
458
+ const current = pending.pop();
459
+ if (current.exit) {
460
+ ancestors.delete(current.value);
461
+ continue;
462
+ }
463
+ nodes += 1;
464
+ if (limits.maxNodes !== void 0 && nodes > limits.maxNodes) {
465
+ return issue("profile_canonicalization_invalid", "A seller profile exceeds the safe JSON node limit", pointer);
466
+ }
467
+ if (current.depth > MAX_CANONICAL_JSON_DEPTH) {
468
+ return issue(
469
+ "profile_canonicalization_invalid",
470
+ `A seller profile exceeds the maximum canonical JSON depth of ${MAX_CANONICAL_JSON_DEPTH}`,
471
+ pointer
472
+ );
473
+ }
474
+ if (typeof current.value === "number" && !Number.isFinite(current.value)) {
475
+ return issue("profile_canonicalization_invalid", "A seller profile contains a non-finite JSON number", pointer);
476
+ }
477
+ if (typeof current.value === "string") {
478
+ stringCodeUnits += current.value.length;
479
+ if (limits.maxStringCodeUnits !== void 0 && stringCodeUnits > limits.maxStringCodeUnits) {
480
+ return issue(
481
+ "profile_canonicalization_invalid",
482
+ "A seller profile exceeds the safe string-size limit",
483
+ pointer
484
+ );
485
+ }
486
+ if (!(0, import_well_formed_unicode.isWellFormedUnicodeString)(current.value)) {
487
+ return issue(
488
+ "profile_canonicalization_invalid",
489
+ "A seller profile must contain well-formed Unicode before RFC 8785 canonicalization",
490
+ pointer
491
+ );
492
+ }
493
+ continue;
494
+ }
495
+ if (current.value === null || typeof current.value !== "object") continue;
496
+ if (ancestors.has(current.value)) {
497
+ return issue("profile_canonicalization_invalid", "A seller profile must not contain JSON cycles", pointer);
498
+ }
499
+ ancestors.add(current.value);
500
+ pending.push({ ...current, exit: true });
501
+ if (Array.isArray(current.value)) {
502
+ for (const child of current.value) pending.push({ value: child, depth: current.depth + 1 });
503
+ continue;
504
+ }
505
+ for (const [key, child] of Object.entries(current.value)) {
506
+ stringCodeUnits += key.length;
507
+ if (limits.maxStringCodeUnits !== void 0 && stringCodeUnits > limits.maxStringCodeUnits) {
508
+ return issue(
509
+ "profile_canonicalization_invalid",
510
+ "A seller profile exceeds the safe string-size limit",
511
+ pointer
512
+ );
513
+ }
514
+ if (!(0, import_well_formed_unicode.isWellFormedUnicodeString)(key)) {
515
+ return issue(
516
+ "profile_canonicalization_invalid",
517
+ "A seller profile must contain well-formed Unicode before RFC 8785 canonicalization",
518
+ pointer
519
+ );
520
+ }
521
+ pending.push({ value: child, depth: current.depth + 1 });
522
+ }
523
+ }
524
+ return void 0;
525
+ }
526
+ function validateCatalogDocument(value) {
527
+ const pending = [{ value, depth: 0 }];
528
+ const ancestors = /* @__PURE__ */ new WeakSet();
529
+ let nodes = 0;
530
+ let stringCodeUnits = 0;
531
+ while (pending.length > 0) {
532
+ const current = pending.pop();
533
+ if (current.exit) {
534
+ ancestors.delete(current.value);
535
+ continue;
536
+ }
537
+ nodes += 1;
538
+ if (nodes > MAX_CATALOG_JSON_NODES) {
539
+ return issue("catalog_document_invalid", "Acceptance-policy catalog exceeds the safe JSON node limit", "/");
540
+ }
541
+ if (current.depth > MAX_CATALOG_JSON_DEPTH) {
542
+ return issue(
543
+ "catalog_document_invalid",
544
+ `Acceptance-policy catalog exceeds the maximum JSON depth of ${MAX_CATALOG_JSON_DEPTH}`,
545
+ "/"
546
+ );
547
+ }
548
+ if (typeof current.value === "number" && !Number.isFinite(current.value)) {
549
+ return issue("catalog_document_invalid", "Acceptance-policy catalog contains a non-finite JSON number", "/");
550
+ }
551
+ if (typeof current.value === "string") {
552
+ stringCodeUnits += current.value.length;
553
+ if (stringCodeUnits > MAX_CATALOG_JSON_STRING_CODE_UNITS) {
554
+ return issue("catalog_document_invalid", "Acceptance-policy catalog exceeds the safe string-size limit", "/");
555
+ }
556
+ if (!(0, import_well_formed_unicode.isWellFormedUnicodeString)(current.value)) {
557
+ return issue("catalog_document_invalid", "Acceptance-policy catalog must contain well-formed Unicode", "/");
558
+ }
559
+ continue;
560
+ }
561
+ if (current.value === null || typeof current.value !== "object") continue;
562
+ if (ancestors.has(current.value)) {
563
+ return issue("catalog_document_invalid", "Acceptance-policy catalog must not contain JSON cycles", "/");
564
+ }
565
+ ancestors.add(current.value);
566
+ pending.push({ ...current, exit: true });
567
+ if (Array.isArray(current.value)) {
568
+ for (const child of current.value) pending.push({ value: child, depth: current.depth + 1 });
569
+ continue;
570
+ }
571
+ for (const [key, child] of Object.entries(current.value)) {
572
+ stringCodeUnits += key.length;
573
+ if (stringCodeUnits > MAX_CATALOG_JSON_STRING_CODE_UNITS) {
574
+ return issue("catalog_document_invalid", "Acceptance-policy catalog exceeds the safe string-size limit", "/");
575
+ }
576
+ if (!(0, import_well_formed_unicode.isWellFormedUnicodeString)(key)) {
577
+ return issue("catalog_document_invalid", "Acceptance-policy catalog must contain well-formed Unicode", "/");
578
+ }
579
+ pending.push({ value: child, depth: current.depth + 1 });
580
+ }
581
+ }
582
+ return void 0;
583
+ }
584
+ function resolveDefaults(catalog, profileIds) {
585
+ return resolveAcceptancePolicyProfiles(catalog, profileIds).filter(
586
+ (value) => value.resolution !== "missing"
587
+ );
588
+ }
589
+ function resolveAcceptancePolicyProfiles(catalog, profileIds) {
590
+ const sellerProfiles = new Map((catalog.profiles ?? []).map((profile) => [profile.profile_id, profile]));
591
+ const registryProfiles = new Map((catalog.registry_profiles ?? []).map((profile) => [profile.profile_id, profile]));
592
+ return profileIds.map((profileId) => {
593
+ const seller = sellerProfiles.get(profileId);
594
+ if (seller) {
595
+ return { source: "seller", resolution: "resolved", profileId, profile: seller };
596
+ }
597
+ const ref = registryProfiles.get(profileId);
598
+ if (ref) return { source: "registry", resolution: "unresolved", profileId, ref };
599
+ return { source: "catalog", resolution: "missing", profileId };
600
+ });
601
+ }
602
+ function safeVersionLabel(version) {
603
+ return /^[0-9A-Za-z.-]{1,64}$/.test(version) ? version : "<requested version>";
604
+ }
605
+ const REGISTRY_TIMEOUT = /* @__PURE__ */ Symbol("registry-timeout");
606
+ async function waitForRegistryPolicy(pending, timeoutMs, controller) {
607
+ let timer;
608
+ try {
609
+ return await Promise.race([
610
+ pending,
611
+ new Promise((resolve) => {
612
+ timer = setTimeout(() => {
613
+ controller.abort();
614
+ resolve(REGISTRY_TIMEOUT);
615
+ }, timeoutMs);
616
+ })
617
+ ]);
618
+ } finally {
619
+ if (timer !== void 0) clearTimeout(timer);
620
+ }
621
+ }
622
+ async function resolveRegistryProfile(ref, pointer, options, deadlineAt, controller) {
623
+ let policy;
624
+ try {
625
+ const remainingMs = deadlineAt - performance.now();
626
+ if (controller.signal.aborted || remainingMs <= 0) {
627
+ return fail(
628
+ issue("registry_timeout", "Registry profile resolution exceeded the overall deadline", pointer, {
629
+ retryable: true
630
+ })
631
+ );
632
+ }
633
+ const resolved = await waitForRegistryPolicy(
634
+ options.registryResolver.resolvePolicy({
635
+ policy_id: ref.policy_id,
636
+ version: ref.policy_version,
637
+ signal: controller.signal
638
+ }),
639
+ remainingMs,
640
+ controller
641
+ );
642
+ if (controller.signal.aborted || performance.now() >= deadlineAt) {
643
+ return fail(
644
+ issue("registry_timeout", "Registry profile resolution exceeded the overall deadline", pointer, {
645
+ retryable: true
646
+ })
647
+ );
648
+ }
649
+ if (resolved === REGISTRY_TIMEOUT) {
650
+ return fail(
651
+ issue("registry_timeout", "Registry profile resolution exceeded the overall deadline", pointer, {
652
+ retryable: true
653
+ })
654
+ );
655
+ }
656
+ policy = resolved;
657
+ } catch {
658
+ if (controller.signal.aborted || performance.now() >= deadlineAt) {
659
+ return fail(
660
+ issue("registry_timeout", "Registry profile resolution exceeded the overall deadline", pointer, {
661
+ retryable: true
662
+ })
663
+ );
664
+ }
665
+ return fail(
666
+ issue("registry_fetch_failed", "The pinned registry policy could not be fetched", pointer, { retryable: true })
667
+ );
668
+ }
669
+ if (!policy || typeof policy !== "object") {
670
+ return fail(
671
+ issue("registry_reference_unresolved", "The pinned registry policy version did not resolve", pointer, {
672
+ retryable: false
673
+ })
674
+ );
675
+ }
676
+ if (policy.policy_id !== ref.policy_id || policy.version !== ref.policy_version) {
677
+ return fail(
678
+ issue("registry_policy_mismatch", "The registry returned a different policy identity or version", pointer)
679
+ );
680
+ }
681
+ if (policy.canonical_content === null || typeof policy.canonical_content !== "object" || Array.isArray(policy.canonical_content) || typeof policy.content_digest !== "string") {
682
+ return fail(
683
+ issue("registry_policy_unverifiable", "The registry policy lacks verifiable canonical content", pointer)
684
+ );
685
+ }
686
+ const registryJsonLimits = {
687
+ maxNodes: MAX_REGISTRY_JSON_NODES,
688
+ maxStringCodeUnits: MAX_REGISTRY_JSON_STRING_CODE_UNITS
689
+ };
690
+ if (validateCanonicalJson(policy.canonical_content, pointer, registryJsonLimits)) {
691
+ return fail(
692
+ issue("registry_policy_unverifiable", "The registry policy canonical content is not safe I-JSON", pointer)
693
+ );
694
+ }
695
+ let policyDigest;
696
+ try {
697
+ policyDigest = `sha256:${(0, import_jcs.canonicalJsonSha256)(policy.canonical_content)}`;
698
+ } catch {
699
+ return fail(
700
+ issue("registry_policy_unverifiable", "The registry policy canonical content cannot be verified", pointer)
701
+ );
702
+ }
703
+ if (policyDigest !== policy.content_digest || policyDigest !== ref.policy_digest) {
704
+ return fail(
705
+ issue("registry_policy_digest_mismatch", "The registry policy digest does not match the catalog pin", pointer)
706
+ );
707
+ }
708
+ const profileValue = policy.acceptance_profile;
709
+ if (profileValue === null || typeof profileValue !== "object" || Array.isArray(profileValue)) {
710
+ return fail(
711
+ issue("registry_profile_invalid", "The pinned registry policy does not contain an acceptance profile", pointer)
712
+ );
713
+ }
714
+ if (validateCanonicalJson(profileValue, pointer, registryJsonLimits)) {
715
+ return fail(issue("registry_profile_invalid", "The registry acceptance profile is not safe I-JSON", pointer));
716
+ }
717
+ const requestedVersion = options.adcpVersion ?? import_version.ADCP_VERSION;
718
+ let validator;
719
+ try {
720
+ validator = (0, import_schema_loader.getSchemaValidatorByRef)(PROFILE_SCHEMA_REF, requestedVersion, void 0, { allErrors: false });
721
+ } catch {
722
+ return fail(
723
+ issue(
724
+ "schema_unavailable",
725
+ `Acceptance-policy profile schema is unavailable for ${safeVersionLabel(requestedVersion)}`,
726
+ pointer
727
+ )
728
+ );
729
+ }
730
+ if (!validator) {
731
+ return fail(
732
+ issue(
733
+ "schema_unavailable",
734
+ `Acceptance-policy profile schema is unavailable for ${safeVersionLabel(requestedVersion)}`,
735
+ pointer
736
+ )
737
+ );
738
+ }
739
+ if (!validator(profileValue)) {
740
+ const error = issue(
741
+ "registry_profile_schema_invalid",
742
+ "The registry acceptance profile is incompatible with the selected AdCP schema",
743
+ pointer,
744
+ {
745
+ keyword: validator.errors?.[0]?.keyword
746
+ }
747
+ );
748
+ const details = schemaIssues(validator.errors).map((value) => ({
749
+ ...value,
750
+ message: "Acceptance-policy profile failed schema validation",
751
+ pointer: `${pointer}/acceptance_profile${value.pointer === "/" ? "" : value.pointer}`
752
+ }));
753
+ return fail(error, [error, ...details]);
754
+ }
755
+ const profile = profileValue;
756
+ if (profile.profile_id !== ref.profile_id || profile.version !== ref.profile_version) {
757
+ return fail(
758
+ issue("registry_profile_mismatch", "The registry returned a different profile identity or version", pointer)
759
+ );
760
+ }
761
+ if (profile.content_digest !== ref.profile_digest) {
762
+ return fail(
763
+ issue("registry_profile_digest_mismatch", "The registry profile digest does not match the catalog pin", pointer)
764
+ );
765
+ }
766
+ const { content_digest: _digest, ...profileDigestInput } = profile;
767
+ let profileDigest;
768
+ try {
769
+ profileDigest = `sha256:${(0, import_jcs.canonicalJsonSha256)(profileDigestInput)}`;
770
+ } catch {
771
+ return fail(
772
+ issue("registry_profile_digest_mismatch", "The registry profile canonical digest cannot be verified", pointer)
773
+ );
774
+ }
775
+ if (profileDigest !== profile.content_digest) {
776
+ return fail(
777
+ issue("registry_profile_digest_mismatch", "The registry profile content does not match its digest", pointer)
778
+ );
779
+ }
780
+ const semantic = semanticIssues({ catalog_version: "registry", profiles: [profile] }, []);
781
+ if (semantic.length > 0) {
782
+ const error = issue("registry_profile_invalid", "The registry profile failed integrity validation", pointer);
783
+ const details = semantic.map((value) => ({
784
+ ...value,
785
+ pointer: `${pointer}/acceptance_profile${value.pointer.replace(/^\/profiles\/0/, "")}`
786
+ }));
787
+ return fail(error, [error, ...details]);
788
+ }
789
+ return {
790
+ source: "registry",
791
+ resolution: "resolved",
792
+ profileId: ref.profile_id,
793
+ profile: cloneJson(profile),
794
+ ref
795
+ };
796
+ }
797
+ async function resolveVerifiedAcceptancePolicyProfiles(catalog, profileIds, options) {
798
+ const optionsSnapshot = { ...options };
799
+ return resolveVerifiedAcceptancePolicyProfilesInternal(catalog, profileIds, optionsSnapshot, false);
800
+ }
801
+ async function resolveVerifiedAcceptancePolicyProfilesInternal(catalog, profileIds, options, catalogAlreadyValidated) {
802
+ if (!options?.registryResolver || typeof options.registryResolver.resolvePolicy !== "function") {
803
+ return fail(
804
+ issue("invalid_options", "registryResolver must provide a resolvePolicy function", "/options/registryResolver")
805
+ );
806
+ }
807
+ if (options.timeoutMs !== void 0 && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > MAX_TIMEOUT_MS)) {
808
+ return fail(
809
+ issue(
810
+ "invalid_options",
811
+ `timeoutMs must be a positive safe integer no greater than ${MAX_TIMEOUT_MS}`,
812
+ "/options/timeoutMs"
813
+ )
814
+ );
815
+ }
816
+ if (options.maxRegistryProfiles !== void 0 && (!Number.isSafeInteger(options.maxRegistryProfiles) || options.maxRegistryProfiles <= 0 || options.maxRegistryProfiles > MAX_REGISTRY_PROFILES)) {
817
+ return fail(
818
+ issue(
819
+ "invalid_options",
820
+ `maxRegistryProfiles must be a positive safe integer no greater than ${MAX_REGISTRY_PROFILES}`,
821
+ "/options/maxRegistryProfiles"
822
+ )
823
+ );
824
+ }
825
+ if (!Array.isArray(profileIds) || profileIds.some((profileId) => typeof profileId !== "string" || profileId.length === 0)) {
826
+ return fail(issue("invalid_options", "profileIds must contain only non-empty strings", "/profileIds"));
827
+ }
828
+ if (profileIds.length > MAX_SELECTED_PROFILE_IDS) {
829
+ return fail(
830
+ issue(
831
+ "invalid_options",
832
+ `profileIds must contain no more than ${MAX_SELECTED_PROFILE_IDS} entries`,
833
+ "/profileIds"
834
+ )
835
+ );
836
+ }
837
+ const requestedVersion = options.adcpVersion ?? import_version.ADCP_VERSION;
838
+ let catalogSnapshot;
839
+ if (catalogAlreadyValidated) {
840
+ catalogSnapshot = catalog;
841
+ } else {
842
+ const documentIssue = validateCatalogDocument(catalog);
843
+ if (documentIssue) return fail(documentIssue);
844
+ let validator;
845
+ try {
846
+ validator = (0, import_schema_loader.getSchemaValidatorByRef)(CATALOG_SCHEMA_REF, requestedVersion, void 0, { allErrors: false });
847
+ } catch {
848
+ return fail(
849
+ issue(
850
+ "schema_unavailable",
851
+ `Acceptance-policy catalog schema is unavailable for ${safeVersionLabel(requestedVersion)}`,
852
+ "/"
853
+ )
854
+ );
855
+ }
856
+ if (!validator) {
857
+ return fail(
858
+ issue(
859
+ "schema_unavailable",
860
+ `Acceptance-policy catalog schema is unavailable for ${safeVersionLabel(requestedVersion)}`,
861
+ "/"
862
+ )
863
+ );
864
+ }
865
+ if (!validator(catalog)) {
866
+ const issues2 = schemaIssues(validator.errors);
867
+ return fail(
868
+ issues2[0] ?? issue("schema_invalid", "Acceptance-policy catalog failed schema validation", "/"),
869
+ issues2
870
+ );
871
+ }
872
+ const integrityIssues = semanticIssues(catalog, []);
873
+ if (integrityIssues.length > 0) return fail(integrityIssues[0], integrityIssues);
874
+ catalogSnapshot = cloneCatalog(catalog);
875
+ }
876
+ const classified = resolveAcceptancePolicyProfiles(catalogSnapshot, [...profileIds]);
877
+ const distinctRegistryProfiles = new Set(
878
+ classified.filter((value) => value.source === "registry" && value.resolution === "unresolved").map((value) => value.profileId)
879
+ );
880
+ const maxRegistryProfiles = options.maxRegistryProfiles ?? DEFAULT_MAX_REGISTRY_PROFILES;
881
+ if (distinctRegistryProfiles.size > maxRegistryProfiles) {
882
+ return {
883
+ ok: true,
884
+ profiles: classified,
885
+ issues: [
886
+ issue(
887
+ "registry_resolution_limit_exceeded",
888
+ "The selected registry profile count exceeds the configured resolution limit",
889
+ "/registry_profiles"
890
+ )
891
+ ]
892
+ };
893
+ }
894
+ const registryIndexes = new Map(
895
+ (catalogSnapshot.registry_profiles ?? []).map((ref, index) => [ref.profile_id, index])
896
+ );
897
+ const registryValues = new Map(
898
+ classified.filter(
899
+ (value) => value.source === "registry" && value.resolution === "unresolved"
900
+ ).map((value) => [value.profileId, value])
901
+ );
902
+ const resolutionByProfileId = /* @__PURE__ */ new Map();
903
+ const registryEntries = [...registryValues.entries()];
904
+ const controller = new AbortController();
905
+ const deadlineAt = performance.now() + (options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
906
+ let nextRegistryIndex = 0;
907
+ async function resolveWorker() {
908
+ while (nextRegistryIndex < registryEntries.length) {
909
+ const entryIndex = nextRegistryIndex++;
910
+ const [profileId, value] = registryEntries[entryIndex];
911
+ const catalogIndex = registryIndexes.get(profileId);
912
+ const resolved = await resolveRegistryProfile(
913
+ value.ref,
914
+ catalogIndex === void 0 ? "/registry_profiles" : `/registry_profiles/${catalogIndex}`,
915
+ options,
916
+ deadlineAt,
917
+ controller
918
+ );
919
+ resolutionByProfileId.set(profileId, resolved);
920
+ }
921
+ }
922
+ await Promise.all(
923
+ Array.from({ length: Math.min(MAX_REGISTRY_CONCURRENCY, registryEntries.length) }, async () => resolveWorker())
924
+ );
925
+ const profiles = [];
926
+ const issues = [];
927
+ const reportedFailures = /* @__PURE__ */ new Set();
928
+ for (const value of classified) {
929
+ if (value.source !== "registry" || value.resolution !== "unresolved") {
930
+ profiles.push(value);
931
+ continue;
932
+ }
933
+ const resolved = resolutionByProfileId.get(value.profileId);
934
+ if (!resolved || "ok" in resolved) {
935
+ profiles.push(value);
936
+ if (resolved && !reportedFailures.has(value.profileId)) {
937
+ issues.push(...resolved.issues ?? [resolved.error]);
938
+ reportedFailures.add(value.profileId);
939
+ }
940
+ continue;
941
+ }
942
+ profiles.push(resolved);
943
+ }
944
+ return { ok: true, profiles, ...issues.length > 0 && { issues } };
945
+ }
946
+ async function resolveOnce(capability, options) {
947
+ const invalidOptions = validateOptions(options);
948
+ if (invalidOptions) return fail(invalidOptions);
949
+ const invalid = validateCapability(capability, options);
950
+ if (invalid) return fail(invalid);
951
+ let fetched;
952
+ try {
953
+ fetched = await (0, import_canonical_references.resolveCanonicalReference)(
954
+ { uri: capability.catalog_url, digest: capability.catalog_digest },
955
+ {
956
+ timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
957
+ maxBodyBytes: options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES,
958
+ allowUnsafeHttp: options.allowUnsafeHttp,
959
+ allowPrivateNetwork: options.allowPrivateNetwork
960
+ }
961
+ );
962
+ } catch {
963
+ return fail(
964
+ issue(
965
+ "fetch_failed",
966
+ "Acceptance-policy catalog resolution failed safely",
967
+ "/media_buy/acceptance_policy_discovery/catalog_url",
968
+ { retryable: false }
969
+ )
970
+ );
971
+ }
972
+ if (!fetched.ok) return translateFetchFailure(fetched);
973
+ const requestedVersion = options.adcpVersion ?? import_version.ADCP_VERSION;
974
+ const displayVersion = safeVersionLabel(requestedVersion);
975
+ let validator;
976
+ try {
977
+ validator = (0, import_schema_loader.getSchemaValidatorByRef)(CATALOG_SCHEMA_REF, requestedVersion, void 0, { allErrors: false });
978
+ } catch {
979
+ return fail(
980
+ issue("schema_unavailable", `Acceptance-policy catalog schema is unavailable for ${displayVersion}`, "/")
981
+ );
982
+ }
983
+ if (!validator) {
984
+ return fail(
985
+ issue("schema_unavailable", `Acceptance-policy catalog schema is unavailable for ${displayVersion}`, "/")
986
+ );
987
+ }
988
+ if (!validator(fetched.document)) {
989
+ const issues2 = schemaIssues(validator.errors);
990
+ return fail(
991
+ issues2[0] ?? issue("schema_invalid", "Acceptance-policy catalog failed schema validation", "/"),
992
+ issues2
993
+ );
994
+ }
995
+ const catalog = fetched.document;
996
+ const issues = semanticIssues(catalog, capability.default_profile_ids ?? []);
997
+ if (issues.length > 0) return fail(issues[0], issues);
998
+ const documentIssue = validateCatalogDocument(catalog);
999
+ if (documentIssue) return fail(documentIssue);
1000
+ const clonedCatalog = cloneCatalog(catalog);
1001
+ let defaultProfiles = resolveDefaults(clonedCatalog, capability.default_profile_ids ?? []);
1002
+ let registryIssues;
1003
+ if (options.registryResolver && defaultProfiles.some((value) => value.resolution === "unresolved")) {
1004
+ const verified = await resolveVerifiedAcceptancePolicyProfilesInternal(
1005
+ clonedCatalog,
1006
+ capability.default_profile_ids ?? [],
1007
+ {
1008
+ registryResolver: options.registryResolver,
1009
+ adcpVersion: requestedVersion,
1010
+ timeoutMs: options.registryTimeoutMs,
1011
+ maxRegistryProfiles: options.maxRegistryProfiles
1012
+ },
1013
+ true
1014
+ );
1015
+ if (!verified.ok) return verified;
1016
+ registryIssues = verified.issues;
1017
+ defaultProfiles = verified.profiles.filter(
1018
+ (value) => value.resolution !== "missing"
1019
+ );
1020
+ }
1021
+ return {
1022
+ ok: true,
1023
+ fromCache: false,
1024
+ catalog: clonedCatalog,
1025
+ defaultProfiles,
1026
+ ...registryIssues !== void 0 && { issues: registryIssues }
1027
+ };
1028
+ }
1029
+ async function resolveAcceptancePolicyCatalog(capability, options = {}) {
1030
+ return resolveOnce(snapshotCapability(capability), { ...options });
1031
+ }
1032
+ function createAcceptancePolicyCatalogResolver(options = {}) {
1033
+ const resolverOptions = { ...options };
1034
+ let capabilityKey;
1035
+ let cached;
1036
+ let generation = 0;
1037
+ let inFlight;
1038
+ return {
1039
+ async resolve(capability) {
1040
+ const snapshot = snapshotCapability(capability);
1041
+ const nextKey = JSON.stringify({
1042
+ catalog_url: snapshot?.catalog_url,
1043
+ catalog_digest: snapshot?.catalog_digest,
1044
+ default_profile_ids: snapshot?.default_profile_ids
1045
+ });
1046
+ if (nextKey !== capabilityKey) {
1047
+ capabilityKey = nextKey;
1048
+ cached = void 0;
1049
+ inFlight = void 0;
1050
+ generation += 1;
1051
+ }
1052
+ if (cached) return cloneSuccess(cached, true);
1053
+ if (inFlight?.key === nextKey && inFlight.generation === generation) {
1054
+ let shared;
1055
+ try {
1056
+ shared = await inFlight.promise;
1057
+ } catch {
1058
+ return fail(
1059
+ issue(
1060
+ "fetch_failed",
1061
+ "Acceptance-policy catalog resolution failed safely",
1062
+ "/media_buy/acceptance_policy_discovery/catalog_url",
1063
+ { retryable: false }
1064
+ )
1065
+ );
1066
+ }
1067
+ return shared.ok ? cloneSuccess(shared, false) : shared;
1068
+ }
1069
+ const startedGeneration = generation;
1070
+ const promise = resolveOnce(snapshot, resolverOptions);
1071
+ inFlight = { key: nextKey, generation: startedGeneration, promise };
1072
+ let result;
1073
+ try {
1074
+ result = await promise;
1075
+ } catch {
1076
+ result = fail(
1077
+ issue(
1078
+ "fetch_failed",
1079
+ "Acceptance-policy catalog resolution failed safely",
1080
+ "/media_buy/acceptance_policy_discovery/catalog_url",
1081
+ { retryable: false }
1082
+ )
1083
+ );
1084
+ } finally {
1085
+ if (inFlight?.promise === promise) inFlight = void 0;
1086
+ }
1087
+ if (!result.ok) return result;
1088
+ if (generation === startedGeneration && capabilityKey === nextKey) {
1089
+ cached = cloneSuccess(result, false);
1090
+ }
1091
+ return cloneSuccess(result, false);
1092
+ },
1093
+ invalidate() {
1094
+ capabilityKey = void 0;
1095
+ cached = void 0;
1096
+ inFlight = void 0;
1097
+ generation += 1;
1098
+ }
1099
+ };
1100
+ }
1101
+ // Annotate the CommonJS export names for ESM import in node:
1102
+ 0 && (module.exports = {
1103
+ createAcceptancePolicyCatalogResolver,
1104
+ resolveAcceptancePolicyCatalog,
1105
+ resolveAcceptancePolicyProfiles,
1106
+ resolveVerifiedAcceptancePolicyProfiles
1107
+ });