@adcp/sdk 12.0.0 → 12.0.2

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 (959) hide show
  1. package/dist/lib/adapters/content-standards-adapter.mjs +0 -6
  2. package/dist/lib/adapters/content-standards-adapter.mjs.map +1 -1
  3. package/dist/lib/adapters/derived-account-store.mjs +0 -6
  4. package/dist/lib/adapters/derived-account-store.mjs.map +1 -1
  5. package/dist/lib/adapters/governance-adapter.mjs +0 -6
  6. package/dist/lib/adapters/governance-adapter.mjs.map +1 -1
  7. package/dist/lib/adapters/implicit-account-store.mjs +0 -6
  8. package/dist/lib/adapters/implicit-account-store.mjs.map +1 -1
  9. package/dist/lib/adapters/index.mjs +0 -6
  10. package/dist/lib/adapters/index.mjs.map +1 -1
  11. package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs +0 -6
  12. package/dist/lib/adapters/legacy/v2-5/create_media_buy.mjs.map +1 -1
  13. package/dist/lib/adapters/legacy/v2-5/get_products.mjs +0 -6
  14. package/dist/lib/adapters/legacy/v2-5/get_products.mjs.map +1 -1
  15. package/dist/lib/adapters/legacy/v2-5/index.mjs +0 -6
  16. package/dist/lib/adapters/legacy/v2-5/index.mjs.map +1 -1
  17. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs +0 -6
  18. package/dist/lib/adapters/legacy/v2-5/list_creative_formats.mjs.map +1 -1
  19. package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs +0 -6
  20. package/dist/lib/adapters/legacy/v2-5/preview_creative.mjs.map +1 -1
  21. package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs +0 -6
  22. package/dist/lib/adapters/legacy/v2-5/sync_creatives.mjs.map +1 -1
  23. package/dist/lib/adapters/legacy/v2-5/types.mjs +0 -6
  24. package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs +0 -6
  25. package/dist/lib/adapters/legacy/v2-5/update_media_buy.mjs.map +1 -1
  26. package/dist/lib/adapters/oauth-passthrough-resolver.mjs +0 -6
  27. package/dist/lib/adapters/oauth-passthrough-resolver.mjs.map +1 -1
  28. package/dist/lib/adapters/property-list-adapter.mjs +0 -6
  29. package/dist/lib/adapters/property-list-adapter.mjs.map +1 -1
  30. package/dist/lib/adapters/roster-account-store.mjs +0 -6
  31. package/dist/lib/adapters/roster-account-store.mjs.map +1 -1
  32. package/dist/lib/adapters/si-session-manager.mjs +0 -6
  33. package/dist/lib/adapters/si-session-manager.mjs.map +1 -1
  34. package/dist/lib/adapters/version/3.0/brand-fields.mjs +0 -6
  35. package/dist/lib/adapters/version/3.0/brand-fields.mjs.map +1 -1
  36. package/dist/lib/adapters/version/3.0/get-products.mjs +0 -6
  37. package/dist/lib/adapters/version/3.0/get-products.mjs.map +1 -1
  38. package/dist/lib/adapters/version/3.0/index.mjs +0 -6
  39. package/dist/lib/adapters/version/3.0/index.mjs.map +1 -1
  40. package/dist/lib/adapters/version/3.0/sync-accounts.mjs +0 -6
  41. package/dist/lib/adapters/version/3.0/sync-accounts.mjs.map +1 -1
  42. package/dist/lib/adapters/version/index.mjs +0 -6
  43. package/dist/lib/adapters/version/index.mjs.map +1 -1
  44. package/dist/lib/adapters/version/types.mjs +0 -6
  45. package/dist/lib/advanced.mjs +0 -6
  46. package/dist/lib/advanced.mjs.map +1 -1
  47. package/dist/lib/agents/index.generated.mjs +0 -6
  48. package/dist/lib/agents/index.generated.mjs.map +1 -1
  49. package/dist/lib/auth/index.mjs +0 -6
  50. package/dist/lib/auth/index.mjs.map +1 -1
  51. package/dist/lib/auth/oauth/CLIFlowHandler.mjs +0 -6
  52. package/dist/lib/auth/oauth/CLIFlowHandler.mjs.map +1 -1
  53. package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs +0 -6
  54. package/dist/lib/auth/oauth/ClientCredentialsFlow.mjs.map +1 -1
  55. package/dist/lib/auth/oauth/MCPOAuthProvider.mjs +0 -6
  56. package/dist/lib/auth/oauth/MCPOAuthProvider.mjs.map +1 -1
  57. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs +0 -6
  58. package/dist/lib/auth/oauth/NonInteractiveFlowHandler.mjs.map +1 -1
  59. package/dist/lib/auth/oauth/authorization-required.mjs +0 -6
  60. package/dist/lib/auth/oauth/authorization-required.mjs.map +1 -1
  61. package/dist/lib/auth/oauth/diagnose.mjs +0 -6
  62. package/dist/lib/auth/oauth/diagnose.mjs.map +1 -1
  63. package/dist/lib/auth/oauth/diagnostics.mjs +0 -6
  64. package/dist/lib/auth/oauth/diagnostics.mjs.map +1 -1
  65. package/dist/lib/auth/oauth/discovery.mjs +0 -6
  66. package/dist/lib/auth/oauth/discovery.mjs.map +1 -1
  67. package/dist/lib/auth/oauth/file-storage.mjs +0 -6
  68. package/dist/lib/auth/oauth/file-storage.mjs.map +1 -1
  69. package/dist/lib/auth/oauth/index.mjs +0 -6
  70. package/dist/lib/auth/oauth/index.mjs.map +1 -1
  71. package/dist/lib/auth/oauth/secret-resolver.mjs +0 -6
  72. package/dist/lib/auth/oauth/secret-resolver.mjs.map +1 -1
  73. package/dist/lib/auth/oauth/storage-registry.mjs +0 -6
  74. package/dist/lib/auth/oauth/storage-registry.mjs.map +1 -1
  75. package/dist/lib/auth/oauth/types.mjs +0 -6
  76. package/dist/lib/auth/oauth/types.mjs.map +1 -1
  77. package/dist/lib/auth/oauth/web-flow.mjs +0 -6
  78. package/dist/lib/auth/oauth/web-flow.mjs.map +1 -1
  79. package/dist/lib/brand/index.mjs +0 -6
  80. package/dist/lib/brand/index.mjs.map +1 -1
  81. package/dist/lib/canonical-references/index.mjs +6 -7
  82. package/dist/lib/canonical-references/index.mjs.map +1 -1
  83. package/dist/lib/client/index.mjs +0 -6
  84. package/dist/lib/client/index.mjs.map +1 -1
  85. package/dist/lib/compliance/index.mjs +0 -6
  86. package/dist/lib/compliance/index.mjs.map +1 -1
  87. package/dist/lib/compliance-fixtures/index.mjs +0 -6
  88. package/dist/lib/compliance-fixtures/index.mjs.map +1 -1
  89. package/dist/lib/compliance-fixtures/test-authorization-server.mjs +0 -6
  90. package/dist/lib/compliance-fixtures/test-authorization-server.mjs.map +1 -1
  91. package/dist/lib/conformance/index.mjs +0 -6
  92. package/dist/lib/conformance/index.mjs.map +1 -1
  93. package/dist/lib/conformance/invariants/uniformError.mjs +0 -6
  94. package/dist/lib/conformance/invariants/uniformError.mjs.map +1 -1
  95. package/dist/lib/conformance/invariants/uniformErrorComparator.mjs +0 -6
  96. package/dist/lib/conformance/invariants/uniformErrorComparator.mjs.map +1 -1
  97. package/dist/lib/conformance/oracle.mjs +0 -6
  98. package/dist/lib/conformance/oracle.mjs.map +1 -1
  99. package/dist/lib/conformance/runConformance.mjs +0 -6
  100. package/dist/lib/conformance/runConformance.mjs.map +1 -1
  101. package/dist/lib/conformance/runners.mjs +0 -6
  102. package/dist/lib/conformance/runners.mjs.map +1 -1
  103. package/dist/lib/conformance/schemaArbitrary.mjs +0 -6
  104. package/dist/lib/conformance/schemaArbitrary.mjs.map +1 -1
  105. package/dist/lib/conformance/schemaLoader.mjs +5 -6
  106. package/dist/lib/conformance/schemaLoader.mjs.map +1 -1
  107. package/dist/lib/conformance/seeder.mjs +0 -6
  108. package/dist/lib/conformance/seeder.mjs.map +1 -1
  109. package/dist/lib/conformance/types.mjs +0 -6
  110. package/dist/lib/conformance/types.mjs.map +1 -1
  111. package/dist/lib/conformance/webhook.mjs +0 -6
  112. package/dist/lib/conformance/webhook.mjs.map +1 -1
  113. package/dist/lib/core/ADCPMultiAgentClient.mjs +0 -6
  114. package/dist/lib/core/ADCPMultiAgentClient.mjs.map +1 -1
  115. package/dist/lib/core/AgentClient.mjs +0 -6
  116. package/dist/lib/core/AgentClient.mjs.map +1 -1
  117. package/dist/lib/core/AsyncHandler.mjs +0 -6
  118. package/dist/lib/core/AsyncHandler.mjs.map +1 -1
  119. package/dist/lib/core/ConfigurationManager.mjs +0 -6
  120. package/dist/lib/core/ConfigurationManager.mjs.map +1 -1
  121. package/dist/lib/core/ConversationTypes.mjs +0 -6
  122. package/dist/lib/core/CreativeAgentClient.mjs +0 -6
  123. package/dist/lib/core/CreativeAgentClient.mjs.map +1 -1
  124. package/dist/lib/core/GovernanceMiddleware.mjs +0 -6
  125. package/dist/lib/core/GovernanceMiddleware.mjs.map +1 -1
  126. package/dist/lib/core/GovernanceTypes.mjs +0 -6
  127. package/dist/lib/core/GovernanceTypes.mjs.map +1 -1
  128. package/dist/lib/core/ProtocolResponseParser.mjs +0 -6
  129. package/dist/lib/core/ProtocolResponseParser.mjs.map +1 -1
  130. package/dist/lib/core/ResponseValidator.mjs +0 -6
  131. package/dist/lib/core/ResponseValidator.mjs.map +1 -1
  132. package/dist/lib/core/SingleAgentClient.mjs +0 -6
  133. package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
  134. package/dist/lib/core/TaskEventTypes.mjs +0 -6
  135. package/dist/lib/core/TaskEventTypes.mjs.map +1 -1
  136. package/dist/lib/core/TaskExecutor.mjs +0 -6
  137. package/dist/lib/core/TaskExecutor.mjs.map +1 -1
  138. package/dist/lib/core/match.mjs +0 -6
  139. package/dist/lib/core/match.mjs.map +1 -1
  140. package/dist/lib/core/task-status.mjs +0 -6
  141. package/dist/lib/core/task-status.mjs.map +1 -1
  142. package/dist/lib/core/webhook-url.mjs +0 -6
  143. package/dist/lib/core/webhook-url.mjs.map +1 -1
  144. package/dist/lib/discovery/adagents-redirects.mjs +0 -6
  145. package/dist/lib/discovery/adagents-redirects.mjs.map +1 -1
  146. package/dist/lib/discovery/agent-directory.mjs +0 -6
  147. package/dist/lib/discovery/agent-directory.mjs.map +1 -1
  148. package/dist/lib/discovery/inline-publisher-properties.mjs +0 -6
  149. package/dist/lib/discovery/inline-publisher-properties.mjs.map +1 -1
  150. package/dist/lib/discovery/network-consistency-checker.mjs +0 -6
  151. package/dist/lib/discovery/network-consistency-checker.mjs.map +1 -1
  152. package/dist/lib/discovery/property-crawler.mjs +0 -6
  153. package/dist/lib/discovery/property-crawler.mjs.map +1 -1
  154. package/dist/lib/discovery/property-index.mjs +0 -6
  155. package/dist/lib/discovery/property-index.mjs.map +1 -1
  156. package/dist/lib/discovery/publisher-property-selector.mjs +0 -6
  157. package/dist/lib/discovery/publisher-property-selector.mjs.map +1 -1
  158. package/dist/lib/discovery/resolve-agent-properties.mjs +0 -6
  159. package/dist/lib/discovery/resolve-agent-properties.mjs.map +1 -1
  160. package/dist/lib/discovery/types.mjs +0 -6
  161. package/dist/lib/discovery/validate-adagents.mjs +0 -6
  162. package/dist/lib/discovery/validate-adagents.mjs.map +1 -1
  163. package/dist/lib/enums.mjs +0 -6
  164. package/dist/lib/enums.mjs.map +1 -1
  165. package/dist/lib/errors/index.mjs +0 -6
  166. package/dist/lib/errors/index.mjs.map +1 -1
  167. package/dist/lib/express-mcp/index.mjs +0 -6
  168. package/dist/lib/express-mcp/index.mjs.map +1 -1
  169. package/dist/lib/governance/index.mjs +0 -6
  170. package/dist/lib/governance/index.mjs.map +1 -1
  171. package/dist/lib/handlers/types.mjs +0 -6
  172. package/dist/lib/handlers/types.mjs.map +1 -1
  173. package/dist/lib/index.d.mts +1 -1
  174. package/dist/lib/index.d.ts +1 -1
  175. package/dist/lib/index.d.ts.map +1 -1
  176. package/dist/lib/index.js.map +1 -1
  177. package/dist/lib/index.mjs +0 -6
  178. package/dist/lib/index.mjs.map +1 -1
  179. package/dist/lib/media-buy/available-actions.mjs +0 -6
  180. package/dist/lib/media-buy/available-actions.mjs.map +1 -1
  181. package/dist/lib/media-buy/index.mjs +0 -6
  182. package/dist/lib/media-buy/index.mjs.map +1 -1
  183. package/dist/lib/media-buy/preflight.mjs +0 -6
  184. package/dist/lib/media-buy/preflight.mjs.map +1 -1
  185. package/dist/lib/media-buy/property-policy.mjs +0 -6
  186. package/dist/lib/media-buy/property-policy.mjs.map +1 -1
  187. package/dist/lib/media-buy/types.mjs +0 -6
  188. package/dist/lib/media-buy/types.mjs.map +1 -1
  189. package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
  190. package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
  191. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
  192. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
  193. package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
  194. package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
  195. package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
  196. package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
  197. package/dist/lib/mock-server/creative-template/server.mjs +0 -6
  198. package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
  199. package/dist/lib/mock-server/index.mjs +0 -6
  200. package/dist/lib/mock-server/index.mjs.map +1 -1
  201. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
  202. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
  203. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
  204. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
  205. package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
  206. package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
  207. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
  208. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
  209. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
  210. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
  211. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
  212. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
  213. package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
  214. package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
  215. package/dist/lib/mock-server/sales-social/server.mjs +0 -6
  216. package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
  217. package/dist/lib/mock-server/scenario.mjs +0 -6
  218. package/dist/lib/mock-server/scenario.mjs.map +1 -1
  219. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
  220. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
  221. package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
  222. package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
  223. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
  224. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
  225. package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
  226. package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
  227. package/dist/lib/net/address-guards.mjs +0 -6
  228. package/dist/lib/net/address-guards.mjs.map +1 -1
  229. package/dist/lib/net/index.mjs +0 -6
  230. package/dist/lib/net/index.mjs.map +1 -1
  231. package/dist/lib/net/ssrf-fetch.mjs +0 -6
  232. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  233. package/dist/lib/observability/index.mjs +0 -6
  234. package/dist/lib/observability/index.mjs.map +1 -1
  235. package/dist/lib/observability/tracing.mjs +6 -7
  236. package/dist/lib/observability/tracing.mjs.map +1 -1
  237. package/dist/lib/protocols/a2a.mjs +0 -6
  238. package/dist/lib/protocols/a2a.mjs.map +1 -1
  239. package/dist/lib/protocols/abort.mjs +0 -6
  240. package/dist/lib/protocols/abort.mjs.map +1 -1
  241. package/dist/lib/protocols/index.mjs +0 -6
  242. package/dist/lib/protocols/index.mjs.map +1 -1
  243. package/dist/lib/protocols/mcp-modern.mjs +0 -6
  244. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  245. package/dist/lib/protocols/mcp-tasks.mjs +0 -6
  246. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  247. package/dist/lib/protocols/mcp.mjs +0 -6
  248. package/dist/lib/protocols/mcp.mjs.map +1 -1
  249. package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
  250. package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
  251. package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
  252. package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
  253. package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
  254. package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
  255. package/dist/lib/registry/cursor-store.mjs +0 -6
  256. package/dist/lib/registry/cursor-store.mjs.map +1 -1
  257. package/dist/lib/registry/feed-stream.mjs +0 -6
  258. package/dist/lib/registry/feed-stream.mjs.map +1 -1
  259. package/dist/lib/registry/index.mjs +0 -6
  260. package/dist/lib/registry/index.mjs.map +1 -1
  261. package/dist/lib/registry/property-registry.mjs +0 -6
  262. package/dist/lib/registry/property-registry.mjs.map +1 -1
  263. package/dist/lib/registry/sync.mjs +0 -6
  264. package/dist/lib/registry/sync.mjs.map +1 -1
  265. package/dist/lib/registry/types.generated.mjs +0 -6
  266. package/dist/lib/registry/types.mjs +0 -6
  267. package/dist/lib/schemas/index.mjs +0 -6
  268. package/dist/lib/schemas/index.mjs.map +1 -1
  269. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  270. package/dist/lib/server/a2a-adapter.mjs +0 -6
  271. package/dist/lib/server/a2a-adapter.mjs.map +1 -1
  272. package/dist/lib/server/account-mode.mjs +0 -6
  273. package/dist/lib/server/account-mode.mjs.map +1 -1
  274. package/dist/lib/server/adcp-server.mjs +0 -6
  275. package/dist/lib/server/adcp-server.mjs.map +1 -1
  276. package/dist/lib/server/auth-introspection.mjs +0 -6
  277. package/dist/lib/server/auth-introspection.mjs.map +1 -1
  278. package/dist/lib/server/auth-signature.mjs +0 -6
  279. package/dist/lib/server/auth-signature.mjs.map +1 -1
  280. package/dist/lib/server/auth.mjs +0 -6
  281. package/dist/lib/server/auth.mjs.map +1 -1
  282. package/dist/lib/server/create-adcp-server.d.mts +13 -0
  283. package/dist/lib/server/create-adcp-server.d.ts +13 -0
  284. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  285. package/dist/lib/server/create-adcp-server.js +3 -2
  286. package/dist/lib/server/create-adcp-server.js.map +1 -1
  287. package/dist/lib/server/create-adcp-server.mjs +3 -8
  288. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  289. package/dist/lib/server/credential-policy.mjs +0 -6
  290. package/dist/lib/server/credential-policy.mjs.map +1 -1
  291. package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
  292. package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
  293. package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
  294. package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
  295. package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
  296. package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
  297. package/dist/lib/server/ctx-metadata/index.mjs +0 -6
  298. package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
  299. package/dist/lib/server/ctx-metadata/store.mjs +0 -6
  300. package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
  301. package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
  302. package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
  303. package/dist/lib/server/decisioning/account.mjs +0 -6
  304. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  305. package/dist/lib/server/decisioning/admin-router.mjs +0 -6
  306. package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
  307. package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
  308. package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
  309. package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
  310. package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
  311. package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
  312. package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
  313. package/dist/lib/server/decisioning/capabilities.mjs +0 -6
  314. package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
  315. package/dist/lib/server/decisioning/compose.mjs +0 -6
  316. package/dist/lib/server/decisioning/compose.mjs.map +1 -1
  317. package/dist/lib/server/decisioning/context.mjs +0 -6
  318. package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
  319. package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
  320. package/dist/lib/server/decisioning/helpers.mjs +0 -6
  321. package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
  322. package/dist/lib/server/decisioning/index.mjs +0 -6
  323. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  324. package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
  325. package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
  326. package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
  327. package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
  328. package/dist/lib/server/decisioning/pagination.mjs +0 -6
  329. package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
  330. package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
  331. package/dist/lib/server/decisioning/platform.mjs +0 -6
  332. package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
  333. package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
  334. package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
  335. package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
  336. package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
  337. package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
  338. package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
  339. package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
  340. package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
  341. package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
  342. package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
  343. package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
  344. package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
  345. package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
  346. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
  347. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
  348. package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
  349. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  350. package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
  351. package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
  352. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
  353. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
  354. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
  355. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
  356. package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
  357. package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
  358. package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
  359. package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
  360. package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
  361. package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
  362. package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
  363. package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
  364. package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
  365. package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
  366. package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
  367. package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
  368. package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
  369. package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
  370. package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
  371. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
  372. package/dist/lib/server/decisioning/start-time.mjs +0 -6
  373. package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
  374. package/dist/lib/server/decisioning/status-changes.mjs +0 -6
  375. package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
  376. package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
  377. package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
  378. package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
  379. package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
  380. package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
  381. package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
  382. package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
  383. package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
  384. package/dist/lib/server/dynamic-registry.mjs +0 -6
  385. package/dist/lib/server/dynamic-registry.mjs.map +1 -1
  386. package/dist/lib/server/envelope-allowlist.mjs +0 -6
  387. package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
  388. package/dist/lib/server/error-arm-tools.mjs +5 -6
  389. package/dist/lib/server/error-arm-tools.mjs.map +1 -1
  390. package/dist/lib/server/errors.mjs +0 -6
  391. package/dist/lib/server/errors.mjs.map +1 -1
  392. package/dist/lib/server/example-tld-guard.mjs +0 -6
  393. package/dist/lib/server/example-tld-guard.mjs.map +1 -1
  394. package/dist/lib/server/express-adapter.mjs +0 -6
  395. package/dist/lib/server/express-adapter.mjs.map +1 -1
  396. package/dist/lib/server/governance.mjs +0 -6
  397. package/dist/lib/server/governance.mjs.map +1 -1
  398. package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
  399. package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
  400. package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
  401. package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
  402. package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
  403. package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
  404. package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
  405. package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
  406. package/dist/lib/server/idempotency/index.mjs +0 -6
  407. package/dist/lib/server/idempotency/index.mjs.map +1 -1
  408. package/dist/lib/server/idempotency/store.mjs +0 -6
  409. package/dist/lib/server/idempotency/store.mjs.map +1 -1
  410. package/dist/lib/server/index.d.mts +1 -1
  411. package/dist/lib/server/index.d.ts +1 -1
  412. package/dist/lib/server/index.d.ts.map +1 -1
  413. package/dist/lib/server/index.js.map +1 -1
  414. package/dist/lib/server/index.mjs +0 -6
  415. package/dist/lib/server/index.mjs.map +1 -1
  416. package/dist/lib/server/legacy/v5/index.d.mts +1 -1
  417. package/dist/lib/server/legacy/v5/index.d.ts +1 -1
  418. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -1
  419. package/dist/lib/server/legacy/v5/index.js.map +1 -1
  420. package/dist/lib/server/legacy/v5/index.mjs +0 -6
  421. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  422. package/dist/lib/server/mcp-modern-server.mjs +0 -6
  423. package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
  424. package/dist/lib/server/media-buy-actions.mjs +0 -6
  425. package/dist/lib/server/media-buy-actions.mjs.map +1 -1
  426. package/dist/lib/server/media-buy-helpers.mjs +0 -6
  427. package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
  428. package/dist/lib/server/media-buy-store.mjs +0 -6
  429. package/dist/lib/server/media-buy-store.mjs.map +1 -1
  430. package/dist/lib/server/normalize-errors.mjs +0 -6
  431. package/dist/lib/server/normalize-errors.mjs.map +1 -1
  432. package/dist/lib/server/operational-platform.mjs +0 -6
  433. package/dist/lib/server/operational-platform.mjs.map +1 -1
  434. package/dist/lib/server/pick-safe-details.mjs +0 -6
  435. package/dist/lib/server/pick-safe-details.mjs.map +1 -1
  436. package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
  437. package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
  438. package/dist/lib/server/postgres-state-store.mjs +0 -6
  439. package/dist/lib/server/postgres-state-store.mjs.map +1 -1
  440. package/dist/lib/server/postgres-task-store.mjs +0 -6
  441. package/dist/lib/server/postgres-task-store.mjs.map +1 -1
  442. package/dist/lib/server/product-defaults.mjs +0 -6
  443. package/dist/lib/server/product-defaults.mjs.map +1 -1
  444. package/dist/lib/server/redact.mjs +0 -6
  445. package/dist/lib/server/redact.mjs.map +1 -1
  446. package/dist/lib/server/responses.mjs +0 -6
  447. package/dist/lib/server/responses.mjs.map +1 -1
  448. package/dist/lib/server/serve.mjs +0 -6
  449. package/dist/lib/server/serve.mjs.map +1 -1
  450. package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
  451. package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
  452. package/dist/lib/server/socket-mode/index.mjs +0 -6
  453. package/dist/lib/server/socket-mode/index.mjs.map +1 -1
  454. package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
  455. package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
  456. package/dist/lib/server/state-machine.mjs +0 -6
  457. package/dist/lib/server/state-machine.mjs.map +1 -1
  458. package/dist/lib/server/state-store.mjs +0 -6
  459. package/dist/lib/server/state-store.mjs.map +1 -1
  460. package/dist/lib/server/structured-serialize.mjs +0 -6
  461. package/dist/lib/server/structured-serialize.mjs.map +1 -1
  462. package/dist/lib/server/targeting-helpers.mjs +0 -6
  463. package/dist/lib/server/targeting-helpers.mjs.map +1 -1
  464. package/dist/lib/server/tasks.mjs +0 -6
  465. package/dist/lib/server/tasks.mjs.map +1 -1
  466. package/dist/lib/server/test-controller-bridge.mjs +0 -6
  467. package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
  468. package/dist/lib/server/test-controller.mjs +0 -6
  469. package/dist/lib/server/test-controller.mjs.map +1 -1
  470. package/dist/lib/server/upstream-helpers.mjs +0 -6
  471. package/dist/lib/server/upstream-helpers.mjs.map +1 -1
  472. package/dist/lib/server/webhook-emitter.mjs +0 -6
  473. package/dist/lib/server/webhook-emitter.mjs.map +1 -1
  474. package/dist/lib/server/wire-safe.mjs +0 -6
  475. package/dist/lib/server/wire-safe.mjs.map +1 -1
  476. package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
  477. package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
  478. package/dist/lib/server/wrap-envelope.mjs +0 -6
  479. package/dist/lib/server/wrap-envelope.mjs.map +1 -1
  480. package/dist/lib/signing/agent-context.mjs +0 -6
  481. package/dist/lib/signing/agent-context.mjs.map +1 -1
  482. package/dist/lib/signing/agent-fetch.mjs +0 -6
  483. package/dist/lib/signing/agent-fetch.mjs.map +1 -1
  484. package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
  485. package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
  486. package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
  487. package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
  488. package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
  489. package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
  490. package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
  491. package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
  492. package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
  493. package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
  494. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
  495. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
  496. package/dist/lib/signing/agent-resolver/index.mjs +0 -6
  497. package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
  498. package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
  499. package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
  500. package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
  501. package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
  502. package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
  503. package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
  504. package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
  505. package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
  506. package/dist/lib/signing/brand-jwks.mjs +0 -6
  507. package/dist/lib/signing/brand-jwks.mjs.map +1 -1
  508. package/dist/lib/signing/canonicalize.mjs +0 -6
  509. package/dist/lib/signing/canonicalize.mjs.map +1 -1
  510. package/dist/lib/signing/capability-cache.mjs +0 -6
  511. package/dist/lib/signing/capability-cache.mjs.map +1 -1
  512. package/dist/lib/signing/capability-priming.mjs +0 -6
  513. package/dist/lib/signing/capability-priming.mjs.map +1 -1
  514. package/dist/lib/signing/client.mjs +0 -6
  515. package/dist/lib/signing/client.mjs.map +1 -1
  516. package/dist/lib/signing/content-digest.mjs +0 -6
  517. package/dist/lib/signing/content-digest.mjs.map +1 -1
  518. package/dist/lib/signing/crypto.mjs +0 -6
  519. package/dist/lib/signing/crypto.mjs.map +1 -1
  520. package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
  521. package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
  522. package/dist/lib/signing/errors.mjs +0 -6
  523. package/dist/lib/signing/errors.mjs.map +1 -1
  524. package/dist/lib/signing/fetch-async.mjs +0 -6
  525. package/dist/lib/signing/fetch-async.mjs.map +1 -1
  526. package/dist/lib/signing/fetch.mjs +0 -6
  527. package/dist/lib/signing/fetch.mjs.map +1 -1
  528. package/dist/lib/signing/index.mjs +0 -6
  529. package/dist/lib/signing/index.mjs.map +1 -1
  530. package/dist/lib/signing/jwks-helpers.mjs +0 -6
  531. package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
  532. package/dist/lib/signing/jwks-https.mjs +0 -6
  533. package/dist/lib/signing/jwks-https.mjs.map +1 -1
  534. package/dist/lib/signing/jwks.mjs +0 -6
  535. package/dist/lib/signing/jwks.mjs.map +1 -1
  536. package/dist/lib/signing/middleware.mjs +0 -6
  537. package/dist/lib/signing/middleware.mjs.map +1 -1
  538. package/dist/lib/signing/parser.mjs +0 -6
  539. package/dist/lib/signing/parser.mjs.map +1 -1
  540. package/dist/lib/signing/postgres-replay-store.mjs +0 -6
  541. package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
  542. package/dist/lib/signing/protocol-response.mjs +0 -6
  543. package/dist/lib/signing/protocol-response.mjs.map +1 -1
  544. package/dist/lib/signing/provider.mjs +0 -6
  545. package/dist/lib/signing/redis-replay-store.mjs +0 -6
  546. package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
  547. package/dist/lib/signing/replay.mjs +0 -6
  548. package/dist/lib/signing/replay.mjs.map +1 -1
  549. package/dist/lib/signing/request-context.mjs +0 -6
  550. package/dist/lib/signing/request-context.mjs.map +1 -1
  551. package/dist/lib/signing/revocation-https.mjs +0 -6
  552. package/dist/lib/signing/revocation-https.mjs.map +1 -1
  553. package/dist/lib/signing/revocation.mjs +0 -6
  554. package/dist/lib/signing/revocation.mjs.map +1 -1
  555. package/dist/lib/signing/server.mjs +0 -6
  556. package/dist/lib/signing/server.mjs.map +1 -1
  557. package/dist/lib/signing/signer-async.mjs +0 -6
  558. package/dist/lib/signing/signer-async.mjs.map +1 -1
  559. package/dist/lib/signing/signer.mjs +0 -6
  560. package/dist/lib/signing/signer.mjs.map +1 -1
  561. package/dist/lib/signing/testing.mjs +0 -6
  562. package/dist/lib/signing/testing.mjs.map +1 -1
  563. package/dist/lib/signing/types.mjs +0 -6
  564. package/dist/lib/signing/types.mjs.map +1 -1
  565. package/dist/lib/signing/verifier.mjs +0 -6
  566. package/dist/lib/signing/verifier.mjs.map +1 -1
  567. package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
  568. package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
  569. package/dist/lib/signing/webhook-verifier.mjs +0 -6
  570. package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
  571. package/dist/lib/storage/MemoryStorage.mjs +0 -6
  572. package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
  573. package/dist/lib/storage/interfaces.mjs +0 -6
  574. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
  575. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
  576. package/dist/lib/substitution/encoder/index.mjs +0 -6
  577. package/dist/lib/substitution/encoder/index.mjs.map +1 -1
  578. package/dist/lib/substitution/index.mjs +0 -6
  579. package/dist/lib/substitution/index.mjs.map +1 -1
  580. package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
  581. package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
  582. package/dist/lib/substitution/observer/alignment.mjs +0 -6
  583. package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
  584. package/dist/lib/substitution/observer/assertions.mjs +0 -6
  585. package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
  586. package/dist/lib/substitution/observer/html-parser.mjs +0 -6
  587. package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
  588. package/dist/lib/substitution/observer/index.mjs +0 -6
  589. package/dist/lib/substitution/observer/index.mjs.map +1 -1
  590. package/dist/lib/substitution/observer/ssrf.mjs +0 -6
  591. package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
  592. package/dist/lib/substitution/rfc3986.mjs +0 -6
  593. package/dist/lib/substitution/rfc3986.mjs.map +1 -1
  594. package/dist/lib/substitution/translate.mjs +0 -6
  595. package/dist/lib/substitution/translate.mjs.map +1 -1
  596. package/dist/lib/substitution/types.mjs +0 -6
  597. package/dist/lib/substitution/vectors.mjs +0 -6
  598. package/dist/lib/substitution/vectors.mjs.map +1 -1
  599. package/dist/lib/testing/agent-tester.mjs +0 -6
  600. package/dist/lib/testing/agent-tester.mjs.map +1 -1
  601. package/dist/lib/testing/client.mjs +0 -6
  602. package/dist/lib/testing/client.mjs.map +1 -1
  603. package/dist/lib/testing/compliance/briefs.mjs +0 -6
  604. package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
  605. package/dist/lib/testing/compliance/comply.mjs +0 -6
  606. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  607. package/dist/lib/testing/compliance/index.mjs +0 -6
  608. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  609. package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
  610. package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
  611. package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
  612. package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
  613. package/dist/lib/testing/compliance/summary.mjs +0 -6
  614. package/dist/lib/testing/compliance/summary.mjs.map +1 -1
  615. package/dist/lib/testing/compliance/types.mjs +0 -6
  616. package/dist/lib/testing/comply-controller.mjs +0 -6
  617. package/dist/lib/testing/comply-controller.mjs.map +1 -1
  618. package/dist/lib/testing/controller-assertions.mjs +0 -6
  619. package/dist/lib/testing/controller-assertions.mjs.map +1 -1
  620. package/dist/lib/testing/formatter.mjs +0 -6
  621. package/dist/lib/testing/formatter.mjs.map +1 -1
  622. package/dist/lib/testing/index.mjs +0 -6
  623. package/dist/lib/testing/index.mjs.map +1 -1
  624. package/dist/lib/testing/local-agent-runner.mjs +0 -6
  625. package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
  626. package/dist/lib/testing/orchestrator.mjs +0 -6
  627. package/dist/lib/testing/orchestrator.mjs.map +1 -1
  628. package/dist/lib/testing/personas/index.mjs +0 -6
  629. package/dist/lib/testing/personas/index.mjs.map +1 -1
  630. package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
  631. package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
  632. package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
  633. package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
  634. package/dist/lib/testing/scenarios/creative.mjs +0 -6
  635. package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
  636. package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
  637. package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
  638. package/dist/lib/testing/scenarios/discovery.mjs +0 -6
  639. package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
  640. package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
  641. package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
  642. package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
  643. package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
  644. package/dist/lib/testing/scenarios/governance.mjs +0 -6
  645. package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
  646. package/dist/lib/testing/scenarios/health.mjs +0 -6
  647. package/dist/lib/testing/scenarios/health.mjs.map +1 -1
  648. package/dist/lib/testing/scenarios/index.mjs +0 -6
  649. package/dist/lib/testing/scenarios/index.mjs.map +1 -1
  650. package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
  651. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  652. package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
  653. package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
  654. package/dist/lib/testing/scenarios/signals.mjs +0 -6
  655. package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
  656. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
  657. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
  658. package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
  659. package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
  660. package/dist/lib/testing/seed-merge.mjs +0 -6
  661. package/dist/lib/testing/seed-merge.mjs.map +1 -1
  662. package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
  663. package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
  664. package/dist/lib/testing/storyboard/assertions.mjs +0 -6
  665. package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
  666. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
  667. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
  668. package/dist/lib/testing/storyboard/compliance.mjs +5 -6
  669. package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
  670. package/dist/lib/testing/storyboard/context.mjs +0 -6
  671. package/dist/lib/testing/storyboard/context.mjs.map +1 -1
  672. package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
  673. package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
  674. package/dist/lib/testing/storyboard/index.mjs +0 -6
  675. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  676. package/dist/lib/testing/storyboard/junit.mjs +0 -6
  677. package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
  678. package/dist/lib/testing/storyboard/loader.mjs +0 -6
  679. package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
  680. package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
  681. package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
  682. package/dist/lib/testing/storyboard/path.mjs +0 -6
  683. package/dist/lib/testing/storyboard/path.mjs.map +1 -1
  684. package/dist/lib/testing/storyboard/probes.mjs +0 -6
  685. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  686. package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
  687. package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
  688. package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
  689. package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
  690. package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
  691. package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
  692. package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
  693. package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
  694. package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
  695. package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
  696. package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
  697. package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
  698. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
  699. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
  700. package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
  701. package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
  702. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
  703. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
  704. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
  705. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
  706. package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
  707. package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
  708. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
  709. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
  710. package/dist/lib/testing/storyboard/runner.mjs +0 -6
  711. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  712. package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
  713. package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
  714. package/dist/lib/testing/storyboard/seeding.mjs +0 -6
  715. package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
  716. package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
  717. package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
  718. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
  719. package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
  720. package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
  721. package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
  722. package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
  723. package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
  724. package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
  725. package/dist/lib/testing/storyboard/task-map.mjs +0 -6
  726. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  727. package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
  728. package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
  729. package/dist/lib/testing/storyboard/types.mjs +0 -6
  730. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  731. package/dist/lib/testing/storyboard/validations.mjs +0 -6
  732. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  733. package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
  734. package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
  735. package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
  736. package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
  737. package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
  738. package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
  739. package/dist/lib/testing/stubs/index.mjs +0 -6
  740. package/dist/lib/testing/stubs/index.mjs.map +1 -1
  741. package/dist/lib/testing/test-controller.mjs +0 -6
  742. package/dist/lib/testing/test-controller.mjs.map +1 -1
  743. package/dist/lib/testing/test-helpers.mjs +0 -6
  744. package/dist/lib/testing/test-helpers.mjs.map +1 -1
  745. package/dist/lib/testing/types.mjs +0 -6
  746. package/dist/lib/types/adcp.mjs +0 -6
  747. package/dist/lib/types/adcp.mjs.map +1 -1
  748. package/dist/lib/types/asset-instances.mjs +0 -6
  749. package/dist/lib/types/compat.mjs +0 -6
  750. package/dist/lib/types/compat.mjs.map +1 -1
  751. package/dist/lib/types/core.generated.mjs +0 -6
  752. package/dist/lib/types/enums.generated.mjs +0 -6
  753. package/dist/lib/types/enums.generated.mjs.map +1 -1
  754. package/dist/lib/types/error-codes.mjs +0 -6
  755. package/dist/lib/types/error-codes.mjs.map +1 -1
  756. package/dist/lib/types/error-details.aliases.mjs +0 -6
  757. package/dist/lib/types/error-details.aliases.mjs.map +1 -1
  758. package/dist/lib/types/format-asset-slots.mjs +0 -6
  759. package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
  760. package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
  761. package/dist/lib/types/index.mjs +0 -6
  762. package/dist/lib/types/index.mjs.map +1 -1
  763. package/dist/lib/types/inline-enums.aliases.mjs +0 -6
  764. package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
  765. package/dist/lib/types/inline-enums.generated.mjs +0 -6
  766. package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
  767. package/dist/lib/types/manifest.generated.mjs +0 -6
  768. package/dist/lib/types/manifest.generated.mjs.map +1 -1
  769. package/dist/lib/types/schemas.generated.mjs +0 -6
  770. package/dist/lib/types/schemas.generated.mjs.map +1 -1
  771. package/dist/lib/types/server-payload-aliases.mjs +0 -6
  772. package/dist/lib/types/server-payload.mjs +0 -6
  773. package/dist/lib/types/sync-rows.mjs +0 -6
  774. package/dist/lib/types/tools.generated.mjs +0 -6
  775. package/dist/lib/types/v2-5/index.mjs +0 -6
  776. package/dist/lib/types/v2-5/index.mjs.map +1 -1
  777. package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
  778. package/dist/lib/types/v3-1-beta/index.mjs +0 -6
  779. package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
  780. package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
  781. package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
  782. package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
  783. package/dist/lib/upstream-recorder/constants.mjs +0 -6
  784. package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
  785. package/dist/lib/upstream-recorder/index.mjs +0 -6
  786. package/dist/lib/upstream-recorder/index.mjs.map +1 -1
  787. package/dist/lib/upstream-recorder/recorder.mjs +0 -6
  788. package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
  789. package/dist/lib/upstream-recorder/types.mjs +0 -6
  790. package/dist/lib/upstream-recorder/types.mjs.map +1 -1
  791. package/dist/lib/utils/a2a-artifacts.mjs +0 -6
  792. package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
  793. package/dist/lib/utils/a2a-discovery.mjs +0 -6
  794. package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
  795. package/dist/lib/utils/activation-key-builders.mjs +0 -6
  796. package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
  797. package/dist/lib/utils/adcp-version-config.mjs +0 -6
  798. package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
  799. package/dist/lib/utils/asset-builders.mjs +0 -6
  800. package/dist/lib/utils/asset-builders.mjs.map +1 -1
  801. package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
  802. package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
  803. package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
  804. package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
  805. package/dist/lib/utils/capabilities.mjs +0 -6
  806. package/dist/lib/utils/capabilities.mjs.map +1 -1
  807. package/dist/lib/utils/capability-rollups.mjs +0 -6
  808. package/dist/lib/utils/capability-rollups.mjs.map +1 -1
  809. package/dist/lib/utils/creative-adapter.mjs +0 -6
  810. package/dist/lib/utils/creative-adapter.mjs.map +1 -1
  811. package/dist/lib/utils/creative-delivery.mjs +0 -6
  812. package/dist/lib/utils/creative-delivery.mjs.map +1 -1
  813. package/dist/lib/utils/deprecation.mjs +0 -6
  814. package/dist/lib/utils/deprecation.mjs.map +1 -1
  815. package/dist/lib/utils/envelope-status-compat.mjs +0 -6
  816. package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
  817. package/dist/lib/utils/error-extraction.mjs +0 -6
  818. package/dist/lib/utils/error-extraction.mjs.map +1 -1
  819. package/dist/lib/utils/extract-result.mjs +0 -6
  820. package/dist/lib/utils/extract-result.mjs.map +1 -1
  821. package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
  822. package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
  823. package/dist/lib/utils/format-assets.mjs +0 -6
  824. package/dist/lib/utils/format-assets.mjs.map +1 -1
  825. package/dist/lib/utils/format-render-builders.mjs +0 -6
  826. package/dist/lib/utils/format-render-builders.mjs.map +1 -1
  827. package/dist/lib/utils/format-renders.mjs +0 -6
  828. package/dist/lib/utils/format-renders.mjs.map +1 -1
  829. package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
  830. package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
  831. package/dist/lib/utils/glob.mjs +0 -6
  832. package/dist/lib/utils/glob.mjs.map +1 -1
  833. package/dist/lib/utils/global-async-local-storage.mjs +0 -6
  834. package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
  835. package/dist/lib/utils/idempotency.mjs +0 -6
  836. package/dist/lib/utils/idempotency.mjs.map +1 -1
  837. package/dist/lib/utils/index.mjs +0 -6
  838. package/dist/lib/utils/index.mjs.map +1 -1
  839. package/dist/lib/utils/jcs.mjs +0 -6
  840. package/dist/lib/utils/jcs.mjs.map +1 -1
  841. package/dist/lib/utils/json-depth.mjs +0 -6
  842. package/dist/lib/utils/json-depth.mjs.map +1 -1
  843. package/dist/lib/utils/logger.mjs +0 -6
  844. package/dist/lib/utils/logger.mjs.map +1 -1
  845. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
  846. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
  847. package/dist/lib/utils/media-buy-status.mjs +0 -6
  848. package/dist/lib/utils/media-buy-status.mjs.map +1 -1
  849. package/dist/lib/utils/pagination.mjs +0 -6
  850. package/dist/lib/utils/pagination.mjs.map +1 -1
  851. package/dist/lib/utils/preview-creative-builders.mjs +0 -6
  852. package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
  853. package/dist/lib/utils/preview-normalizer.mjs +0 -6
  854. package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
  855. package/dist/lib/utils/preview-utils.mjs +0 -6
  856. package/dist/lib/utils/preview-utils.mjs.map +1 -1
  857. package/dist/lib/utils/pricing-adapter.mjs +0 -6
  858. package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
  859. package/dist/lib/utils/probe-policy.mjs +0 -6
  860. package/dist/lib/utils/probe-policy.mjs.map +1 -1
  861. package/dist/lib/utils/protocol-detection.mjs +0 -6
  862. package/dist/lib/utils/protocol-detection.mjs.map +1 -1
  863. package/dist/lib/utils/redact-secrets.mjs +0 -6
  864. package/dist/lib/utils/redact-secrets.mjs.map +1 -1
  865. package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
  866. package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
  867. package/dist/lib/utils/render-builders.mjs +0 -6
  868. package/dist/lib/utils/render-builders.mjs.map +1 -1
  869. package/dist/lib/utils/request-normalizer.mjs +0 -6
  870. package/dist/lib/utils/request-normalizer.mjs.map +1 -1
  871. package/dist/lib/utils/response-schemas.mjs +0 -6
  872. package/dist/lib/utils/response-schemas.mjs.map +1 -1
  873. package/dist/lib/utils/response-unwrapper.mjs +0 -6
  874. package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
  875. package/dist/lib/utils/retry.mjs +0 -6
  876. package/dist/lib/utils/retry.mjs.map +1 -1
  877. package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
  878. package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
  879. package/dist/lib/utils/signal-id-builders.mjs +0 -6
  880. package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
  881. package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
  882. package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
  883. package/dist/lib/utils/task-state.mjs +0 -6
  884. package/dist/lib/utils/task-state.mjs.map +1 -1
  885. package/dist/lib/utils/tool-request-schemas.mjs +0 -6
  886. package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
  887. package/dist/lib/utils/typeGuards.mjs +0 -6
  888. package/dist/lib/utils/typeGuards.mjs.map +1 -1
  889. package/dist/lib/utils/union-errors.mjs +0 -6
  890. package/dist/lib/utils/union-errors.mjs.map +1 -1
  891. package/dist/lib/utils/validate-user-agent.mjs +0 -6
  892. package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
  893. package/dist/lib/v2/format-schema/fetch.mjs +0 -6
  894. package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
  895. package/dist/lib/v2/format-schema/index.mjs +0 -6
  896. package/dist/lib/v2/format-schema/index.mjs.map +1 -1
  897. package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
  898. package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
  899. package/dist/lib/v2/format-schema/resolver.mjs +7 -8
  900. package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
  901. package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
  902. package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
  903. package/dist/lib/v2/projection/augment-response.mjs +0 -6
  904. package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
  905. package/dist/lib/v2/projection/builders.mjs +0 -6
  906. package/dist/lib/v2/projection/builders.mjs.map +1 -1
  907. package/dist/lib/v2/projection/cache-versions.mjs +0 -6
  908. package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
  909. package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
  910. package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
  911. package/dist/lib/v2/projection/catalog.mjs +5 -6
  912. package/dist/lib/v2/projection/catalog.mjs.map +1 -1
  913. package/dist/lib/v2/projection/constants.mjs +0 -6
  914. package/dist/lib/v2/projection/constants.mjs.map +1 -1
  915. package/dist/lib/v2/projection/index.mjs +0 -6
  916. package/dist/lib/v2/projection/index.mjs.map +1 -1
  917. package/dist/lib/v2/projection/registry.mjs +5 -6
  918. package/dist/lib/v2/projection/registry.mjs.map +1 -1
  919. package/dist/lib/v2/projection/types.mjs +0 -6
  920. package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
  921. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  922. package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
  923. package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
  924. package/dist/lib/v2/projection/write-side.mjs +0 -6
  925. package/dist/lib/v2/projection/write-side.mjs.map +1 -1
  926. package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
  927. package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
  928. package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
  929. package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
  930. package/dist/lib/validation/client-hooks.mjs +0 -6
  931. package/dist/lib/validation/client-hooks.mjs.map +1 -1
  932. package/dist/lib/validation/hints.mjs +0 -6
  933. package/dist/lib/validation/hints.mjs.map +1 -1
  934. package/dist/lib/validation/index.mjs +0 -6
  935. package/dist/lib/validation/index.mjs.map +1 -1
  936. package/dist/lib/validation/schema-errors.mjs +0 -6
  937. package/dist/lib/validation/schema-errors.mjs.map +1 -1
  938. package/dist/lib/validation/schema-loader.mjs +5 -6
  939. package/dist/lib/validation/schema-loader.mjs.map +1 -1
  940. package/dist/lib/validation/schema-validator.mjs +0 -6
  941. package/dist/lib/validation/schema-validator.mjs.map +1 -1
  942. package/dist/lib/validation/sync-creatives.mjs +0 -6
  943. package/dist/lib/validation/sync-creatives.mjs.map +1 -1
  944. package/dist/lib/version.d.mts +3 -3
  945. package/dist/lib/version.d.ts +3 -3
  946. package/dist/lib/version.js +3 -3
  947. package/dist/lib/version.js.map +1 -1
  948. package/dist/lib/version.mjs +3 -9
  949. package/dist/lib/version.mjs.map +1 -1
  950. package/dist/lib/webhooks/index.mjs +0 -6
  951. package/dist/lib/webhooks/index.mjs.map +1 -1
  952. package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
  953. package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
  954. package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
  955. package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
  956. package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
  957. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
  958. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
  959. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/loader.ts"],"sourcesContent":["/**\n * Storyboard YAML parser.\n *\n * Storyboards are pulled from the compliance cache populated by\n * `npm run sync-schemas`. See `./compliance.ts` for capability-driven\n * resolution and bundle loading.\n */\n\nimport { readFileSync } from 'fs';\nimport { parse } from 'yaml';\nimport type { Storyboard } from './types';\nimport { MUTATING_TASKS } from '../../utils/idempotency';\n\n/**\n * Supported `branch_set.semantics` values. Extend when AdCP adds `all_of`,\n * `at_least_n`, etc. Exported so the runner can enforce the same whitelist\n * on programmatically-constructed storyboards that bypass the YAML parser.\n */\nexport const BRANCH_SET_SEMANTICS = ['any_of'] as const;\n\nconst IDENTIFIER_PATH_SEGMENT = String.raw`[A-Za-z_][A-Za-z0-9_-]*(?:\\[\\*\\])*`;\nconst IDENTIFIER_PATH_PATTERN = new RegExp(`^${IDENTIFIER_PATH_SEGMENT}(?:\\\\.${IDENTIFIER_PATH_SEGMENT})*$`);\n\n/** Parse a YAML string into a Storyboard. Throws if required fields are missing. */\nexport function parseStoryboard(yamlContent: string): Storyboard {\n const parsed = parse(yamlContent) as Storyboard;\n if (!parsed?.id || !parsed?.phases) {\n throw new Error('Invalid storyboard YAML: missing required fields (id, phases)');\n }\n for (const phase of parsed.phases) {\n // Specialism YAMLs may declare a phase with no `steps:` — the steps are\n // synthesized at runtime from fixtures (see request-signing/synthesize.ts).\n // Treat missing steps as an empty list so the parser stays phase-agnostic.\n if (!phase.steps) phase.steps = [];\n // YAML uses `name:` for context outputs but our runtime expects `key:`.\n for (const step of phase.steps) {\n if (!step.context_outputs) continue;\n for (const output of step.context_outputs) {\n const raw = output as unknown as Record<string, unknown>;\n if (raw.name && !raw.key) {\n output.key = raw.name as string;\n }\n }\n }\n }\n validateStoryboardShape(parsed);\n return parsed;\n}\n\n/** Load and parse a single storyboard file. Useful for ad-hoc testing of in-development YAMLs. */\nexport function loadStoryboardFile(filePath: string): Storyboard {\n return parseStoryboard(readFileSync(filePath, 'utf-8'));\n}\n\n/**\n * Enforce authoring-time invariants on a Storyboard. Called by\n * `parseStoryboard`, and should also be called by any runner entry point\n * that accepts a programmatically-built `Storyboard` object so the same\n * loud-fail-on-drift guarantee holds regardless of how the storyboard was\n * constructed. Mutates only legacy shorthand fields (resolves\n * `contributes: true` to `contributes_to`) and is idempotent on\n * already-validated inputs.\n */\nexport function validateStoryboardShape(storyboard: Storyboard): void {\n validateRequires(storyboard);\n validateRequiredAnyOfTools(storyboard);\n validatePhaseDependsOn(storyboard);\n for (const phase of storyboard.phases) {\n validateBranchSet(storyboard.id, phase);\n if (!phase.steps) continue;\n for (const step of phase.steps) {\n resolveContributesShorthand(storyboard.id, phase, step);\n validateFixtureForMutatingStep(storyboard.id, phase, step);\n validateOmitFlagCoherence(storyboard.id, phase, step);\n validateContextOutputs(storyboard.id, phase, step);\n validateUpstreamAttestationMode(storyboard.id, phase, step);\n validateUpstreamIdentifierPaths(storyboard.id, phase, step);\n validatePeerSubstitutesFor(storyboard.id, phase, step);\n }\n }\n}\n\nfunction validateUpstreamAttestationMode(\n storyboardId: string,\n phase: { id?: string },\n step: { id?: string; validations?: any[] }\n): void {\n const validations = step.validations ?? [];\n for (let validationIndex = 0; validationIndex < validations.length; validationIndex++) {\n const validation = validations[validationIndex];\n if (validation?.check !== 'upstream_traffic') continue;\n const mode = validation.preferred_attestation_mode;\n if (mode !== undefined && mode !== 'raw' && mode !== 'digest') {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].preferred_attestation_mode: must be \"raw\" or \"digest\"`\n );\n }\n }\n}\n\nfunction validateUpstreamIdentifierPaths(\n storyboardId: string,\n phase: { id?: string },\n step: { id?: string; validations?: any[] }\n): void {\n const validations = step.validations ?? [];\n for (let validationIndex = 0; validationIndex < validations.length; validationIndex++) {\n const validation = validations[validationIndex];\n if (validation?.check !== 'upstream_traffic' || validation.identifier_paths === undefined) continue;\n if (!Array.isArray(validation.identifier_paths)) {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${\n step.id ?? '?'\n }.validations[${validationIndex}].identifier_paths: must be an array of request-payload paths`\n );\n }\n for (let pathIndex = 0; pathIndex < validation.identifier_paths.length; pathIndex++) {\n const path = validation.identifier_paths[pathIndex];\n if (typeof path !== 'string' || path.length === 0) {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].identifier_paths[${pathIndex}]: must be a non-empty string`\n );\n }\n const pathErrorPrefix = `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].identifier_paths[${pathIndex}]`;\n let firstSegment: string;\n try {\n const validated = validateIdentifierPathSyntax(path);\n firstSegment = validated.firstSegment;\n } catch {\n throw new Error(\n `${pathErrorPrefix}: \"${path}\" is unsupported; identifier_paths resolve only against the request payload or sample_request using dotted paths with [*] array selectors`\n );\n }\n const root = firstSegment.toLowerCase();\n if (root === 'request' || root === 'response' || root === 'context') {\n throw new Error(\n `${pathErrorPrefix}: \"${path}\" is unsupported; identifier_paths resolve only against the request payload or sample_request`\n );\n }\n }\n }\n}\n\nfunction validateIdentifierPathSyntax(path: string): { normalized: string; firstSegment: string } {\n const trimmed = path.trim();\n const normalized = trimmed.startsWith('$.') ? trimmed.slice(2) : trimmed;\n if (!IDENTIFIER_PATH_PATTERN.test(normalized)) {\n throw new Error('unsupported identifier path syntax');\n }\n return { normalized, firstSegment: normalized.split(/[.[\\]]/, 1)[0] ?? '' };\n}\n\nfunction validateRequiredAnyOfTools(storyboard: Storyboard): void {\n if (storyboard.required_any_of_tools === undefined) return;\n if (!Array.isArray(storyboard.required_any_of_tools)) {\n throw new Error(`[${storyboard.id}] required_any_of_tools: must be an array of tool-family objects`);\n }\n if (storyboard.required_any_of_tools.length === 0) {\n throw new Error(`[${storyboard.id}] required_any_of_tools: [] is not allowed — omit the field to use no gate`);\n }\n for (let i = 0; i < storyboard.required_any_of_tools.length; i++) {\n const family = storyboard.required_any_of_tools[i] as unknown;\n if (family === null || typeof family !== 'object' || Array.isArray(family)) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}]: must be an object`);\n }\n const { tools, rationale } = family as { tools?: unknown; rationale?: unknown };\n if (!Array.isArray(tools) || tools.length < 2) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].tools: must list at least two tool names`);\n }\n for (const tool of tools) {\n if (typeof tool !== 'string' || tool.length === 0) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].tools: entries must be non-empty strings`);\n }\n }\n if (rationale !== undefined && typeof rationale !== 'string') {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].rationale: must be a string`);\n }\n }\n}\n\n/**\n * Authoring-time validation for `phase.depends_on` (#1161). Each entry\n * must reference a phase declared earlier in the storyboard. Forward\n * references and self-references fail loud at parse time so authoring\n * mistakes (typos, reorderings) don't degrade silently into \"phase\n * always runs\" / \"phase always cascades.\"\n *\n * Rules:\n * - Empty list (`depends_on: []`) is legal — it declares an\n * independent phase. No further validation needed.\n * - Each non-empty entry must be a non-empty string.\n * - Each entry must reference a phase that appears EARLIER in the\n * `storyboard.phases[]` array (forward references are rejected).\n * - A phase cannot depend on itself.\n */\nfunction validatePhaseDependsOn(storyboard: Storyboard): void {\n const phaseIdsSeen = new Set<string>();\n for (const phase of storyboard.phases) {\n if (phase.depends_on !== undefined) {\n if (!Array.isArray(phase.depends_on)) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on must be an array of phase ids`);\n }\n for (const dep of phase.depends_on) {\n if (typeof dep !== 'string' || dep.length === 0) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on entries must be non-empty strings`);\n }\n if (dep === phase.id) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on cannot reference itself`);\n }\n if (!phaseIdsSeen.has(dep)) {\n throw new Error(\n `[${storyboard.id}] phase '${phase.id}': depends_on '${dep}' is not a phase declared earlier in this storyboard (forward and unknown references are rejected)`\n );\n }\n }\n }\n phaseIdsSeen.add(phase.id);\n }\n}\n\n/**\n * Authoring-time validation for `Storyboard.requires` (#1626). The field is\n * an array of non-empty requirement names:\n *\n * - `requires: []` is rejected — an empty array reads as \"no\n * requirements,\" which is the same as omitting the field; failing\n * load forces the author to omit it explicitly.\n * - Each entry must be a non-empty string.\n *\n * Unknown string values are allowed for forward compatibility. Runners that\n * don't know how to satisfy a future requirement skip at runtime with\n * `skip_reason: 'requirement_unmet'` and the authored value in\n * `skip.requirement`.\n */\nfunction validateRequires(storyboard: Storyboard): void {\n if (storyboard.requires === undefined) return;\n if (!Array.isArray(storyboard.requires)) {\n throw new Error(\n `[${storyboard.id}] requires: must be an array of requirement names (got ${typeof storyboard.requires})`\n );\n }\n if (storyboard.requires.length === 0) {\n throw new Error(`[${storyboard.id}] requires: [] is not allowed — omit the field to use the default ([real_wire])`);\n }\n for (let i = 0; i < storyboard.requires.length; i++) {\n const name = storyboard.requires[i];\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error(`[${storyboard.id}] requires[${i}]: entries must be non-empty strings`);\n }\n }\n}\n\n/**\n * Issue #820: mutating tasks (per {@link MUTATING_TASKS}) must have a\n * `sample_request` authored. The fixture is authoritative at run time —\n * there's no sane default payload for a write, and silently fabricating\n * one was the bug factory that produced #780 / #792 / #793 / #802 / #805.\n *\n * Error messages point at the task name, the step id, the storyboard, and\n * suggest the concrete author action.\n *\n * Opt-out: steps with `expect_error: true` that deliberately exercise\n * missing-fixture / malformed-payload seller behavior skip this check —\n * the author is signaling the payload is the test condition.\n *\n * Synthesized phases (`request-signing/synthesize.ts`, controller seeding)\n * start with `phase.steps = []` in YAML and the loader doesn't see the\n * runtime-generated steps, so those paths are not affected.\n */\nfunction validateFixtureForMutatingStep(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (!MUTATING_TASKS.has(step.task)) return;\n if (step.sample_request !== undefined) return;\n if (step.expect_error === true) return;\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}' (task=${step.task}): ` +\n `mutating tasks require a sample_request fixture — the runner no longer fabricates ` +\n `write payloads. Author sample_request in the step or, for intentionally malformed ` +\n `payloads, set expect_error: true.`\n );\n}\n\n/**\n * `omit_account: true` must be paired with `expect_error: true`.\n *\n * An accountless `create_media_buy` will always be rejected by a spec-compliant\n * seller; a step that sets `omit_account` without `expect_error` will be graded\n * as a failure (not a controlled negative test), producing a misleading\n * compliance result. Fail loud at parse time so the author sees the problem\n * during storyboard load, not at run time.\n */\nfunction validateOmitFlagCoherence(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (step.omit_account && step.expect_error !== true) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ` +\n `omit_account: true requires expect_error: true — an accountless ` +\n `create_media_buy will always be rejected by a spec-compliant seller.`\n );\n }\n}\n\n/**\n * Each `context_outputs` entry must declare exactly one source: either\n * `path` (extract from response) or `generate` (mint at run time). An entry\n * with neither is a silent no-op; one with both would silently pick `generate`\n * and ignore `path`. Both are authoring foot-guns that should fail loud.\n */\nfunction validateContextOutputs(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (!step.context_outputs?.length) return;\n for (const output of step.context_outputs) {\n const hasPath = output.path !== undefined;\n const hasGenerate = output.generate !== undefined;\n if (!hasPath && !hasGenerate) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' must set exactly one of 'path' or 'generate'.`\n );\n }\n if (hasPath && hasGenerate) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' sets both 'path' and 'generate' — they are mutually exclusive.`\n );\n }\n // Validate generator name. The runtime resolver also checks but the loader\n // catches typos at storyboard-load time so authors see the failure on\n // build, not on the first run.\n if (hasGenerate && output.generate !== 'uuid_v4' && output.generate !== 'opaque_id') {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' has unknown generate value '${output.generate}'. ` +\n `Supported: 'uuid_v4', 'opaque_id'.`\n );\n }\n }\n}\n\n/**\n * Authoring-time validation for `provides_state_for` (the AdCP 3.0.3 spec\n * field — adcp#3734) and the legacy `peer_substitutes_for` synonym. The\n * runner treats the field as same-phase-only and substitution-only-when-\n * stateful; surface those constraints at parse time so storyboard authors\n * see typos and cross-phase references on build, not as a silent no-rescue\n * at run time.\n *\n * Both field names parse to the same canonical normalized form on the step\n * object (the spec name `provides_state_for` is preferred when both are\n * declared). The deprecation alias is documented in `types.ts`.\n *\n * Rules:\n * - Each target must reference a step that exists in the same phase.\n * - A step cannot substitute for itself.\n * - The substitute step itself must be `stateful: true` — non-stateful\n * passes don't establish state per the cascade contract.\n * - The target step must be `stateful: true` — non-stateful targets\n * don't participate in cascade gating, so a substitution declaration\n * would be a no-op.\n * - When both fields are declared on the same step, they must match\n * element-for-element (the deprecation contract is \"synonym for\", not\n * \"additive with\").\n */\nfunction validatePeerSubstitutesFor(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n const newField = step.provides_state_for;\n const legacyField = step.peer_substitutes_for;\n if (newField === undefined && legacyField === undefined) return;\n\n if (newField !== undefined && legacyField !== undefined) {\n // Order-sensitive equality: `[A, B]` vs `[B, A]` would throw despite being\n // semantically equivalent. Authors mid-migration should write the same list\n // in both fields; the deprecation alias is a literal synonym, not a\n // same-set restatement.\n const a = JSON.stringify(Array.isArray(newField) ? newField : [newField]);\n const b = JSON.stringify(Array.isArray(legacyField) ? legacyField : [legacyField]);\n if (a !== b) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': both provides_state_for and ` +\n `peer_substitutes_for declared with different values — pick one (provides_state_for is the ` +\n `spec field; peer_substitutes_for is a deprecated synonym)`\n );\n }\n }\n\n // Normalize onto provides_state_for so the runner can read a single field.\n // peer_substitutes_for stays for back-compat with any consumer code that\n // already reads it.\n if (newField === undefined && legacyField !== undefined) {\n step.provides_state_for = legacyField;\n } else if (newField !== undefined && legacyField === undefined) {\n step.peer_substitutes_for = newField;\n }\n\n const sourceFieldName = newField !== undefined ? 'provides_state_for' : 'peer_substitutes_for';\n const declared = step.provides_state_for!;\n const targets = Array.isArray(declared) ? declared : [declared];\n if (!step.stateful) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} is only legal on stateful steps`\n );\n }\n const phaseStepIds = new Map(phase.steps.map(s => [s.id, s]));\n for (const target of targets) {\n if (typeof target !== 'string' || target.length === 0) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} entries must be non-empty strings`\n );\n }\n if (target === step.id) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} cannot reference itself`\n );\n }\n const targetStep = phaseStepIds.get(target);\n if (!targetStep) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} target '${target}' is not a step in this phase (same-phase only)`\n );\n }\n if (!targetStep.stateful) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} target '${target}' must be stateful`\n );\n }\n }\n}\n\nfunction validateBranchSet(storyboardId: string, phase: Storyboard['phases'][number]): void {\n if (phase.branch_set === undefined) return;\n const bs = phase.branch_set as unknown;\n if (!bs || typeof bs !== 'object') {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set must be an object with { id, semantics }`);\n }\n const { id, semantics } = bs as Record<string, unknown>;\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set.id must be a non-empty string`);\n }\n if (typeof semantics !== 'string' || semantics.length === 0) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set.semantics must be a non-empty string`);\n }\n // Only `any_of` is defined in AdCP today (adcp#2646 lint rule 2 —\n // `at_least_n` and `all_of` are reserved but not defined). Reject unknown\n // values at parse rather than silently skipping grading at runtime, so\n // spec-drift typos fail loud instead of degrading to raw `failed` peers.\n if (!(BRANCH_SET_SEMANTICS as readonly string[]).includes(semantics)) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}': branch_set.semantics='${semantics}' is not supported (valid: ${BRANCH_SET_SEMANTICS.join(', ')})`\n );\n }\n // Schema constraint: every phase in a branch set MUST be optional. A\n // non-optional branch-set phase would fail the storyboard on any step\n // failure regardless of peer contribution, defeating the any_of gate.\n if (phase.optional !== true) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': phases declaring branch_set must set 'optional: true'`);\n }\n}\n\n/**\n * Resolve the `contributes: true` boolean shorthand introduced alongside the\n * first-class `branch_set:` phase field (adcp-client#693, adcp#2646).\n *\n * Rules:\n * - `contributes: true` is legal only inside a phase that declares `branch_set:`.\n * - A step MUST NOT set both `contributes` and `contributes_to` (ambiguous).\n * - A string `contributes_to` inside a branch_set phase MUST equal `branch_set.id`\n * (otherwise the aggregation target drifts — same invariant the spec lint enforces).\n *\n * After resolution, `step.contributes_to` carries the flag name and `step.contributes`\n * is cleared, so the runner reads a single field regardless of authoring form.\n */\nfunction resolveContributesShorthand(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n const hasBoolean = step.contributes !== undefined;\n const hasString = step.contributes_to !== undefined;\n\n if (hasBoolean && hasString) {\n throw new Error(`[${storyboardId}] step '${step.id}' declares both 'contributes' and 'contributes_to' — pick one`);\n }\n\n if (hasBoolean) {\n if (step.contributes === true) {\n if (!phase.branch_set) {\n throw new Error(\n `[${storyboardId}] step '${step.id}': 'contributes: true' is only legal inside a phase that declares branch_set`\n );\n }\n step.contributes_to = phase.branch_set.id;\n }\n delete step.contributes;\n return;\n }\n\n if (hasString && phase.branch_set && step.contributes_to !== phase.branch_set.id) {\n throw new Error(\n `[${storyboardId}] step '${step.id}': contributes_to='${step.contributes_to}' must equal enclosing phase's branch_set.id='${phase.branch_set.id}'`\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/loader.ts"],"sourcesContent":["/**\n * Storyboard YAML parser.\n *\n * Storyboards are pulled from the compliance cache populated by\n * `npm run sync-schemas`. See `./compliance.ts` for capability-driven\n * resolution and bundle loading.\n */\n\nimport { readFileSync } from 'fs';\nimport { parse } from 'yaml';\nimport type { Storyboard } from './types';\nimport { MUTATING_TASKS } from '../../utils/idempotency';\n\n/**\n * Supported `branch_set.semantics` values. Extend when AdCP adds `all_of`,\n * `at_least_n`, etc. Exported so the runner can enforce the same whitelist\n * on programmatically-constructed storyboards that bypass the YAML parser.\n */\nexport const BRANCH_SET_SEMANTICS = ['any_of'] as const;\n\nconst IDENTIFIER_PATH_SEGMENT = String.raw`[A-Za-z_][A-Za-z0-9_-]*(?:\\[\\*\\])*`;\nconst IDENTIFIER_PATH_PATTERN = new RegExp(`^${IDENTIFIER_PATH_SEGMENT}(?:\\\\.${IDENTIFIER_PATH_SEGMENT})*$`);\n\n/** Parse a YAML string into a Storyboard. Throws if required fields are missing. */\nexport function parseStoryboard(yamlContent: string): Storyboard {\n const parsed = parse(yamlContent) as Storyboard;\n if (!parsed?.id || !parsed?.phases) {\n throw new Error('Invalid storyboard YAML: missing required fields (id, phases)');\n }\n for (const phase of parsed.phases) {\n // Specialism YAMLs may declare a phase with no `steps:` — the steps are\n // synthesized at runtime from fixtures (see request-signing/synthesize.ts).\n // Treat missing steps as an empty list so the parser stays phase-agnostic.\n if (!phase.steps) phase.steps = [];\n // YAML uses `name:` for context outputs but our runtime expects `key:`.\n for (const step of phase.steps) {\n if (!step.context_outputs) continue;\n for (const output of step.context_outputs) {\n const raw = output as unknown as Record<string, unknown>;\n if (raw.name && !raw.key) {\n output.key = raw.name as string;\n }\n }\n }\n }\n validateStoryboardShape(parsed);\n return parsed;\n}\n\n/** Load and parse a single storyboard file. Useful for ad-hoc testing of in-development YAMLs. */\nexport function loadStoryboardFile(filePath: string): Storyboard {\n return parseStoryboard(readFileSync(filePath, 'utf-8'));\n}\n\n/**\n * Enforce authoring-time invariants on a Storyboard. Called by\n * `parseStoryboard`, and should also be called by any runner entry point\n * that accepts a programmatically-built `Storyboard` object so the same\n * loud-fail-on-drift guarantee holds regardless of how the storyboard was\n * constructed. Mutates only legacy shorthand fields (resolves\n * `contributes: true` to `contributes_to`) and is idempotent on\n * already-validated inputs.\n */\nexport function validateStoryboardShape(storyboard: Storyboard): void {\n validateRequires(storyboard);\n validateRequiredAnyOfTools(storyboard);\n validatePhaseDependsOn(storyboard);\n for (const phase of storyboard.phases) {\n validateBranchSet(storyboard.id, phase);\n if (!phase.steps) continue;\n for (const step of phase.steps) {\n resolveContributesShorthand(storyboard.id, phase, step);\n validateFixtureForMutatingStep(storyboard.id, phase, step);\n validateOmitFlagCoherence(storyboard.id, phase, step);\n validateContextOutputs(storyboard.id, phase, step);\n validateUpstreamAttestationMode(storyboard.id, phase, step);\n validateUpstreamIdentifierPaths(storyboard.id, phase, step);\n validatePeerSubstitutesFor(storyboard.id, phase, step);\n }\n }\n}\n\nfunction validateUpstreamAttestationMode(\n storyboardId: string,\n phase: { id?: string },\n step: { id?: string; validations?: any[] }\n): void {\n const validations = step.validations ?? [];\n for (let validationIndex = 0; validationIndex < validations.length; validationIndex++) {\n const validation = validations[validationIndex];\n if (validation?.check !== 'upstream_traffic') continue;\n const mode = validation.preferred_attestation_mode;\n if (mode !== undefined && mode !== 'raw' && mode !== 'digest') {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].preferred_attestation_mode: must be \"raw\" or \"digest\"`\n );\n }\n }\n}\n\nfunction validateUpstreamIdentifierPaths(\n storyboardId: string,\n phase: { id?: string },\n step: { id?: string; validations?: any[] }\n): void {\n const validations = step.validations ?? [];\n for (let validationIndex = 0; validationIndex < validations.length; validationIndex++) {\n const validation = validations[validationIndex];\n if (validation?.check !== 'upstream_traffic' || validation.identifier_paths === undefined) continue;\n if (!Array.isArray(validation.identifier_paths)) {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${\n step.id ?? '?'\n }.validations[${validationIndex}].identifier_paths: must be an array of request-payload paths`\n );\n }\n for (let pathIndex = 0; pathIndex < validation.identifier_paths.length; pathIndex++) {\n const path = validation.identifier_paths[pathIndex];\n if (typeof path !== 'string' || path.length === 0) {\n throw new Error(\n `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].identifier_paths[${pathIndex}]: must be a non-empty string`\n );\n }\n const pathErrorPrefix = `[${storyboardId}] ${phase.id ?? '?'}.${step.id ?? '?'}.validations[${validationIndex}].identifier_paths[${pathIndex}]`;\n let firstSegment: string;\n try {\n const validated = validateIdentifierPathSyntax(path);\n firstSegment = validated.firstSegment;\n } catch {\n throw new Error(\n `${pathErrorPrefix}: \"${path}\" is unsupported; identifier_paths resolve only against the request payload or sample_request using dotted paths with [*] array selectors`\n );\n }\n const root = firstSegment.toLowerCase();\n if (root === 'request' || root === 'response' || root === 'context') {\n throw new Error(\n `${pathErrorPrefix}: \"${path}\" is unsupported; identifier_paths resolve only against the request payload or sample_request`\n );\n }\n }\n }\n}\n\nfunction validateIdentifierPathSyntax(path: string): { normalized: string; firstSegment: string } {\n const trimmed = path.trim();\n const normalized = trimmed.startsWith('$.') ? trimmed.slice(2) : trimmed;\n if (!IDENTIFIER_PATH_PATTERN.test(normalized)) {\n throw new Error('unsupported identifier path syntax');\n }\n return { normalized, firstSegment: normalized.split(/[.[\\]]/, 1)[0] ?? '' };\n}\n\nfunction validateRequiredAnyOfTools(storyboard: Storyboard): void {\n if (storyboard.required_any_of_tools === undefined) return;\n if (!Array.isArray(storyboard.required_any_of_tools)) {\n throw new Error(`[${storyboard.id}] required_any_of_tools: must be an array of tool-family objects`);\n }\n if (storyboard.required_any_of_tools.length === 0) {\n throw new Error(`[${storyboard.id}] required_any_of_tools: [] is not allowed — omit the field to use no gate`);\n }\n for (let i = 0; i < storyboard.required_any_of_tools.length; i++) {\n const family = storyboard.required_any_of_tools[i] as unknown;\n if (family === null || typeof family !== 'object' || Array.isArray(family)) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}]: must be an object`);\n }\n const { tools, rationale } = family as { tools?: unknown; rationale?: unknown };\n if (!Array.isArray(tools) || tools.length < 2) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].tools: must list at least two tool names`);\n }\n for (const tool of tools) {\n if (typeof tool !== 'string' || tool.length === 0) {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].tools: entries must be non-empty strings`);\n }\n }\n if (rationale !== undefined && typeof rationale !== 'string') {\n throw new Error(`[${storyboard.id}] required_any_of_tools[${i}].rationale: must be a string`);\n }\n }\n}\n\n/**\n * Authoring-time validation for `phase.depends_on` (#1161). Each entry\n * must reference a phase declared earlier in the storyboard. Forward\n * references and self-references fail loud at parse time so authoring\n * mistakes (typos, reorderings) don't degrade silently into \"phase\n * always runs\" / \"phase always cascades.\"\n *\n * Rules:\n * - Empty list (`depends_on: []`) is legal — it declares an\n * independent phase. No further validation needed.\n * - Each non-empty entry must be a non-empty string.\n * - Each entry must reference a phase that appears EARLIER in the\n * `storyboard.phases[]` array (forward references are rejected).\n * - A phase cannot depend on itself.\n */\nfunction validatePhaseDependsOn(storyboard: Storyboard): void {\n const phaseIdsSeen = new Set<string>();\n for (const phase of storyboard.phases) {\n if (phase.depends_on !== undefined) {\n if (!Array.isArray(phase.depends_on)) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on must be an array of phase ids`);\n }\n for (const dep of phase.depends_on) {\n if (typeof dep !== 'string' || dep.length === 0) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on entries must be non-empty strings`);\n }\n if (dep === phase.id) {\n throw new Error(`[${storyboard.id}] phase '${phase.id}': depends_on cannot reference itself`);\n }\n if (!phaseIdsSeen.has(dep)) {\n throw new Error(\n `[${storyboard.id}] phase '${phase.id}': depends_on '${dep}' is not a phase declared earlier in this storyboard (forward and unknown references are rejected)`\n );\n }\n }\n }\n phaseIdsSeen.add(phase.id);\n }\n}\n\n/**\n * Authoring-time validation for `Storyboard.requires` (#1626). The field is\n * an array of non-empty requirement names:\n *\n * - `requires: []` is rejected — an empty array reads as \"no\n * requirements,\" which is the same as omitting the field; failing\n * load forces the author to omit it explicitly.\n * - Each entry must be a non-empty string.\n *\n * Unknown string values are allowed for forward compatibility. Runners that\n * don't know how to satisfy a future requirement skip at runtime with\n * `skip_reason: 'requirement_unmet'` and the authored value in\n * `skip.requirement`.\n */\nfunction validateRequires(storyboard: Storyboard): void {\n if (storyboard.requires === undefined) return;\n if (!Array.isArray(storyboard.requires)) {\n throw new Error(\n `[${storyboard.id}] requires: must be an array of requirement names (got ${typeof storyboard.requires})`\n );\n }\n if (storyboard.requires.length === 0) {\n throw new Error(`[${storyboard.id}] requires: [] is not allowed — omit the field to use the default ([real_wire])`);\n }\n for (let i = 0; i < storyboard.requires.length; i++) {\n const name = storyboard.requires[i];\n if (typeof name !== 'string' || name.length === 0) {\n throw new Error(`[${storyboard.id}] requires[${i}]: entries must be non-empty strings`);\n }\n }\n}\n\n/**\n * Issue #820: mutating tasks (per {@link MUTATING_TASKS}) must have a\n * `sample_request` authored. The fixture is authoritative at run time —\n * there's no sane default payload for a write, and silently fabricating\n * one was the bug factory that produced #780 / #792 / #793 / #802 / #805.\n *\n * Error messages point at the task name, the step id, the storyboard, and\n * suggest the concrete author action.\n *\n * Opt-out: steps with `expect_error: true` that deliberately exercise\n * missing-fixture / malformed-payload seller behavior skip this check —\n * the author is signaling the payload is the test condition.\n *\n * Synthesized phases (`request-signing/synthesize.ts`, controller seeding)\n * start with `phase.steps = []` in YAML and the loader doesn't see the\n * runtime-generated steps, so those paths are not affected.\n */\nfunction validateFixtureForMutatingStep(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (!MUTATING_TASKS.has(step.task)) return;\n if (step.sample_request !== undefined) return;\n if (step.expect_error === true) return;\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}' (task=${step.task}): ` +\n `mutating tasks require a sample_request fixture — the runner no longer fabricates ` +\n `write payloads. Author sample_request in the step or, for intentionally malformed ` +\n `payloads, set expect_error: true.`\n );\n}\n\n/**\n * `omit_account: true` must be paired with `expect_error: true`.\n *\n * An accountless `create_media_buy` will always be rejected by a spec-compliant\n * seller; a step that sets `omit_account` without `expect_error` will be graded\n * as a failure (not a controlled negative test), producing a misleading\n * compliance result. Fail loud at parse time so the author sees the problem\n * during storyboard load, not at run time.\n */\nfunction validateOmitFlagCoherence(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (step.omit_account && step.expect_error !== true) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ` +\n `omit_account: true requires expect_error: true — an accountless ` +\n `create_media_buy will always be rejected by a spec-compliant seller.`\n );\n }\n}\n\n/**\n * Each `context_outputs` entry must declare exactly one source: either\n * `path` (extract from response) or `generate` (mint at run time). An entry\n * with neither is a silent no-op; one with both would silently pick `generate`\n * and ignore `path`. Both are authoring foot-guns that should fail loud.\n */\nfunction validateContextOutputs(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n if (!step.context_outputs?.length) return;\n for (const output of step.context_outputs) {\n const hasPath = output.path !== undefined;\n const hasGenerate = output.generate !== undefined;\n if (!hasPath && !hasGenerate) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' must set exactly one of 'path' or 'generate'.`\n );\n }\n if (hasPath && hasGenerate) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' sets both 'path' and 'generate' — they are mutually exclusive.`\n );\n }\n // Validate generator name. The runtime resolver also checks but the loader\n // catches typos at storyboard-load time so authors see the failure on\n // build, not on the first run.\n if (hasGenerate && output.generate !== 'uuid_v4' && output.generate !== 'opaque_id') {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': context_outputs entry ` +\n `'${output.key}' has unknown generate value '${output.generate}'. ` +\n `Supported: 'uuid_v4', 'opaque_id'.`\n );\n }\n }\n}\n\n/**\n * Authoring-time validation for `provides_state_for` (the AdCP 3.0.3 spec\n * field — adcp#3734) and the legacy `peer_substitutes_for` synonym. The\n * runner treats the field as same-phase-only and substitution-only-when-\n * stateful; surface those constraints at parse time so storyboard authors\n * see typos and cross-phase references on build, not as a silent no-rescue\n * at run time.\n *\n * Both field names parse to the same canonical normalized form on the step\n * object (the spec name `provides_state_for` is preferred when both are\n * declared). The deprecation alias is documented in `types.ts`.\n *\n * Rules:\n * - Each target must reference a step that exists in the same phase.\n * - A step cannot substitute for itself.\n * - The substitute step itself must be `stateful: true` — non-stateful\n * passes don't establish state per the cascade contract.\n * - The target step must be `stateful: true` — non-stateful targets\n * don't participate in cascade gating, so a substitution declaration\n * would be a no-op.\n * - When both fields are declared on the same step, they must match\n * element-for-element (the deprecation contract is \"synonym for\", not\n * \"additive with\").\n */\nfunction validatePeerSubstitutesFor(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n const newField = step.provides_state_for;\n const legacyField = step.peer_substitutes_for;\n if (newField === undefined && legacyField === undefined) return;\n\n if (newField !== undefined && legacyField !== undefined) {\n // Order-sensitive equality: `[A, B]` vs `[B, A]` would throw despite being\n // semantically equivalent. Authors mid-migration should write the same list\n // in both fields; the deprecation alias is a literal synonym, not a\n // same-set restatement.\n const a = JSON.stringify(Array.isArray(newField) ? newField : [newField]);\n const b = JSON.stringify(Array.isArray(legacyField) ? legacyField : [legacyField]);\n if (a !== b) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': both provides_state_for and ` +\n `peer_substitutes_for declared with different values — pick one (provides_state_for is the ` +\n `spec field; peer_substitutes_for is a deprecated synonym)`\n );\n }\n }\n\n // Normalize onto provides_state_for so the runner can read a single field.\n // peer_substitutes_for stays for back-compat with any consumer code that\n // already reads it.\n if (newField === undefined && legacyField !== undefined) {\n step.provides_state_for = legacyField;\n } else if (newField !== undefined && legacyField === undefined) {\n step.peer_substitutes_for = newField;\n }\n\n const sourceFieldName = newField !== undefined ? 'provides_state_for' : 'peer_substitutes_for';\n const declared = step.provides_state_for!;\n const targets = Array.isArray(declared) ? declared : [declared];\n if (!step.stateful) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} is only legal on stateful steps`\n );\n }\n const phaseStepIds = new Map(phase.steps.map(s => [s.id, s]));\n for (const target of targets) {\n if (typeof target !== 'string' || target.length === 0) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} entries must be non-empty strings`\n );\n }\n if (target === step.id) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} cannot reference itself`\n );\n }\n const targetStep = phaseStepIds.get(target);\n if (!targetStep) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} target '${target}' is not a step in this phase (same-phase only)`\n );\n }\n if (!targetStep.stateful) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}' step '${step.id}': ${sourceFieldName} target '${target}' must be stateful`\n );\n }\n }\n}\n\nfunction validateBranchSet(storyboardId: string, phase: Storyboard['phases'][number]): void {\n if (phase.branch_set === undefined) return;\n const bs = phase.branch_set as unknown;\n if (!bs || typeof bs !== 'object') {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set must be an object with { id, semantics }`);\n }\n const { id, semantics } = bs as Record<string, unknown>;\n if (typeof id !== 'string' || id.length === 0) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set.id must be a non-empty string`);\n }\n if (typeof semantics !== 'string' || semantics.length === 0) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': branch_set.semantics must be a non-empty string`);\n }\n // Only `any_of` is defined in AdCP today (adcp#2646 lint rule 2 —\n // `at_least_n` and `all_of` are reserved but not defined). Reject unknown\n // values at parse rather than silently skipping grading at runtime, so\n // spec-drift typos fail loud instead of degrading to raw `failed` peers.\n if (!(BRANCH_SET_SEMANTICS as readonly string[]).includes(semantics)) {\n throw new Error(\n `[${storyboardId}] phase '${phase.id}': branch_set.semantics='${semantics}' is not supported (valid: ${BRANCH_SET_SEMANTICS.join(', ')})`\n );\n }\n // Schema constraint: every phase in a branch set MUST be optional. A\n // non-optional branch-set phase would fail the storyboard on any step\n // failure regardless of peer contribution, defeating the any_of gate.\n if (phase.optional !== true) {\n throw new Error(`[${storyboardId}] phase '${phase.id}': phases declaring branch_set must set 'optional: true'`);\n }\n}\n\n/**\n * Resolve the `contributes: true` boolean shorthand introduced alongside the\n * first-class `branch_set:` phase field (adcp-client#693, adcp#2646).\n *\n * Rules:\n * - `contributes: true` is legal only inside a phase that declares `branch_set:`.\n * - A step MUST NOT set both `contributes` and `contributes_to` (ambiguous).\n * - A string `contributes_to` inside a branch_set phase MUST equal `branch_set.id`\n * (otherwise the aggregation target drifts — same invariant the spec lint enforces).\n *\n * After resolution, `step.contributes_to` carries the flag name and `step.contributes`\n * is cleared, so the runner reads a single field regardless of authoring form.\n */\nfunction resolveContributesShorthand(\n storyboardId: string,\n phase: Storyboard['phases'][number],\n step: Storyboard['phases'][number]['steps'][number]\n): void {\n const hasBoolean = step.contributes !== undefined;\n const hasString = step.contributes_to !== undefined;\n\n if (hasBoolean && hasString) {\n throw new Error(`[${storyboardId}] step '${step.id}' declares both 'contributes' and 'contributes_to' — pick one`);\n }\n\n if (hasBoolean) {\n if (step.contributes === true) {\n if (!phase.branch_set) {\n throw new Error(\n `[${storyboardId}] step '${step.id}': 'contributes: true' is only legal inside a phase that declares branch_set`\n );\n }\n step.contributes_to = phase.branch_set.id;\n }\n delete step.contributes;\n return;\n }\n\n if (hasString && phase.branch_set && step.contributes_to !== phase.branch_set.id) {\n throw new Error(\n `[${storyboardId}] step '${step.id}': contributes_to='${step.contributes_to}' must equal enclosing phase's branch_set.id='${phase.branch_set.id}'`\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { executeStoryboardTask } from "./task-map.mjs";
8
2
  const PARALLEL_DISPATCH_COUNT_MIN = 2;
9
3
  const PARALLEL_DISPATCH_COUNT_MAX = 10;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/parallel-dispatch.ts"],"sourcesContent":["/**\n * Parallel-dispatch runner support for the `parallel_dispatch_runner`\n * test-kit contract. Drives the concurrent-retry phase of the idempotency\n * storyboard (rule 9 / first-insert-wins): two `create_media_buy` calls\n * with the same `idempotency_key` race the seller's INSERT and must\n * resolve to one resource. Spec:\n * `test-kits/parallel-dispatch-runner.yaml`.\n *\n * Modes:\n * - `process_local` (default): fan out N requests via `Promise.all`. Event-\n * loop concurrent, sufficient to exercise the seller's INSERT race per\n * the contract YAML's `not_required_to_synthesize_packet_schedule`.\n * - `distributed`: barrier-synced workers across processes — out of scope\n * for this module. Callers grade the step `not_applicable` when the\n * storyboard requests `distributed` and the runner cannot satisfy it.\n *\n * In-flight resolution: a dispatch that returns `IDEMPOTENCY_IN_FLIGHT` or\n * (legacy) `SERVICE_UNAVAILABLE` with a `retry_after` hint retries with the\n * SAME idempotency_key after the hint elapses. The runner caps retries so\n * a stuck seller can't pin a barrier indefinitely; the outer barrier\n * timeout is the second line of defense.\n */\n\nimport type { TaskResult } from '../types';\nimport { executeStoryboardTask } from './task-map';\nimport type { CrossResponseDispatch, CrossResponseSet } from './validations';\nimport type { ParallelDispatchSpec } from './types';\n\n/**\n * Minimum and maximum parallel dispatches per the contract YAML. The\n * `count_max: 10` is a soft ceiling — every runner mode MUST support up to\n * 10 parallel dispatches per the spec's\n * `every_runner_mode_supports_up_to_10` note.\n */\nexport const PARALLEL_DISPATCH_COUNT_MIN = 2;\nexport const PARALLEL_DISPATCH_COUNT_MAX = 10;\n/** Default barrier timeout when the storyboard omits `barrier_timeout_ms`. */\nexport const PARALLEL_DISPATCH_DEFAULT_BARRIER_MS = 5000;\n/**\n * Per-dispatch retry budget for the in-flight branch. The outer barrier\n * (default 5s, configurable) is the real cap — the dispatcher honors the\n * seller's `retry_after` hint, then clamps every sleep to the remaining\n * barrier so the budget mostly matters when a misbehaving seller floods\n * tiny hints. 5 is enough headroom for that case without letting a stuck\n * seller pin the runner past the barrier.\n */\nconst IN_FLIGHT_RETRY_BUDGET = 5;\n/** Floor for the in-flight retry sleep so a misbehaving seller can't busy-loop the runner. */\nconst IN_FLIGHT_MIN_SLEEP_MS = 50;\n\n/**\n * The contract id storyboards declare on `requires_contract` to opt into\n * parallel-dispatch grading. Runners without the contract in scope grade\n * the step `not_applicable`.\n */\nexport const PARALLEL_DISPATCH_CONTRACT = 'parallel_dispatch_runner';\n\n/**\n * In-flight resolution: error codes the runner treats as \"retry with the\n * same idempotency_key after retry_after.\" `IDEMPOTENCY_IN_FLIGHT` is the\n * AdCP 3.1 wire code; `SERVICE_UNAVAILABLE` is accepted as a legacy\n * fallback so the runner grades SDKs that haven't migrated yet against\n * the same contract.\n */\nconst IN_FLIGHT_ERROR_CODES = new Set(['IDEMPOTENCY_IN_FLIGHT', 'SERVICE_UNAVAILABLE']);\n\n/** Parsed `(code, retry_after_seconds)` from a TaskResult, when present. */\ninterface AdcpErrorInfo {\n code: string;\n retry_after_seconds?: number;\n}\n\nfunction extractAdcpError(tr: TaskResult): AdcpErrorInfo | undefined {\n const data = tr.data as Record<string, unknown> | undefined;\n const err = data?.adcp_error as Record<string, unknown> | undefined;\n if (!err || typeof err.code !== 'string') return undefined;\n const retry = err.retry_after;\n return {\n code: err.code,\n ...(typeof retry === 'number' && Number.isFinite(retry) ? { retry_after_seconds: retry } : {}),\n };\n}\n\n/**\n * Configuration accepted by {@link dispatchOnceWithInflightRetry}.\n */\nexport interface DispatchOnceOptions {\n /**\n * Cooperative deadline (epoch ms) past which retries are abandoned. Set by\n * the caller to align with the outer barrier — a dispatch that's still\n * IDEMPOTENCY_IN_FLIGHT at the deadline returns its most recent\n * TaskResult so the barrier-timeout grading path can record the seller's\n * last-seen error code.\n */\n deadlineMs: number;\n}\n\n/**\n * Validate a {@link ParallelDispatchSpec} or return a structured authoring\n * error. Returns `null` when the spec is well-formed. The runner surfaces\n * the error as a `parallel_dispatch_misconfigured` step result rather than\n * silently clamping — silent clamping would let a storyboard advertise a\n * `count_max: 50` test that the runner only partially executed.\n */\nexport function validateParallelDispatchSpec(spec: ParallelDispatchSpec): string | null {\n if (!Number.isInteger(spec.count)) {\n return `parallel_dispatch.count must be an integer; received ${spec.count}`;\n }\n if (spec.count < PARALLEL_DISPATCH_COUNT_MIN || spec.count > PARALLEL_DISPATCH_COUNT_MAX) {\n return (\n `parallel_dispatch.count must be in [${PARALLEL_DISPATCH_COUNT_MIN}, ${PARALLEL_DISPATCH_COUNT_MAX}] ` +\n `per test-kits/parallel-dispatch-runner.yaml; received ${spec.count}`\n );\n }\n if (spec.barrier_timeout_ms !== undefined) {\n if (!Number.isFinite(spec.barrier_timeout_ms) || spec.barrier_timeout_ms <= 0) {\n return `parallel_dispatch.barrier_timeout_ms must be a positive finite number; received ${spec.barrier_timeout_ms}`;\n }\n }\n if (spec.mode !== undefined && spec.mode !== 'process_local' && spec.mode !== 'distributed') {\n return `parallel_dispatch.mode must be 'process_local' or 'distributed'; received '${spec.mode}'`;\n }\n return null;\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, Math.max(0, ms)));\n\n/**\n * Run one dispatch and retry on the in-flight branch. Returns the dispatch's\n * terminal `TaskResult` (success, terminal error, or last-seen in-flight\n * after the deadline). Catches thrown errors and shapes them into a\n * synthetic error TaskResult so callers see a uniform `TaskResult`-shaped\n * outcome.\n */\nexport async function dispatchOnceWithInflightRetry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n request: Record<string, unknown>,\n opts: DispatchOnceOptions\n): Promise<{ taskResult: TaskResult; error?: string }> {\n let lastTaskResult: TaskResult | undefined;\n let lastError: string | undefined;\n for (let attempt = 0; attempt < IN_FLIGHT_RETRY_BUDGET; attempt++) {\n try {\n const tr = await executeStoryboardTask(client, taskName, request);\n lastTaskResult = tr;\n lastError = undefined;\n if (tr.success) {\n return { taskResult: tr };\n }\n const err = extractAdcpError(tr);\n if (!err || !IN_FLIGHT_ERROR_CODES.has(err.code)) {\n return { taskResult: tr };\n }\n // Honor the seller's retry hint when present (clamped to [50ms, 3600s]\n // per spec retry_after range). Default to 200 ms — enough headroom\n // for the first request's INSERT to commit on a healthy seller, short\n // enough that the barrier timeout dominates on a stuck one.\n const hintMs = err.retry_after_seconds !== undefined ? Math.floor(err.retry_after_seconds * 1000) : 200;\n const sleepMs = Math.max(IN_FLIGHT_MIN_SLEEP_MS, Math.min(3_600_000, hintMs));\n const remaining = opts.deadlineMs - Date.now();\n if (remaining <= 0) {\n return { taskResult: tr };\n }\n await sleep(Math.min(sleepMs, remaining));\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n const remaining = opts.deadlineMs - Date.now();\n if (remaining <= 0) break;\n // Thrown SDK errors aren't `IDEMPOTENCY_IN_FLIGHT` by definition (the\n // SDK only throws on transport / parse failures); stop retrying so we\n // surface the thrown error rather than masking it as a retry storm.\n break;\n }\n }\n if (lastTaskResult) {\n return { taskResult: lastTaskResult, ...(lastError ? { error: lastError } : {}) };\n }\n return {\n taskResult: {\n success: false,\n ...(lastError !== undefined && { error: lastError }),\n },\n ...(lastError !== undefined && { error: lastError }),\n };\n}\n\n/**\n * Fan out N concurrent dispatches and collect the resolved set.\n *\n * Every dispatch shares the caller's `baseRequest` (so the canonical\n * payload hash matches across dispatches and the seller's idempotency\n * store sees a single logical request). Per-dispatch ergonomics:\n *\n * - `context.correlation_id` is rewritten to a per-dispatch suffix so\n * trace logs can attribute a delivery to a specific arm. Per the\n * spec, `context` (object form) is excluded from the canonical\n * payload hash, so distinct correlation_ids don't trip\n * IDEMPOTENCY_CONFLICT.\n * - `same_idempotency_key !== false` (default `true`): every dispatch\n * shares `baseRequest.idempotency_key`. The runner does NOT mint\n * fresh keys per arm — that defeats the test.\n * - `same_idempotency_key: false`: each dispatch gets its own\n * idempotency_key minted via `keyMinter`. Used by soak tests that\n * want parallelism without the race semantics.\n */\nexport interface RunParallelDispatchesOptions {\n /** Spec block from the storyboard step. */\n spec: ParallelDispatchSpec;\n /**\n * Mint a fresh idempotency_key. Only invoked when `same_idempotency_key`\n * is explicitly `false`. Callers thread the runner's existing\n * `generateIdempotencyKey()` here.\n */\n keyMinter: () => string;\n /**\n * Correlation prefix; the runner suffixes `#<dispatch_index>` to produce\n * the per-arm correlation_id written to `context.correlation_id`. Defaults\n * to the storyboard step id.\n */\n correlationPrefix?: string;\n}\n\nexport async function runParallelDispatches(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n baseRequest: Record<string, unknown>,\n opts: RunParallelDispatchesOptions\n): Promise<CrossResponseSet> {\n const { spec, keyMinter, correlationPrefix = 'parallel_dispatch' } = opts;\n const barrierMs = spec.barrier_timeout_ms ?? PARALLEL_DISPATCH_DEFAULT_BARRIER_MS;\n const sameKey = spec.same_idempotency_key !== false;\n const deadlineMs = Date.now() + barrierMs;\n\n const dispatchPromises = Array.from({ length: spec.count }, (_, index) => {\n const correlationId = `${correlationPrefix}#${index}`;\n const request: Record<string, unknown> = { ...baseRequest };\n if (!sameKey) {\n request.idempotency_key = keyMinter();\n }\n // Replace context.correlation_id without touching other fields. context\n // is hash-excluded only in object form; if a storyboard supplied a\n // string context (SI tools), leave it alone — the runner won't tag\n // those arms but the dispatch still functions.\n const existingContext = request.context;\n if (existingContext && typeof existingContext === 'object' && !Array.isArray(existingContext)) {\n request.context = { ...(existingContext as Record<string, unknown>), correlation_id: correlationId };\n } else if (existingContext === undefined) {\n request.context = { correlation_id: correlationId };\n }\n\n const started = Date.now();\n return dispatchWithBarrier(client, taskName, request, deadlineMs).then(outcome => {\n const dispatch: CrossResponseDispatch = {\n correlation_id: correlationId,\n duration_ms: Date.now() - started,\n ...(outcome.taskResult && { taskResult: outcome.taskResult }),\n ...(outcome.error !== undefined && { error: outcome.error }),\n ...(outcome.timed_out && { timed_out: true }),\n };\n return dispatch;\n });\n });\n\n const dispatches = await Promise.all(dispatchPromises);\n const resolved = dispatches\n .filter(d => d.taskResult?.success === true && !d.timed_out)\n .map(d => d.taskResult as TaskResult);\n return { dispatches, resolved };\n}\n\ninterface DispatchOutcome {\n taskResult?: TaskResult;\n error?: string;\n timed_out?: boolean;\n}\n\nasync function dispatchWithBarrier(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n request: Record<string, unknown>,\n deadlineMs: number\n): Promise<DispatchOutcome> {\n const work = dispatchOnceWithInflightRetry(client, taskName, request, { deadlineMs });\n const remaining = deadlineMs - Date.now();\n if (remaining <= 0) {\n return { timed_out: true };\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<DispatchOutcome>(resolve => {\n timeoutHandle = setTimeout(() => resolve({ timed_out: true }), remaining);\n });\n try {\n const result = await Promise.race([work.then(r => r as DispatchOutcome), timeoutPromise]);\n return result;\n } finally {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/parallel-dispatch.ts"],"sourcesContent":["/**\n * Parallel-dispatch runner support for the `parallel_dispatch_runner`\n * test-kit contract. Drives the concurrent-retry phase of the idempotency\n * storyboard (rule 9 / first-insert-wins): two `create_media_buy` calls\n * with the same `idempotency_key` race the seller's INSERT and must\n * resolve to one resource. Spec:\n * `test-kits/parallel-dispatch-runner.yaml`.\n *\n * Modes:\n * - `process_local` (default): fan out N requests via `Promise.all`. Event-\n * loop concurrent, sufficient to exercise the seller's INSERT race per\n * the contract YAML's `not_required_to_synthesize_packet_schedule`.\n * - `distributed`: barrier-synced workers across processes — out of scope\n * for this module. Callers grade the step `not_applicable` when the\n * storyboard requests `distributed` and the runner cannot satisfy it.\n *\n * In-flight resolution: a dispatch that returns `IDEMPOTENCY_IN_FLIGHT` or\n * (legacy) `SERVICE_UNAVAILABLE` with a `retry_after` hint retries with the\n * SAME idempotency_key after the hint elapses. The runner caps retries so\n * a stuck seller can't pin a barrier indefinitely; the outer barrier\n * timeout is the second line of defense.\n */\n\nimport type { TaskResult } from '../types';\nimport { executeStoryboardTask } from './task-map';\nimport type { CrossResponseDispatch, CrossResponseSet } from './validations';\nimport type { ParallelDispatchSpec } from './types';\n\n/**\n * Minimum and maximum parallel dispatches per the contract YAML. The\n * `count_max: 10` is a soft ceiling — every runner mode MUST support up to\n * 10 parallel dispatches per the spec's\n * `every_runner_mode_supports_up_to_10` note.\n */\nexport const PARALLEL_DISPATCH_COUNT_MIN = 2;\nexport const PARALLEL_DISPATCH_COUNT_MAX = 10;\n/** Default barrier timeout when the storyboard omits `barrier_timeout_ms`. */\nexport const PARALLEL_DISPATCH_DEFAULT_BARRIER_MS = 5000;\n/**\n * Per-dispatch retry budget for the in-flight branch. The outer barrier\n * (default 5s, configurable) is the real cap — the dispatcher honors the\n * seller's `retry_after` hint, then clamps every sleep to the remaining\n * barrier so the budget mostly matters when a misbehaving seller floods\n * tiny hints. 5 is enough headroom for that case without letting a stuck\n * seller pin the runner past the barrier.\n */\nconst IN_FLIGHT_RETRY_BUDGET = 5;\n/** Floor for the in-flight retry sleep so a misbehaving seller can't busy-loop the runner. */\nconst IN_FLIGHT_MIN_SLEEP_MS = 50;\n\n/**\n * The contract id storyboards declare on `requires_contract` to opt into\n * parallel-dispatch grading. Runners without the contract in scope grade\n * the step `not_applicable`.\n */\nexport const PARALLEL_DISPATCH_CONTRACT = 'parallel_dispatch_runner';\n\n/**\n * In-flight resolution: error codes the runner treats as \"retry with the\n * same idempotency_key after retry_after.\" `IDEMPOTENCY_IN_FLIGHT` is the\n * AdCP 3.1 wire code; `SERVICE_UNAVAILABLE` is accepted as a legacy\n * fallback so the runner grades SDKs that haven't migrated yet against\n * the same contract.\n */\nconst IN_FLIGHT_ERROR_CODES = new Set(['IDEMPOTENCY_IN_FLIGHT', 'SERVICE_UNAVAILABLE']);\n\n/** Parsed `(code, retry_after_seconds)` from a TaskResult, when present. */\ninterface AdcpErrorInfo {\n code: string;\n retry_after_seconds?: number;\n}\n\nfunction extractAdcpError(tr: TaskResult): AdcpErrorInfo | undefined {\n const data = tr.data as Record<string, unknown> | undefined;\n const err = data?.adcp_error as Record<string, unknown> | undefined;\n if (!err || typeof err.code !== 'string') return undefined;\n const retry = err.retry_after;\n return {\n code: err.code,\n ...(typeof retry === 'number' && Number.isFinite(retry) ? { retry_after_seconds: retry } : {}),\n };\n}\n\n/**\n * Configuration accepted by {@link dispatchOnceWithInflightRetry}.\n */\nexport interface DispatchOnceOptions {\n /**\n * Cooperative deadline (epoch ms) past which retries are abandoned. Set by\n * the caller to align with the outer barrier — a dispatch that's still\n * IDEMPOTENCY_IN_FLIGHT at the deadline returns its most recent\n * TaskResult so the barrier-timeout grading path can record the seller's\n * last-seen error code.\n */\n deadlineMs: number;\n}\n\n/**\n * Validate a {@link ParallelDispatchSpec} or return a structured authoring\n * error. Returns `null` when the spec is well-formed. The runner surfaces\n * the error as a `parallel_dispatch_misconfigured` step result rather than\n * silently clamping — silent clamping would let a storyboard advertise a\n * `count_max: 50` test that the runner only partially executed.\n */\nexport function validateParallelDispatchSpec(spec: ParallelDispatchSpec): string | null {\n if (!Number.isInteger(spec.count)) {\n return `parallel_dispatch.count must be an integer; received ${spec.count}`;\n }\n if (spec.count < PARALLEL_DISPATCH_COUNT_MIN || spec.count > PARALLEL_DISPATCH_COUNT_MAX) {\n return (\n `parallel_dispatch.count must be in [${PARALLEL_DISPATCH_COUNT_MIN}, ${PARALLEL_DISPATCH_COUNT_MAX}] ` +\n `per test-kits/parallel-dispatch-runner.yaml; received ${spec.count}`\n );\n }\n if (spec.barrier_timeout_ms !== undefined) {\n if (!Number.isFinite(spec.barrier_timeout_ms) || spec.barrier_timeout_ms <= 0) {\n return `parallel_dispatch.barrier_timeout_ms must be a positive finite number; received ${spec.barrier_timeout_ms}`;\n }\n }\n if (spec.mode !== undefined && spec.mode !== 'process_local' && spec.mode !== 'distributed') {\n return `parallel_dispatch.mode must be 'process_local' or 'distributed'; received '${spec.mode}'`;\n }\n return null;\n}\n\nconst sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, Math.max(0, ms)));\n\n/**\n * Run one dispatch and retry on the in-flight branch. Returns the dispatch's\n * terminal `TaskResult` (success, terminal error, or last-seen in-flight\n * after the deadline). Catches thrown errors and shapes them into a\n * synthetic error TaskResult so callers see a uniform `TaskResult`-shaped\n * outcome.\n */\nexport async function dispatchOnceWithInflightRetry(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n request: Record<string, unknown>,\n opts: DispatchOnceOptions\n): Promise<{ taskResult: TaskResult; error?: string }> {\n let lastTaskResult: TaskResult | undefined;\n let lastError: string | undefined;\n for (let attempt = 0; attempt < IN_FLIGHT_RETRY_BUDGET; attempt++) {\n try {\n const tr = await executeStoryboardTask(client, taskName, request);\n lastTaskResult = tr;\n lastError = undefined;\n if (tr.success) {\n return { taskResult: tr };\n }\n const err = extractAdcpError(tr);\n if (!err || !IN_FLIGHT_ERROR_CODES.has(err.code)) {\n return { taskResult: tr };\n }\n // Honor the seller's retry hint when present (clamped to [50ms, 3600s]\n // per spec retry_after range). Default to 200 ms — enough headroom\n // for the first request's INSERT to commit on a healthy seller, short\n // enough that the barrier timeout dominates on a stuck one.\n const hintMs = err.retry_after_seconds !== undefined ? Math.floor(err.retry_after_seconds * 1000) : 200;\n const sleepMs = Math.max(IN_FLIGHT_MIN_SLEEP_MS, Math.min(3_600_000, hintMs));\n const remaining = opts.deadlineMs - Date.now();\n if (remaining <= 0) {\n return { taskResult: tr };\n }\n await sleep(Math.min(sleepMs, remaining));\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n const remaining = opts.deadlineMs - Date.now();\n if (remaining <= 0) break;\n // Thrown SDK errors aren't `IDEMPOTENCY_IN_FLIGHT` by definition (the\n // SDK only throws on transport / parse failures); stop retrying so we\n // surface the thrown error rather than masking it as a retry storm.\n break;\n }\n }\n if (lastTaskResult) {\n return { taskResult: lastTaskResult, ...(lastError ? { error: lastError } : {}) };\n }\n return {\n taskResult: {\n success: false,\n ...(lastError !== undefined && { error: lastError }),\n },\n ...(lastError !== undefined && { error: lastError }),\n };\n}\n\n/**\n * Fan out N concurrent dispatches and collect the resolved set.\n *\n * Every dispatch shares the caller's `baseRequest` (so the canonical\n * payload hash matches across dispatches and the seller's idempotency\n * store sees a single logical request). Per-dispatch ergonomics:\n *\n * - `context.correlation_id` is rewritten to a per-dispatch suffix so\n * trace logs can attribute a delivery to a specific arm. Per the\n * spec, `context` (object form) is excluded from the canonical\n * payload hash, so distinct correlation_ids don't trip\n * IDEMPOTENCY_CONFLICT.\n * - `same_idempotency_key !== false` (default `true`): every dispatch\n * shares `baseRequest.idempotency_key`. The runner does NOT mint\n * fresh keys per arm — that defeats the test.\n * - `same_idempotency_key: false`: each dispatch gets its own\n * idempotency_key minted via `keyMinter`. Used by soak tests that\n * want parallelism without the race semantics.\n */\nexport interface RunParallelDispatchesOptions {\n /** Spec block from the storyboard step. */\n spec: ParallelDispatchSpec;\n /**\n * Mint a fresh idempotency_key. Only invoked when `same_idempotency_key`\n * is explicitly `false`. Callers thread the runner's existing\n * `generateIdempotencyKey()` here.\n */\n keyMinter: () => string;\n /**\n * Correlation prefix; the runner suffixes `#<dispatch_index>` to produce\n * the per-arm correlation_id written to `context.correlation_id`. Defaults\n * to the storyboard step id.\n */\n correlationPrefix?: string;\n}\n\nexport async function runParallelDispatches(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n baseRequest: Record<string, unknown>,\n opts: RunParallelDispatchesOptions\n): Promise<CrossResponseSet> {\n const { spec, keyMinter, correlationPrefix = 'parallel_dispatch' } = opts;\n const barrierMs = spec.barrier_timeout_ms ?? PARALLEL_DISPATCH_DEFAULT_BARRIER_MS;\n const sameKey = spec.same_idempotency_key !== false;\n const deadlineMs = Date.now() + barrierMs;\n\n const dispatchPromises = Array.from({ length: spec.count }, (_, index) => {\n const correlationId = `${correlationPrefix}#${index}`;\n const request: Record<string, unknown> = { ...baseRequest };\n if (!sameKey) {\n request.idempotency_key = keyMinter();\n }\n // Replace context.correlation_id without touching other fields. context\n // is hash-excluded only in object form; if a storyboard supplied a\n // string context (SI tools), leave it alone — the runner won't tag\n // those arms but the dispatch still functions.\n const existingContext = request.context;\n if (existingContext && typeof existingContext === 'object' && !Array.isArray(existingContext)) {\n request.context = { ...(existingContext as Record<string, unknown>), correlation_id: correlationId };\n } else if (existingContext === undefined) {\n request.context = { correlation_id: correlationId };\n }\n\n const started = Date.now();\n return dispatchWithBarrier(client, taskName, request, deadlineMs).then(outcome => {\n const dispatch: CrossResponseDispatch = {\n correlation_id: correlationId,\n duration_ms: Date.now() - started,\n ...(outcome.taskResult && { taskResult: outcome.taskResult }),\n ...(outcome.error !== undefined && { error: outcome.error }),\n ...(outcome.timed_out && { timed_out: true }),\n };\n return dispatch;\n });\n });\n\n const dispatches = await Promise.all(dispatchPromises);\n const resolved = dispatches\n .filter(d => d.taskResult?.success === true && !d.timed_out)\n .map(d => d.taskResult as TaskResult);\n return { dispatches, resolved };\n}\n\ninterface DispatchOutcome {\n taskResult?: TaskResult;\n error?: string;\n timed_out?: boolean;\n}\n\nasync function dispatchWithBarrier(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- client surface varies (TestClient)\n client: any,\n taskName: string,\n request: Record<string, unknown>,\n deadlineMs: number\n): Promise<DispatchOutcome> {\n const work = dispatchOnceWithInflightRetry(client, taskName, request, { deadlineMs });\n const remaining = deadlineMs - Date.now();\n if (remaining <= 0) {\n return { timed_out: true };\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<DispatchOutcome>(resolve => {\n timeoutHandle = setTimeout(() => resolve({ timed_out: true }), remaining);\n });\n try {\n const result = await Promise.race([work.then(r => r as DispatchOutcome), timeoutPromise]);\n return result;\n } finally {\n if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  const WILDCARD = /* @__PURE__ */ Symbol("path.wildcard");
8
2
  const RESOLVE_PATH_ALL_MAX = 1e4;
9
3
  const MAX_PATH_LENGTH = 1024;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/path.ts"],"sourcesContent":["/**\n * Shared JSON path utilities for storyboard context and validations.\n *\n * Parses dot-notation paths with array indexing (e.g., \"accounts[0].account_id\")\n * into segment arrays, and resolves/sets values at those paths.\n */\n\n/**\n * Wildcard marker produced by `parsePathWithWildcards` for `[*]` / `[]`\n * segments.\n * The plain `parsePath` tokenizer does not emit it — callers that need\n * wildcard semantics (`resolvePathAll`) use the wildcard-aware parser.\n */\nexport const WILDCARD = Symbol('path.wildcard');\n\n/**\n * Upper bound on the number of terminal values `resolvePathAll` will emit.\n * Guards the runner against OOM when a wildcard-heavy path (`a[*].b[*].c[*]…`)\n * is applied to a malicious agent response shaped to maximize fan-out.\n * The cap is well above any realistic storyboard use (a 1000-product\n * catalog × 10 formats = 10k terminal values).\n */\nexport const RESOLVE_PATH_ALL_MAX = 10_000;\n\n/**\n * Upper bound on storyboard path-string length. The parser is linear in\n * input size, but a hostile storyboard can still spend CPU against a\n * megabyte-long path with no legitimate use case.\n */\nconst MAX_PATH_LENGTH = 1024;\n\n/**\n * Parse a path string into segments.\n * \"accounts[0].account_id\" → [\"accounts\", 0, \"account_id\"]\n *\n * Returns an empty segment list for paths that exceed `MAX_PATH_LENGTH`\n * so downstream resolvers degrade to \"nothing at this path\" instead of\n * burning CPU on a pathological input.\n */\nexport function parsePath(path: string): Array<string | number> {\n if (path.length > MAX_PATH_LENGTH) return [];\n const segments: Array<string | number> = [];\n const re = /([^.\\[\\]]+)|\\[(\\d+)\\]/g;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(path)) !== null) {\n if (match[2] !== undefined) {\n segments.push(parseInt(match[2], 10));\n } else if (match[1] !== undefined) {\n segments.push(match[1]);\n }\n }\n\n return segments;\n}\n\n/**\n * Parse a path string into segments, preserving `[*]` wildcards. Empty\n * brackets (`[]`) are accepted as a shorthand wildcard for storyboard\n * assertions written in the same style as schema prose (`allowed_actions[]`).\n * \"products[*].format_ids[*]\" → [\"products\", WILDCARD, \"format_ids\", WILDCARD]\n */\nexport function parsePathWithWildcards(path: string): Array<string | number | typeof WILDCARD> {\n if (path.length > MAX_PATH_LENGTH) return [];\n const segments: Array<string | number | typeof WILDCARD> = [];\n const re = /([^.\\[\\]]+)|\\[(\\d+)\\]|\\[(\\*)?\\]/g;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(path)) !== null) {\n if (match[3] !== undefined || match[0] === '[]') {\n segments.push(WILDCARD);\n } else if (match[2] !== undefined) {\n segments.push(parseInt(match[2], 10));\n } else if (match[1] !== undefined) {\n segments.push(match[1]);\n }\n }\n\n return segments;\n}\n\n/**\n * Resolve a dot-path with array indexing against an object.\n *\n * Examples:\n * \"accounts[0].account_id\" → obj.accounts[0].account_id\n * \"formats[0].format_id.id\" → obj.formats[0].format_id.id\n * \"status\" → obj.status\n */\nexport function resolvePath(obj: unknown, path: string): unknown {\n if (obj === null || obj === undefined) return undefined;\n\n const segments = parsePath(path);\n let current: unknown = obj;\n\n for (const segment of segments) {\n if (current === null || current === undefined) return undefined;\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return undefined;\n current = current[segment];\n } else {\n if (FORBIDDEN_KEYS.has(segment)) return undefined;\n if (typeof current !== 'object') return undefined;\n // Own-property gate keeps `Object.prototype` accessors (`toString`,\n // `hasOwnProperty`, …) from surfacing into compliance reports as\n // \"agent returned X.\" Matches `resolvePathAll` / `setPath`.\n if (!Object.prototype.hasOwnProperty.call(current, segment)) return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n }\n\n return current;\n}\n\n/**\n * Resolve a wildcard-aware path and return every terminal value as a flat\n * array. `[*]` segments fan out over arrays; undefined intermediates\n * short-circuit the current branch without throwing. `null`, `false`, `0`,\n * and `\"\"` terminals are preserved — only `undefined` means \"no value at\n * this path.\" This matches `resolvePath`'s scalar contract.\n *\n * Output is capped at `RESOLVE_PATH_ALL_MAX` terminal values. When the cap\n * is hit the walker stops and returns what it has; callers that need to\n * know whether truncation happened should compare the length to the cap.\n *\n * Examples:\n * \"products[*].format_ids[*]\" on `{products:[{format_ids:[a,b]},{format_ids:[c]}]}` → [a, b, c]\n * \"formats[*].format_id\" on `{formats:[{format_id:x},{format_id:y}]}` → [x, y]\n * \"status\" (no wildcard) → [obj.status] if defined, else []\n */\nexport function resolvePathAll(obj: unknown, path: string): unknown[] {\n if (obj === undefined) return [];\n const segments = parsePathWithWildcards(path);\n const results: unknown[] = [];\n walk(obj, segments, 0, results);\n return results;\n}\n\nconst PORTABLE_IDENTIFIER_SEGMENT_RE = /^[A-Za-z_][A-Za-z0-9_]*(?:\\[\\*\\])?$/;\nconst RESERVED_IDENTIFIER_ROOTS = new Set(['request', 'response', 'context']);\n\nexport interface PortableIdentifierPathIssue {\n path: string;\n reason: string;\n}\n\n/**\n * Validate the portable `upstream_traffic.identifier_paths` grammar.\n *\n * These paths are intentionally narrower than the general storyboard path\n * helpers: request-payload-relative dotted keys, with at most one `[*]`\n * wildcard suffix per segment. They are exchanged across independent\n * storyboard runners, so permissive JSONPath conveniences would create\n * non-portable grading.\n */\nexport function validatePortableIdentifierPath(path: string): string | null {\n if (typeof path !== 'string' || path.length === 0) return 'must be a non-empty string';\n if (path.length > MAX_PATH_LENGTH) return `must be ${MAX_PATH_LENGTH} characters or fewer`;\n if (path.startsWith('$')) return 'must be request-payload-relative; explicit roots like \"$.foo\" are not allowed';\n if (path.startsWith('.') || path.endsWith('.') || path.includes('..')) {\n return 'must not contain empty segments or recursive descent';\n }\n\n const segments = path.split('.');\n const first = segments[0]!;\n const firstKey = first.endsWith('[*]') ? first.slice(0, -3) : first;\n if (RESERVED_IDENTIFIER_ROOTS.has(firstKey)) {\n return `must not use reserved root \"${firstKey}\"`;\n }\n\n for (const segment of segments) {\n if (segment.includes('[\"') || segment.includes(\"['\")) return 'must not use bracket-quoted keys';\n if (/\\[\\d+\\]/.test(segment)) return 'must not use numeric array indexes';\n if (!PORTABLE_IDENTIFIER_SEGMENT_RE.test(segment)) {\n return `segment \"${segment}\" must be an identifier key optionally followed by [*]`;\n }\n const key = segment.endsWith('[*]') ? segment.slice(0, -3) : segment;\n if (FORBIDDEN_KEYS.has(key)) return `must not use forbidden key \"${key}\"`;\n }\n\n return null;\n}\n\n/**\n * Resolve a path that has already been restricted to the portable\n * `identifier_paths` grammar. Invalid paths return no values; callers that\n * need author-facing diagnostics should call `validatePortableIdentifierPath`\n * first and surface the reason.\n */\nexport function resolvePortableIdentifierPathAll(obj: unknown, path: string): unknown[] {\n if (obj === undefined || validatePortableIdentifierPath(path) !== null) return [];\n const segments = path.split('.').map(segment => ({\n key: segment.endsWith('[*]') ? segment.slice(0, -3) : segment,\n wildcard: segment.endsWith('[*]'),\n }));\n\n let frontier: unknown[] = [obj];\n for (const segment of segments) {\n const next: unknown[] = [];\n for (const current of frontier) {\n if (next.length >= RESOLVE_PATH_ALL_MAX) break;\n if (current === undefined || current === null || typeof current !== 'object') continue;\n if (FORBIDDEN_KEYS.has(segment.key)) continue;\n if (!Object.prototype.hasOwnProperty.call(current, segment.key)) continue;\n const value = (current as Record<string, unknown>)[segment.key];\n if (segment.wildcard) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (next.length >= RESOLVE_PATH_ALL_MAX) break;\n next.push(item);\n }\n }\n } else {\n next.push(value);\n }\n }\n frontier = next.slice(0, RESOLVE_PATH_ALL_MAX).filter(value => value !== undefined);\n }\n\n return frontier;\n}\n\nfunction walk(current: unknown, segments: Array<string | number | typeof WILDCARD>, i: number, out: unknown[]): void {\n if (out.length >= RESOLVE_PATH_ALL_MAX) return;\n if (i === segments.length) {\n if (current !== undefined) out.push(current);\n return;\n }\n if (current === undefined || current === null) return;\n const segment = segments[i]!;\n if (segment === WILDCARD) {\n if (!Array.isArray(current)) return;\n for (const item of current) {\n if (out.length >= RESOLVE_PATH_ALL_MAX) return;\n walk(item, segments, i + 1, out);\n }\n return;\n }\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return;\n walk(current[segment], segments, i + 1, out);\n return;\n }\n if (FORBIDDEN_KEYS.has(segment)) return;\n if (typeof current !== 'object') return;\n // Gate on own properties so attackers can't surface Object.prototype state\n // even when a key slips past FORBIDDEN_KEYS (defense-in-depth; FORBIDDEN_KEYS\n // already catches `__proto__`/`constructor`/`prototype` by name).\n if (!Object.prototype.hasOwnProperty.call(current, segment)) return;\n walk((current as Record<string, unknown>)[segment], segments, i + 1, out);\n}\n\n/**\n * Convert a dot/bracket path (`accounts[0].account_id`) into an RFC 6901\n * JSON Pointer (`/accounts/0/account_id`). Returns `\"\"` for the empty path\n * (the root per RFC 6901). Per RFC 6901 §3, `~` is escaped as `~0` and `/`\n * as `~1`.\n */\nexport function toJsonPointer(path: string): string {\n const segments = parsePathWithWildcards(path);\n if (segments.length === 0) return '';\n return (\n '/' +\n segments\n .map(seg =>\n seg === WILDCARD\n ? '*'\n : typeof seg === 'number'\n ? String(seg)\n : String(seg).replace(/~/g, '~0').replace(/\\//g, '~1')\n )\n .join('/')\n );\n}\n\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Set a value at a dot-path with array indexing.\n * Creates intermediate objects/arrays as needed.\n * Guards against prototype pollution.\n *\n * \"media_buy_ids[0]\" → obj.media_buy_ids[0] = value\n */\nexport function setPath(obj: Record<string, unknown>, path: string, value: unknown): void {\n const segments = parsePath(path);\n let current: unknown = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i]!;\n const nextSegment = segments[i + 1];\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return;\n if (current[segment] === undefined || current[segment] === null) {\n current[segment] = typeof nextSegment === 'number' ? [] : {};\n }\n current = current[segment];\n } else {\n if (FORBIDDEN_KEYS.has(segment)) return;\n if (!isPlainObject(current)) return;\n if (!Object.prototype.hasOwnProperty.call(current, segment) || current[segment] == null) {\n Object.defineProperty(current, segment, {\n value: typeof nextSegment === 'number' ? [] : {},\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n current = current[segment];\n }\n }\n\n const lastSegment = segments[segments.length - 1];\n if (lastSegment === undefined) return;\n\n if (typeof lastSegment === 'number') {\n if (Array.isArray(current)) {\n current[lastSegment] = value;\n }\n } else {\n if (FORBIDDEN_KEYS.has(lastSegment)) return;\n if (!isPlainObject(current)) return;\n Object.defineProperty(current, lastSegment, {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/path.ts"],"sourcesContent":["/**\n * Shared JSON path utilities for storyboard context and validations.\n *\n * Parses dot-notation paths with array indexing (e.g., \"accounts[0].account_id\")\n * into segment arrays, and resolves/sets values at those paths.\n */\n\n/**\n * Wildcard marker produced by `parsePathWithWildcards` for `[*]` / `[]`\n * segments.\n * The plain `parsePath` tokenizer does not emit it — callers that need\n * wildcard semantics (`resolvePathAll`) use the wildcard-aware parser.\n */\nexport const WILDCARD = Symbol('path.wildcard');\n\n/**\n * Upper bound on the number of terminal values `resolvePathAll` will emit.\n * Guards the runner against OOM when a wildcard-heavy path (`a[*].b[*].c[*]…`)\n * is applied to a malicious agent response shaped to maximize fan-out.\n * The cap is well above any realistic storyboard use (a 1000-product\n * catalog × 10 formats = 10k terminal values).\n */\nexport const RESOLVE_PATH_ALL_MAX = 10_000;\n\n/**\n * Upper bound on storyboard path-string length. The parser is linear in\n * input size, but a hostile storyboard can still spend CPU against a\n * megabyte-long path with no legitimate use case.\n */\nconst MAX_PATH_LENGTH = 1024;\n\n/**\n * Parse a path string into segments.\n * \"accounts[0].account_id\" → [\"accounts\", 0, \"account_id\"]\n *\n * Returns an empty segment list for paths that exceed `MAX_PATH_LENGTH`\n * so downstream resolvers degrade to \"nothing at this path\" instead of\n * burning CPU on a pathological input.\n */\nexport function parsePath(path: string): Array<string | number> {\n if (path.length > MAX_PATH_LENGTH) return [];\n const segments: Array<string | number> = [];\n const re = /([^.\\[\\]]+)|\\[(\\d+)\\]/g;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(path)) !== null) {\n if (match[2] !== undefined) {\n segments.push(parseInt(match[2], 10));\n } else if (match[1] !== undefined) {\n segments.push(match[1]);\n }\n }\n\n return segments;\n}\n\n/**\n * Parse a path string into segments, preserving `[*]` wildcards. Empty\n * brackets (`[]`) are accepted as a shorthand wildcard for storyboard\n * assertions written in the same style as schema prose (`allowed_actions[]`).\n * \"products[*].format_ids[*]\" → [\"products\", WILDCARD, \"format_ids\", WILDCARD]\n */\nexport function parsePathWithWildcards(path: string): Array<string | number | typeof WILDCARD> {\n if (path.length > MAX_PATH_LENGTH) return [];\n const segments: Array<string | number | typeof WILDCARD> = [];\n const re = /([^.\\[\\]]+)|\\[(\\d+)\\]|\\[(\\*)?\\]/g;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(path)) !== null) {\n if (match[3] !== undefined || match[0] === '[]') {\n segments.push(WILDCARD);\n } else if (match[2] !== undefined) {\n segments.push(parseInt(match[2], 10));\n } else if (match[1] !== undefined) {\n segments.push(match[1]);\n }\n }\n\n return segments;\n}\n\n/**\n * Resolve a dot-path with array indexing against an object.\n *\n * Examples:\n * \"accounts[0].account_id\" → obj.accounts[0].account_id\n * \"formats[0].format_id.id\" → obj.formats[0].format_id.id\n * \"status\" → obj.status\n */\nexport function resolvePath(obj: unknown, path: string): unknown {\n if (obj === null || obj === undefined) return undefined;\n\n const segments = parsePath(path);\n let current: unknown = obj;\n\n for (const segment of segments) {\n if (current === null || current === undefined) return undefined;\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return undefined;\n current = current[segment];\n } else {\n if (FORBIDDEN_KEYS.has(segment)) return undefined;\n if (typeof current !== 'object') return undefined;\n // Own-property gate keeps `Object.prototype` accessors (`toString`,\n // `hasOwnProperty`, …) from surfacing into compliance reports as\n // \"agent returned X.\" Matches `resolvePathAll` / `setPath`.\n if (!Object.prototype.hasOwnProperty.call(current, segment)) return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n }\n\n return current;\n}\n\n/**\n * Resolve a wildcard-aware path and return every terminal value as a flat\n * array. `[*]` segments fan out over arrays; undefined intermediates\n * short-circuit the current branch without throwing. `null`, `false`, `0`,\n * and `\"\"` terminals are preserved — only `undefined` means \"no value at\n * this path.\" This matches `resolvePath`'s scalar contract.\n *\n * Output is capped at `RESOLVE_PATH_ALL_MAX` terminal values. When the cap\n * is hit the walker stops and returns what it has; callers that need to\n * know whether truncation happened should compare the length to the cap.\n *\n * Examples:\n * \"products[*].format_ids[*]\" on `{products:[{format_ids:[a,b]},{format_ids:[c]}]}` → [a, b, c]\n * \"formats[*].format_id\" on `{formats:[{format_id:x},{format_id:y}]}` → [x, y]\n * \"status\" (no wildcard) → [obj.status] if defined, else []\n */\nexport function resolvePathAll(obj: unknown, path: string): unknown[] {\n if (obj === undefined) return [];\n const segments = parsePathWithWildcards(path);\n const results: unknown[] = [];\n walk(obj, segments, 0, results);\n return results;\n}\n\nconst PORTABLE_IDENTIFIER_SEGMENT_RE = /^[A-Za-z_][A-Za-z0-9_]*(?:\\[\\*\\])?$/;\nconst RESERVED_IDENTIFIER_ROOTS = new Set(['request', 'response', 'context']);\n\nexport interface PortableIdentifierPathIssue {\n path: string;\n reason: string;\n}\n\n/**\n * Validate the portable `upstream_traffic.identifier_paths` grammar.\n *\n * These paths are intentionally narrower than the general storyboard path\n * helpers: request-payload-relative dotted keys, with at most one `[*]`\n * wildcard suffix per segment. They are exchanged across independent\n * storyboard runners, so permissive JSONPath conveniences would create\n * non-portable grading.\n */\nexport function validatePortableIdentifierPath(path: string): string | null {\n if (typeof path !== 'string' || path.length === 0) return 'must be a non-empty string';\n if (path.length > MAX_PATH_LENGTH) return `must be ${MAX_PATH_LENGTH} characters or fewer`;\n if (path.startsWith('$')) return 'must be request-payload-relative; explicit roots like \"$.foo\" are not allowed';\n if (path.startsWith('.') || path.endsWith('.') || path.includes('..')) {\n return 'must not contain empty segments or recursive descent';\n }\n\n const segments = path.split('.');\n const first = segments[0]!;\n const firstKey = first.endsWith('[*]') ? first.slice(0, -3) : first;\n if (RESERVED_IDENTIFIER_ROOTS.has(firstKey)) {\n return `must not use reserved root \"${firstKey}\"`;\n }\n\n for (const segment of segments) {\n if (segment.includes('[\"') || segment.includes(\"['\")) return 'must not use bracket-quoted keys';\n if (/\\[\\d+\\]/.test(segment)) return 'must not use numeric array indexes';\n if (!PORTABLE_IDENTIFIER_SEGMENT_RE.test(segment)) {\n return `segment \"${segment}\" must be an identifier key optionally followed by [*]`;\n }\n const key = segment.endsWith('[*]') ? segment.slice(0, -3) : segment;\n if (FORBIDDEN_KEYS.has(key)) return `must not use forbidden key \"${key}\"`;\n }\n\n return null;\n}\n\n/**\n * Resolve a path that has already been restricted to the portable\n * `identifier_paths` grammar. Invalid paths return no values; callers that\n * need author-facing diagnostics should call `validatePortableIdentifierPath`\n * first and surface the reason.\n */\nexport function resolvePortableIdentifierPathAll(obj: unknown, path: string): unknown[] {\n if (obj === undefined || validatePortableIdentifierPath(path) !== null) return [];\n const segments = path.split('.').map(segment => ({\n key: segment.endsWith('[*]') ? segment.slice(0, -3) : segment,\n wildcard: segment.endsWith('[*]'),\n }));\n\n let frontier: unknown[] = [obj];\n for (const segment of segments) {\n const next: unknown[] = [];\n for (const current of frontier) {\n if (next.length >= RESOLVE_PATH_ALL_MAX) break;\n if (current === undefined || current === null || typeof current !== 'object') continue;\n if (FORBIDDEN_KEYS.has(segment.key)) continue;\n if (!Object.prototype.hasOwnProperty.call(current, segment.key)) continue;\n const value = (current as Record<string, unknown>)[segment.key];\n if (segment.wildcard) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (next.length >= RESOLVE_PATH_ALL_MAX) break;\n next.push(item);\n }\n }\n } else {\n next.push(value);\n }\n }\n frontier = next.slice(0, RESOLVE_PATH_ALL_MAX).filter(value => value !== undefined);\n }\n\n return frontier;\n}\n\nfunction walk(current: unknown, segments: Array<string | number | typeof WILDCARD>, i: number, out: unknown[]): void {\n if (out.length >= RESOLVE_PATH_ALL_MAX) return;\n if (i === segments.length) {\n if (current !== undefined) out.push(current);\n return;\n }\n if (current === undefined || current === null) return;\n const segment = segments[i]!;\n if (segment === WILDCARD) {\n if (!Array.isArray(current)) return;\n for (const item of current) {\n if (out.length >= RESOLVE_PATH_ALL_MAX) return;\n walk(item, segments, i + 1, out);\n }\n return;\n }\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return;\n walk(current[segment], segments, i + 1, out);\n return;\n }\n if (FORBIDDEN_KEYS.has(segment)) return;\n if (typeof current !== 'object') return;\n // Gate on own properties so attackers can't surface Object.prototype state\n // even when a key slips past FORBIDDEN_KEYS (defense-in-depth; FORBIDDEN_KEYS\n // already catches `__proto__`/`constructor`/`prototype` by name).\n if (!Object.prototype.hasOwnProperty.call(current, segment)) return;\n walk((current as Record<string, unknown>)[segment], segments, i + 1, out);\n}\n\n/**\n * Convert a dot/bracket path (`accounts[0].account_id`) into an RFC 6901\n * JSON Pointer (`/accounts/0/account_id`). Returns `\"\"` for the empty path\n * (the root per RFC 6901). Per RFC 6901 §3, `~` is escaped as `~0` and `/`\n * as `~1`.\n */\nexport function toJsonPointer(path: string): string {\n const segments = parsePathWithWildcards(path);\n if (segments.length === 0) return '';\n return (\n '/' +\n segments\n .map(seg =>\n seg === WILDCARD\n ? '*'\n : typeof seg === 'number'\n ? String(seg)\n : String(seg).replace(/~/g, '~0').replace(/\\//g, '~1')\n )\n .join('/')\n );\n}\n\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Set a value at a dot-path with array indexing.\n * Creates intermediate objects/arrays as needed.\n * Guards against prototype pollution.\n *\n * \"media_buy_ids[0]\" → obj.media_buy_ids[0] = value\n */\nexport function setPath(obj: Record<string, unknown>, path: string, value: unknown): void {\n const segments = parsePath(path);\n let current: unknown = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i]!;\n const nextSegment = segments[i + 1];\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current)) return;\n if (current[segment] === undefined || current[segment] === null) {\n current[segment] = typeof nextSegment === 'number' ? [] : {};\n }\n current = current[segment];\n } else {\n if (FORBIDDEN_KEYS.has(segment)) return;\n if (!isPlainObject(current)) return;\n if (!Object.prototype.hasOwnProperty.call(current, segment) || current[segment] == null) {\n Object.defineProperty(current, segment, {\n value: typeof nextSegment === 'number' ? [] : {},\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n current = current[segment];\n }\n }\n\n const lastSegment = segments[segments.length - 1];\n if (lastSegment === undefined) return;\n\n if (typeof lastSegment === 'number') {\n if (Array.isArray(current)) {\n current[lastSegment] = value;\n }\n } else {\n if (FORBIDDEN_KEYS.has(lastSegment)) return;\n if (!isPlainObject(current)) return;\n Object.defineProperty(current, lastSegment, {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { randomBytes } from "crypto";
8
2
  import { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from "@modelcontextprotocol/sdk/types.js";
9
3
  import {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/testing/storyboard/probes.ts"],"sourcesContent":["/**\n * HTTP probes used by security-baseline storyboard tasks.\n *\n * Three synthetic tasks dispatch through here instead of the MCP client:\n *\n * - `protected_resource_metadata` — GET the agent's\n * `/.well-known/oauth-protected-resource<mountPath>` and verify RFC 9728.\n * - `oauth_auth_server_metadata` — GET `<issuer>/.well-known/oauth-authorization-server`\n * using the first issuer from the previous step's response. Hardened against\n * SSRF because the URL comes from agent-controlled data.\n * - `assert_contribution` — no network; evaluates accumulated flags set by\n * prior steps that carried `contributes_to`.\n */\nimport { randomBytes } from 'crypto';\nimport { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/sdk/types.js';\nimport {\n ssrfSafeFetch,\n decodeBodyAsJsonOrText,\n SsrfRefusedError,\n isAlwaysBlocked as sharedIsAlwaysBlocked,\n isPrivateIp as sharedIsPrivateIp,\n} from '../../net';\nimport type { HttpProbeResult } from './types';\nimport type { TaskResult } from '../types';\n\n// Timeout + body-cap defaults come from `ssrfSafeFetch` (10 s, 64 KiB).\n// The probe wrappers deliberately don't override them so probe behavior\n// stays in sync with the shared primitive.\n\n/** Task names dispatched via HTTP probes (not via the MCP client). */\nexport const PROBE_TASKS = new Set([\n 'protected_resource_metadata',\n 'oauth_auth_server_metadata',\n 'assert_contribution',\n 'request_signing_probe',\n 'fetch_brand_jwks',\n 'assert_jwks_purpose',\n 'expect_rate_limit_not_replayed',\n]);\n\n// ---------------------------------------------------------------------------\n// Protected-resource metadata probe\n// ---------------------------------------------------------------------------\n\n/**\n * GET `<agentUrl origin>/.well-known/oauth-protected-resource<agentUrl path>`.\n * Same-origin as the agent, so SSRF risk is bounded.\n *\n * When `allowPrivateIp` is set (matches the runner's `--allow-http` flag),\n * loopback and RFC 1918 targets are allowed so dev loops against localhost\n * agents work end-to-end.\n */\nexport async function probeProtectedResourceMetadata(\n agentUrl: string,\n options: { allowPrivateIp?: boolean } = {}\n): Promise<HttpProbeResult> {\n const u = new URL(agentUrl);\n const metadataUrl = `${u.origin}/.well-known/oauth-protected-resource${u.pathname}`;\n return fetchProbe(metadataUrl, { allowPrivateIp: options.allowPrivateIp ?? false });\n}\n\n// ---------------------------------------------------------------------------\n// OAuth authorization-server metadata probe\n// ---------------------------------------------------------------------------\n\n/**\n * GET `<issuer>/.well-known/oauth-authorization-server` for the first issuer\n * named in the protected-resource metadata. Because the URL is agent-supplied,\n * this is the SSRF-hot path — {@link fetchProbe} rejects private networks,\n * non-https schemes, and unbounded responses.\n */\nexport async function probeOauthAuthServerMetadata(\n priorProbe: HttpProbeResult | undefined,\n options: { allowPrivateIp?: boolean } = {}\n): Promise<HttpProbeResult> {\n if (!priorProbe || priorProbe.error) {\n return {\n url: '',\n status: 0,\n headers: {},\n body: null,\n error: 'protected_resource_metadata step missing or errored — cannot resolve issuer',\n };\n }\n const body = priorProbe.body as { authorization_servers?: unknown } | null;\n const servers = Array.isArray(body?.authorization_servers) ? (body!.authorization_servers as string[]) : [];\n if (servers.length === 0 || typeof servers[0] !== 'string') {\n return {\n url: '',\n status: 0,\n headers: {},\n body: null,\n error: 'No authorization_servers[0] found in protected-resource metadata',\n };\n }\n const issuer = servers[0].replace(/\\/$/, '');\n const metadataUrl = `${issuer}/.well-known/oauth-authorization-server`;\n return fetchProbe(metadataUrl, { allowPrivateIp: options.allowPrivateIp ?? false });\n}\n\n// ---------------------------------------------------------------------------\n// Fetch with guardrails\n// ---------------------------------------------------------------------------\n\nexport interface FetchProbeOptions {\n /** Allow http:// and private-IP destinations. Default false. */\n allowPrivateIp?: boolean;\n /** Override timeout for specific call sites. */\n timeoutMs?: number;\n}\n\n/**\n * Perform a GET against an attacker-influenceable URL with defensive limits.\n *\n * Guardrails (RFC 9728 / RFC 8414 metadata endpoints typically live on public\n * HTTPS; anything else is suspicious):\n * - Scheme: `https:` only by default; `http:` allowed only when\n * `allowPrivateIp` is set. `file:`, `ftp:`, `data:`, etc. are always rejected.\n * - DNS: resolves all A/AAAA records once, rejects if any is private, then\n * pins the outbound connection to the validated IP. Defeats DNS rebinding\n * where an attacker's authoritative nameserver returns a public address\n * to our guard lookup and a private address to the connect-time lookup.\n * - Private-IP block applies RFC 1918, loopback, link-local, IPv6 ULA,\n * CGNAT (100.64/10), multicast, broadcast, and IPv4-mapped IPv6.\n * - IMDS (169.254.169.254 / fe80::) stays blocked **even under\n * `allowPrivateIp`** — no legitimate dev use for probing it.\n * - Redirects are NOT followed (`redirect: 'manual'`).\n * - Body capped at 64 KiB, total fetch time capped at 10 s.\n */\nexport async function fetchProbe(url: string, options: FetchProbeOptions = {}): Promise<HttpProbeResult> {\n try {\n const res = await ssrfSafeFetch(url, {\n method: 'GET',\n headers: { accept: 'application/json' },\n allowPrivateIp: options.allowPrivateIp ?? false,\n ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n });\n return {\n url,\n status: res.status,\n headers: res.headers,\n body: decodeBodyAsJsonOrText(res.body, res.headers['content-type']),\n };\n } catch (err) {\n return {\n url,\n status: 0,\n headers: {},\n body: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential generators (value_strategy)\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a per-run bogus API key. Prefix is human-readable for log grep;\n * the 32 random hex bytes guarantee no allowlist collision.\n */\nexport function generateRandomInvalidApiKey(): string {\n return `invalid-${randomBytes(32).toString('hex')}`;\n}\n\n/**\n * Generate a per-run bogus JWT-shaped Bearer token. Emits three segments with\n * valid base64url-encoded JSON header/payload and a random signature — so\n * well-implemented validators fail at signature verification (→ 401), and\n * strict parse-time validators that reject at the structural level also fail\n * cleanly (→ 400 per RFC 6750 §3.1). Either is conformant.\n */\nexport function generateRandomInvalidJwt(): string {\n const header = base64url(Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })));\n const payload = base64url(\n Buffer.from(JSON.stringify({ sub: `invalid-${randomBytes(8).toString('hex')}`, aud: 'invalid-probe' }))\n );\n const signature = base64url(randomBytes(32));\n return `${header}.${payload}.${signature}`;\n}\n\nfunction base64url(buf: Buffer): string {\n return buf.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n// ---------------------------------------------------------------------------\n// Raw-MCP probe (auth-override dispatch)\n// ---------------------------------------------------------------------------\n\nlet probeRequestId = 0;\nconst MCP_SESSION_ID_HEADER = 'mcp-session-id';\nconst MCP_PROTOCOL_VERSION_HEADER = 'mcp-protocol-version';\n\ntype JsonRpcEnvelope = {\n jsonrpc: '2.0';\n id?: number;\n method?: string;\n params?: Record<string, unknown>;\n result?: { structuredContent?: unknown; content?: unknown; isError?: boolean; protocolVersion?: string };\n error?: { message?: string; code?: number };\n};\n\ninterface RawJsonRpcPostResult {\n httpResult: HttpProbeResult;\n parsed?: JsonRpcEnvelope;\n parseError?: boolean;\n}\n\nasync function postRawMcpJsonRpc(options: {\n agentUrl: string;\n envelope: Record<string, unknown>;\n headers: Record<string, string>;\n allowPrivateIp: boolean;\n sessionId?: string;\n protocolVersion?: string;\n responseId?: number;\n parseBody?: boolean;\n allowEmptyBody?: boolean;\n}): Promise<RawJsonRpcPostResult> {\n const {\n agentUrl,\n envelope,\n headers,\n allowPrivateIp,\n sessionId,\n protocolVersion,\n responseId,\n parseBody = true,\n allowEmptyBody = false,\n } = options;\n const httpResult: HttpProbeResult = { url: agentUrl, status: 0, headers: {}, body: null };\n try {\n const res = await ssrfSafeFetch(agentUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n ...withoutMcpSessionHeaders(headers),\n ...(sessionId ? { [MCP_SESSION_ID_HEADER]: sessionId } : {}),\n ...(protocolVersion ? { [MCP_PROTOCOL_VERSION_HEADER]: protocolVersion } : {}),\n },\n body: JSON.stringify(envelope),\n allowPrivateIp,\n });\n httpResult.status = res.status;\n httpResult.headers = res.headers;\n\n const text = Buffer.from(res.body.buffer, res.body.byteOffset, res.body.byteLength).toString('utf8');\n if (!parseBody) {\n httpResult.body = text || null;\n return { httpResult };\n }\n if (allowEmptyBody && text.trim() === '') {\n httpResult.body = null;\n return { httpResult };\n }\n try {\n const parsed = parseMcpJsonRpcResponse(text, httpResult.headers['content-type'], responseId);\n httpResult.body = parsed;\n return { httpResult, parsed };\n } catch {\n httpResult.body = text;\n return { httpResult, parseError: true };\n }\n } catch (err) {\n httpResult.error = err instanceof Error ? err.message : String(err);\n return { httpResult };\n }\n}\n\nfunction withoutMcpSessionHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n const normalized = key.toLowerCase();\n if (normalized === MCP_SESSION_ID_HEADER || normalized === MCP_PROTOCOL_VERSION_HEADER) continue;\n cleaned[key] = value;\n }\n return cleaned;\n}\n\nfunction parseMcpJsonRpcResponse(text: string, contentType: string | undefined, responseId?: number): JsonRpcEnvelope {\n if (contentType?.toLowerCase().includes('text/event-stream')) {\n // Streamable-HTTP MCP: the response is one or more SSE events whose\n // `data:` payloads are JSON-RPC envelopes. The spec lets a server emit\n // notifications before the final response, so choose the matching id.\n const dataLines = text.split(/\\r?\\n/).filter(l => l.startsWith('data:'));\n if (dataLines.length === 0) throw new Error('SSE response with no data event');\n let matched: JsonRpcEnvelope | undefined;\n let lastParsed: JsonRpcEnvelope | undefined;\n for (const line of dataLines) {\n const payload = line.slice('data:'.length).trim();\n if (!payload) continue;\n try {\n const envelope = JSON.parse(payload) as JsonRpcEnvelope;\n lastParsed = envelope;\n if (responseId !== undefined && envelope?.id === responseId) {\n matched = envelope;\n break;\n }\n } catch {\n // Skip non-JSON data lines (heartbeats, etc.); keep walking.\n }\n }\n const parsed = matched ?? lastParsed;\n if (parsed === undefined) throw new Error('SSE response had data events but none were parseable JSON');\n return parsed;\n }\n return JSON.parse(text) as JsonRpcEnvelope;\n}\n\nfunction taskResultFromRpc(httpResult: HttpProbeResult, rpc: JsonRpcEnvelope): TaskResult {\n if (httpResult.status >= 400) {\n return {\n success: false,\n data: undefined,\n error: rpc.error?.message ?? `HTTP ${httpResult.status}`,\n _extraction_path: 'error',\n };\n }\n if (rpc.error) {\n const code = rpc.error.code;\n return {\n success: false,\n data: undefined,\n error:\n code !== undefined\n ? `JSON-RPC error ${code}: ${rpc.error.message ?? 'no message'}`\n : (rpc.error.message ?? 'JSON-RPC error (no code)'),\n _extraction_path: 'error',\n };\n }\n const structured = rpc.result?.structuredContent;\n const hasStructured = structured !== undefined && structured !== null;\n const data = hasStructured ? structured : rpc.result?.content;\n const isError = !!rpc.result?.isError;\n const extractionPath: 'structured_content' | 'text_fallback' | 'error' | 'none' = isError\n ? 'error'\n : hasStructured\n ? 'structured_content'\n : data !== undefined && data !== null\n ? 'text_fallback'\n : 'none';\n return { success: !isError, data, _extraction_path: extractionPath };\n}\n\nfunction failedTaskResult(message: string): TaskResult {\n return {\n success: false,\n data: undefined,\n error: message,\n _extraction_path: 'error',\n };\n}\n\nfunction taskResultFromPostFailure(posted: RawJsonRpcPostResult): TaskResult {\n if (posted.parseError) {\n return failedTaskResult(\n `Non-JSON response body (content-type: ${posted.httpResult.headers['content-type'] ?? 'unknown'}).`\n );\n }\n if (posted.parsed) return taskResultFromRpc(posted.httpResult, posted.parsed);\n return failedTaskResult(posted.httpResult.error ?? `HTTP ${posted.httpResult.status}`);\n}\n\n/**\n * POST a JSON-RPC `tools/call` request to the MCP endpoint with caller-provided\n * headers. The probe first performs the Streamable HTTP initialize handshake,\n * including `notifications/initialized`, so auth probes hit the same session\n * boundary as normal MCP clients while still exposing raw HTTP status and\n * `WWW-Authenticate` headers for security storyboards.\n *\n * **Args are not secret** — must not contain credentials or PII. The server's\n * response body lands in `httpResult.body` and is written to compliance\n * reports. Outbound request body is not persisted.\n *\n * Returns an HttpProbeResult plus a synthetic TaskResult for steps that also\n * want to validate body shape — the structuredContent is unwrapped so\n * `field_present: \"context\"` resolves naturally.\n */\nexport async function rawMcpProbe(options: {\n agentUrl: string;\n toolName: string;\n args: Record<string, unknown>;\n headers?: Record<string, string>;\n /** Allow http:// and private-IP agent URLs (dev loops). Default false. */\n allowPrivateIp?: boolean;\n}): Promise<{ httpResult: HttpProbeResult; taskResult?: TaskResult }> {\n const { agentUrl, toolName, args, headers = {}, allowPrivateIp = false } = options;\n const initializeId = ++probeRequestId;\n const initialize = await postRawMcpJsonRpc({\n agentUrl,\n envelope: {\n jsonrpc: '2.0',\n id: initializeId,\n method: 'initialize',\n params: {\n protocolVersion: LATEST_PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'AdCP Storyboard Raw MCP Probe', version: '1.0.0' },\n },\n },\n headers,\n allowPrivateIp,\n responseId: initializeId,\n });\n if (\n initialize.httpResult.error ||\n initialize.httpResult.status >= 400 ||\n !initialize.parsed ||\n initialize.parsed.error\n ) {\n return {\n httpResult: initialize.httpResult,\n taskResult: taskResultFromPostFailure(initialize),\n };\n }\n const negotiatedProtocolVersion = initialize.parsed.result?.protocolVersion;\n if (\n typeof negotiatedProtocolVersion !== 'string' ||\n !SUPPORTED_PROTOCOL_VERSIONS.includes(negotiatedProtocolVersion)\n ) {\n return {\n httpResult: initialize.httpResult,\n taskResult: failedTaskResult(\n negotiatedProtocolVersion\n ? `Server's protocol version is not supported: ${negotiatedProtocolVersion}`\n : 'Server sent invalid initialize result: missing protocolVersion'\n ),\n };\n }\n\n const sessionId = initialize.httpResult.headers[MCP_SESSION_ID_HEADER];\n const initialized = await postRawMcpJsonRpc({\n agentUrl,\n envelope: {\n jsonrpc: '2.0',\n method: 'notifications/initialized',\n params: {},\n },\n headers,\n allowPrivateIp,\n ...(sessionId && { sessionId }),\n protocolVersion: negotiatedProtocolVersion,\n allowEmptyBody: true,\n });\n if (\n initialized.httpResult.error ||\n initialized.httpResult.status >= 400 ||\n initialized.parseError ||\n initialized.parsed?.error\n ) {\n return {\n httpResult: initialized.httpResult,\n taskResult: taskResultFromPostFailure(initialized),\n };\n }\n\n const requestId = ++probeRequestId;\n const toolEnvelope = {\n jsonrpc: '2.0',\n id: requestId,\n method: 'tools/call',\n params: { name: toolName, arguments: args },\n };\n const posted = await postRawMcpJsonRpc({\n agentUrl,\n envelope: toolEnvelope,\n headers,\n allowPrivateIp,\n ...(sessionId && { sessionId }),\n protocolVersion: negotiatedProtocolVersion,\n responseId: requestId,\n });\n const { httpResult, parsed } = posted;\n if (httpResult.error) return { httpResult, taskResult: taskResultFromPostFailure(posted) };\n if (!parsed) {\n return {\n httpResult,\n taskResult: taskResultFromPostFailure(posted),\n };\n }\n return { httpResult, taskResult: taskResultFromRpc(httpResult, parsed) };\n}\n\n// ---------------------------------------------------------------------------\n// Raw-A2A probe (transport-layer diagnostics for A2A agents)\n// ---------------------------------------------------------------------------\n\n/**\n * POST a JSON-RPC 2.0 request to an A2A agent endpoint with caller-provided\n * headers. Bypasses the A2A SDK so raw HTTP status, headers, and JSON-RPC\n * error codes can be captured by storyboard diagnostics.\n *\n * Mirrors `rawMcpProbe` in structure and SSRF-safety contract. Key\n * differences from the MCP variant:\n *\n * - The caller supplies `method` + optional `params` (not a fixed `tools/call`\n * body). A2A has no single canonical method — use `\"message/send\"` for most\n * auth and error-code probes, `\"tasks/get\"` / `\"tasks/cancel\"` for lifecycle\n * checks. **Note:** `message/send` requires `params.message` (a full A2A\n * `Message` object with `messageId`, `role`, `kind`, `parts`). Passing\n * `params: {}` will produce `-32602 Invalid params` from a conformant server,\n * masking auth rejections — supply a minimal message when probing auth paths.\n * - A2A JSON-RPC error codes differ from MCP's. Notably `-32002` means\n * `TaskNotCancelable` in A2A (not session-not-initialized). The probe\n * surfaces raw numeric codes without protocol-specific aliasing so\n * storyboards can assert on the exact code.\n * - SSE (streaming) responses are handled the same way as `rawMcpProbe`:\n * `Accept: application/json` is sent; non-JSON bodies surface a distinct\n * error so callers don't mistake an event-stream for a silent success.\n *\n * **Args are not secret** — must not contain credentials or PII. The\n * server's response body lands in `httpResult.body` and is written to\n * compliance reports.\n *\n * Returns an `HttpProbeResult` plus an optional `TaskResult` (same shape as\n * `rawMcpProbe`) so the storyboard `ValidationContext` can consume both probes\n * interchangeably. The A2A success `_extraction_path` is `'text_fallback'`\n * (not `'structured_content'`) because A2A's `result` field is a plain object,\n * not an MCP structured-content envelope.\n */\nexport async function rawA2aProbe(options: {\n /** Base URL of the A2A agent endpoint (e.g. `https://agent.example.com/a2a`). */\n agentUrl: string;\n /** A2A/JSON-RPC 2.0 method name (e.g. `\"message/send\"`, `\"tasks/get\"`). */\n method: string;\n /** JSON-RPC params. Defaults to `{}` so the probe always emits a valid envelope. */\n params?: Record<string, unknown>;\n headers?: Record<string, string>;\n /** Allow http:// and private-IP agent URLs (dev loops). Default false. */\n allowPrivateIp?: boolean;\n}): Promise<{ httpResult: HttpProbeResult; taskResult?: TaskResult }> {\n const { agentUrl, method, params, headers = {}, allowPrivateIp = false } = options;\n const body = JSON.stringify({\n jsonrpc: '2.0',\n id: ++probeRequestId,\n method,\n params: params ?? {},\n });\n\n const httpResult: HttpProbeResult = { url: agentUrl, status: 0, headers: {}, body: null };\n try {\n const res = await ssrfSafeFetch(agentUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json',\n ...headers,\n },\n body,\n allowPrivateIp,\n });\n httpResult.status = res.status;\n httpResult.headers = res.headers;\n\n const text = Buffer.from(res.body.buffer, res.body.byteOffset, res.body.byteLength).toString('utf8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n httpResult.body = text;\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error: `Non-JSON response body (content-type: ${httpResult.headers['content-type'] ?? 'unknown'}).`,\n _extraction_path: 'error',\n },\n };\n }\n httpResult.body = parsed;\n\n const rpc = parsed as {\n result?: unknown;\n error?: { message?: string; code?: number };\n };\n\n if (httpResult.status >= 400) {\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error: rpc.error?.message ?? `HTTP ${httpResult.status}`,\n _extraction_path: 'error',\n },\n };\n }\n\n if (rpc.error) {\n const code = rpc.error.code;\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error:\n code !== undefined\n ? `JSON-RPC error ${code}: ${rpc.error.message ?? 'no message'}`\n : (rpc.error.message ?? 'JSON-RPC error (no code)'),\n _extraction_path: 'error',\n },\n };\n }\n\n const data = rpc.result;\n const extractionPath: 'text_fallback' | 'none' = data !== undefined && data !== null ? 'text_fallback' : 'none';\n return { httpResult, taskResult: { success: true, data, _extraction_path: extractionPath } };\n } catch (err) {\n httpResult.error = err instanceof Error ? err.message : String(err);\n return { httpResult };\n }\n}\n\n// IP classifiers live in `src/lib/net/address-guards.ts` so the SSRF-safe\n// fetch primitive can use them without depending on the testing module.\n// Re-exported here for existing import sites (storyboard-security test + any\n// external probe consumers).\nexport const isAlwaysBlocked = sharedIsAlwaysBlocked;\nexport const isPrivateIp = sharedIsPrivateIp;\nexport { SsrfRefusedError };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/lib/testing/storyboard/probes.ts"],"sourcesContent":["/**\n * HTTP probes used by security-baseline storyboard tasks.\n *\n * Three synthetic tasks dispatch through here instead of the MCP client:\n *\n * - `protected_resource_metadata` — GET the agent's\n * `/.well-known/oauth-protected-resource<mountPath>` and verify RFC 9728.\n * - `oauth_auth_server_metadata` — GET `<issuer>/.well-known/oauth-authorization-server`\n * using the first issuer from the previous step's response. Hardened against\n * SSRF because the URL comes from agent-controlled data.\n * - `assert_contribution` — no network; evaluates accumulated flags set by\n * prior steps that carried `contributes_to`.\n */\nimport { randomBytes } from 'crypto';\nimport { LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS } from '@modelcontextprotocol/sdk/types.js';\nimport {\n ssrfSafeFetch,\n decodeBodyAsJsonOrText,\n SsrfRefusedError,\n isAlwaysBlocked as sharedIsAlwaysBlocked,\n isPrivateIp as sharedIsPrivateIp,\n} from '../../net';\nimport type { HttpProbeResult } from './types';\nimport type { TaskResult } from '../types';\n\n// Timeout + body-cap defaults come from `ssrfSafeFetch` (10 s, 64 KiB).\n// The probe wrappers deliberately don't override them so probe behavior\n// stays in sync with the shared primitive.\n\n/** Task names dispatched via HTTP probes (not via the MCP client). */\nexport const PROBE_TASKS = new Set([\n 'protected_resource_metadata',\n 'oauth_auth_server_metadata',\n 'assert_contribution',\n 'request_signing_probe',\n 'fetch_brand_jwks',\n 'assert_jwks_purpose',\n 'expect_rate_limit_not_replayed',\n]);\n\n// ---------------------------------------------------------------------------\n// Protected-resource metadata probe\n// ---------------------------------------------------------------------------\n\n/**\n * GET `<agentUrl origin>/.well-known/oauth-protected-resource<agentUrl path>`.\n * Same-origin as the agent, so SSRF risk is bounded.\n *\n * When `allowPrivateIp` is set (matches the runner's `--allow-http` flag),\n * loopback and RFC 1918 targets are allowed so dev loops against localhost\n * agents work end-to-end.\n */\nexport async function probeProtectedResourceMetadata(\n agentUrl: string,\n options: { allowPrivateIp?: boolean } = {}\n): Promise<HttpProbeResult> {\n const u = new URL(agentUrl);\n const metadataUrl = `${u.origin}/.well-known/oauth-protected-resource${u.pathname}`;\n return fetchProbe(metadataUrl, { allowPrivateIp: options.allowPrivateIp ?? false });\n}\n\n// ---------------------------------------------------------------------------\n// OAuth authorization-server metadata probe\n// ---------------------------------------------------------------------------\n\n/**\n * GET `<issuer>/.well-known/oauth-authorization-server` for the first issuer\n * named in the protected-resource metadata. Because the URL is agent-supplied,\n * this is the SSRF-hot path — {@link fetchProbe} rejects private networks,\n * non-https schemes, and unbounded responses.\n */\nexport async function probeOauthAuthServerMetadata(\n priorProbe: HttpProbeResult | undefined,\n options: { allowPrivateIp?: boolean } = {}\n): Promise<HttpProbeResult> {\n if (!priorProbe || priorProbe.error) {\n return {\n url: '',\n status: 0,\n headers: {},\n body: null,\n error: 'protected_resource_metadata step missing or errored — cannot resolve issuer',\n };\n }\n const body = priorProbe.body as { authorization_servers?: unknown } | null;\n const servers = Array.isArray(body?.authorization_servers) ? (body!.authorization_servers as string[]) : [];\n if (servers.length === 0 || typeof servers[0] !== 'string') {\n return {\n url: '',\n status: 0,\n headers: {},\n body: null,\n error: 'No authorization_servers[0] found in protected-resource metadata',\n };\n }\n const issuer = servers[0].replace(/\\/$/, '');\n const metadataUrl = `${issuer}/.well-known/oauth-authorization-server`;\n return fetchProbe(metadataUrl, { allowPrivateIp: options.allowPrivateIp ?? false });\n}\n\n// ---------------------------------------------------------------------------\n// Fetch with guardrails\n// ---------------------------------------------------------------------------\n\nexport interface FetchProbeOptions {\n /** Allow http:// and private-IP destinations. Default false. */\n allowPrivateIp?: boolean;\n /** Override timeout for specific call sites. */\n timeoutMs?: number;\n}\n\n/**\n * Perform a GET against an attacker-influenceable URL with defensive limits.\n *\n * Guardrails (RFC 9728 / RFC 8414 metadata endpoints typically live on public\n * HTTPS; anything else is suspicious):\n * - Scheme: `https:` only by default; `http:` allowed only when\n * `allowPrivateIp` is set. `file:`, `ftp:`, `data:`, etc. are always rejected.\n * - DNS: resolves all A/AAAA records once, rejects if any is private, then\n * pins the outbound connection to the validated IP. Defeats DNS rebinding\n * where an attacker's authoritative nameserver returns a public address\n * to our guard lookup and a private address to the connect-time lookup.\n * - Private-IP block applies RFC 1918, loopback, link-local, IPv6 ULA,\n * CGNAT (100.64/10), multicast, broadcast, and IPv4-mapped IPv6.\n * - IMDS (169.254.169.254 / fe80::) stays blocked **even under\n * `allowPrivateIp`** — no legitimate dev use for probing it.\n * - Redirects are NOT followed (`redirect: 'manual'`).\n * - Body capped at 64 KiB, total fetch time capped at 10 s.\n */\nexport async function fetchProbe(url: string, options: FetchProbeOptions = {}): Promise<HttpProbeResult> {\n try {\n const res = await ssrfSafeFetch(url, {\n method: 'GET',\n headers: { accept: 'application/json' },\n allowPrivateIp: options.allowPrivateIp ?? false,\n ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),\n });\n return {\n url,\n status: res.status,\n headers: res.headers,\n body: decodeBodyAsJsonOrText(res.body, res.headers['content-type']),\n };\n } catch (err) {\n return {\n url,\n status: 0,\n headers: {},\n body: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Credential generators (value_strategy)\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a per-run bogus API key. Prefix is human-readable for log grep;\n * the 32 random hex bytes guarantee no allowlist collision.\n */\nexport function generateRandomInvalidApiKey(): string {\n return `invalid-${randomBytes(32).toString('hex')}`;\n}\n\n/**\n * Generate a per-run bogus JWT-shaped Bearer token. Emits three segments with\n * valid base64url-encoded JSON header/payload and a random signature — so\n * well-implemented validators fail at signature verification (→ 401), and\n * strict parse-time validators that reject at the structural level also fail\n * cleanly (→ 400 per RFC 6750 §3.1). Either is conformant.\n */\nexport function generateRandomInvalidJwt(): string {\n const header = base64url(Buffer.from(JSON.stringify({ alg: 'RS256', typ: 'JWT' })));\n const payload = base64url(\n Buffer.from(JSON.stringify({ sub: `invalid-${randomBytes(8).toString('hex')}`, aud: 'invalid-probe' }))\n );\n const signature = base64url(randomBytes(32));\n return `${header}.${payload}.${signature}`;\n}\n\nfunction base64url(buf: Buffer): string {\n return buf.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n// ---------------------------------------------------------------------------\n// Raw-MCP probe (auth-override dispatch)\n// ---------------------------------------------------------------------------\n\nlet probeRequestId = 0;\nconst MCP_SESSION_ID_HEADER = 'mcp-session-id';\nconst MCP_PROTOCOL_VERSION_HEADER = 'mcp-protocol-version';\n\ntype JsonRpcEnvelope = {\n jsonrpc: '2.0';\n id?: number;\n method?: string;\n params?: Record<string, unknown>;\n result?: { structuredContent?: unknown; content?: unknown; isError?: boolean; protocolVersion?: string };\n error?: { message?: string; code?: number };\n};\n\ninterface RawJsonRpcPostResult {\n httpResult: HttpProbeResult;\n parsed?: JsonRpcEnvelope;\n parseError?: boolean;\n}\n\nasync function postRawMcpJsonRpc(options: {\n agentUrl: string;\n envelope: Record<string, unknown>;\n headers: Record<string, string>;\n allowPrivateIp: boolean;\n sessionId?: string;\n protocolVersion?: string;\n responseId?: number;\n parseBody?: boolean;\n allowEmptyBody?: boolean;\n}): Promise<RawJsonRpcPostResult> {\n const {\n agentUrl,\n envelope,\n headers,\n allowPrivateIp,\n sessionId,\n protocolVersion,\n responseId,\n parseBody = true,\n allowEmptyBody = false,\n } = options;\n const httpResult: HttpProbeResult = { url: agentUrl, status: 0, headers: {}, body: null };\n try {\n const res = await ssrfSafeFetch(agentUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n ...withoutMcpSessionHeaders(headers),\n ...(sessionId ? { [MCP_SESSION_ID_HEADER]: sessionId } : {}),\n ...(protocolVersion ? { [MCP_PROTOCOL_VERSION_HEADER]: protocolVersion } : {}),\n },\n body: JSON.stringify(envelope),\n allowPrivateIp,\n });\n httpResult.status = res.status;\n httpResult.headers = res.headers;\n\n const text = Buffer.from(res.body.buffer, res.body.byteOffset, res.body.byteLength).toString('utf8');\n if (!parseBody) {\n httpResult.body = text || null;\n return { httpResult };\n }\n if (allowEmptyBody && text.trim() === '') {\n httpResult.body = null;\n return { httpResult };\n }\n try {\n const parsed = parseMcpJsonRpcResponse(text, httpResult.headers['content-type'], responseId);\n httpResult.body = parsed;\n return { httpResult, parsed };\n } catch {\n httpResult.body = text;\n return { httpResult, parseError: true };\n }\n } catch (err) {\n httpResult.error = err instanceof Error ? err.message : String(err);\n return { httpResult };\n }\n}\n\nfunction withoutMcpSessionHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n const normalized = key.toLowerCase();\n if (normalized === MCP_SESSION_ID_HEADER || normalized === MCP_PROTOCOL_VERSION_HEADER) continue;\n cleaned[key] = value;\n }\n return cleaned;\n}\n\nfunction parseMcpJsonRpcResponse(text: string, contentType: string | undefined, responseId?: number): JsonRpcEnvelope {\n if (contentType?.toLowerCase().includes('text/event-stream')) {\n // Streamable-HTTP MCP: the response is one or more SSE events whose\n // `data:` payloads are JSON-RPC envelopes. The spec lets a server emit\n // notifications before the final response, so choose the matching id.\n const dataLines = text.split(/\\r?\\n/).filter(l => l.startsWith('data:'));\n if (dataLines.length === 0) throw new Error('SSE response with no data event');\n let matched: JsonRpcEnvelope | undefined;\n let lastParsed: JsonRpcEnvelope | undefined;\n for (const line of dataLines) {\n const payload = line.slice('data:'.length).trim();\n if (!payload) continue;\n try {\n const envelope = JSON.parse(payload) as JsonRpcEnvelope;\n lastParsed = envelope;\n if (responseId !== undefined && envelope?.id === responseId) {\n matched = envelope;\n break;\n }\n } catch {\n // Skip non-JSON data lines (heartbeats, etc.); keep walking.\n }\n }\n const parsed = matched ?? lastParsed;\n if (parsed === undefined) throw new Error('SSE response had data events but none were parseable JSON');\n return parsed;\n }\n return JSON.parse(text) as JsonRpcEnvelope;\n}\n\nfunction taskResultFromRpc(httpResult: HttpProbeResult, rpc: JsonRpcEnvelope): TaskResult {\n if (httpResult.status >= 400) {\n return {\n success: false,\n data: undefined,\n error: rpc.error?.message ?? `HTTP ${httpResult.status}`,\n _extraction_path: 'error',\n };\n }\n if (rpc.error) {\n const code = rpc.error.code;\n return {\n success: false,\n data: undefined,\n error:\n code !== undefined\n ? `JSON-RPC error ${code}: ${rpc.error.message ?? 'no message'}`\n : (rpc.error.message ?? 'JSON-RPC error (no code)'),\n _extraction_path: 'error',\n };\n }\n const structured = rpc.result?.structuredContent;\n const hasStructured = structured !== undefined && structured !== null;\n const data = hasStructured ? structured : rpc.result?.content;\n const isError = !!rpc.result?.isError;\n const extractionPath: 'structured_content' | 'text_fallback' | 'error' | 'none' = isError\n ? 'error'\n : hasStructured\n ? 'structured_content'\n : data !== undefined && data !== null\n ? 'text_fallback'\n : 'none';\n return { success: !isError, data, _extraction_path: extractionPath };\n}\n\nfunction failedTaskResult(message: string): TaskResult {\n return {\n success: false,\n data: undefined,\n error: message,\n _extraction_path: 'error',\n };\n}\n\nfunction taskResultFromPostFailure(posted: RawJsonRpcPostResult): TaskResult {\n if (posted.parseError) {\n return failedTaskResult(\n `Non-JSON response body (content-type: ${posted.httpResult.headers['content-type'] ?? 'unknown'}).`\n );\n }\n if (posted.parsed) return taskResultFromRpc(posted.httpResult, posted.parsed);\n return failedTaskResult(posted.httpResult.error ?? `HTTP ${posted.httpResult.status}`);\n}\n\n/**\n * POST a JSON-RPC `tools/call` request to the MCP endpoint with caller-provided\n * headers. The probe first performs the Streamable HTTP initialize handshake,\n * including `notifications/initialized`, so auth probes hit the same session\n * boundary as normal MCP clients while still exposing raw HTTP status and\n * `WWW-Authenticate` headers for security storyboards.\n *\n * **Args are not secret** — must not contain credentials or PII. The server's\n * response body lands in `httpResult.body` and is written to compliance\n * reports. Outbound request body is not persisted.\n *\n * Returns an HttpProbeResult plus a synthetic TaskResult for steps that also\n * want to validate body shape — the structuredContent is unwrapped so\n * `field_present: \"context\"` resolves naturally.\n */\nexport async function rawMcpProbe(options: {\n agentUrl: string;\n toolName: string;\n args: Record<string, unknown>;\n headers?: Record<string, string>;\n /** Allow http:// and private-IP agent URLs (dev loops). Default false. */\n allowPrivateIp?: boolean;\n}): Promise<{ httpResult: HttpProbeResult; taskResult?: TaskResult }> {\n const { agentUrl, toolName, args, headers = {}, allowPrivateIp = false } = options;\n const initializeId = ++probeRequestId;\n const initialize = await postRawMcpJsonRpc({\n agentUrl,\n envelope: {\n jsonrpc: '2.0',\n id: initializeId,\n method: 'initialize',\n params: {\n protocolVersion: LATEST_PROTOCOL_VERSION,\n capabilities: {},\n clientInfo: { name: 'AdCP Storyboard Raw MCP Probe', version: '1.0.0' },\n },\n },\n headers,\n allowPrivateIp,\n responseId: initializeId,\n });\n if (\n initialize.httpResult.error ||\n initialize.httpResult.status >= 400 ||\n !initialize.parsed ||\n initialize.parsed.error\n ) {\n return {\n httpResult: initialize.httpResult,\n taskResult: taskResultFromPostFailure(initialize),\n };\n }\n const negotiatedProtocolVersion = initialize.parsed.result?.protocolVersion;\n if (\n typeof negotiatedProtocolVersion !== 'string' ||\n !SUPPORTED_PROTOCOL_VERSIONS.includes(negotiatedProtocolVersion)\n ) {\n return {\n httpResult: initialize.httpResult,\n taskResult: failedTaskResult(\n negotiatedProtocolVersion\n ? `Server's protocol version is not supported: ${negotiatedProtocolVersion}`\n : 'Server sent invalid initialize result: missing protocolVersion'\n ),\n };\n }\n\n const sessionId = initialize.httpResult.headers[MCP_SESSION_ID_HEADER];\n const initialized = await postRawMcpJsonRpc({\n agentUrl,\n envelope: {\n jsonrpc: '2.0',\n method: 'notifications/initialized',\n params: {},\n },\n headers,\n allowPrivateIp,\n ...(sessionId && { sessionId }),\n protocolVersion: negotiatedProtocolVersion,\n allowEmptyBody: true,\n });\n if (\n initialized.httpResult.error ||\n initialized.httpResult.status >= 400 ||\n initialized.parseError ||\n initialized.parsed?.error\n ) {\n return {\n httpResult: initialized.httpResult,\n taskResult: taskResultFromPostFailure(initialized),\n };\n }\n\n const requestId = ++probeRequestId;\n const toolEnvelope = {\n jsonrpc: '2.0',\n id: requestId,\n method: 'tools/call',\n params: { name: toolName, arguments: args },\n };\n const posted = await postRawMcpJsonRpc({\n agentUrl,\n envelope: toolEnvelope,\n headers,\n allowPrivateIp,\n ...(sessionId && { sessionId }),\n protocolVersion: negotiatedProtocolVersion,\n responseId: requestId,\n });\n const { httpResult, parsed } = posted;\n if (httpResult.error) return { httpResult, taskResult: taskResultFromPostFailure(posted) };\n if (!parsed) {\n return {\n httpResult,\n taskResult: taskResultFromPostFailure(posted),\n };\n }\n return { httpResult, taskResult: taskResultFromRpc(httpResult, parsed) };\n}\n\n// ---------------------------------------------------------------------------\n// Raw-A2A probe (transport-layer diagnostics for A2A agents)\n// ---------------------------------------------------------------------------\n\n/**\n * POST a JSON-RPC 2.0 request to an A2A agent endpoint with caller-provided\n * headers. Bypasses the A2A SDK so raw HTTP status, headers, and JSON-RPC\n * error codes can be captured by storyboard diagnostics.\n *\n * Mirrors `rawMcpProbe` in structure and SSRF-safety contract. Key\n * differences from the MCP variant:\n *\n * - The caller supplies `method` + optional `params` (not a fixed `tools/call`\n * body). A2A has no single canonical method — use `\"message/send\"` for most\n * auth and error-code probes, `\"tasks/get\"` / `\"tasks/cancel\"` for lifecycle\n * checks. **Note:** `message/send` requires `params.message` (a full A2A\n * `Message` object with `messageId`, `role`, `kind`, `parts`). Passing\n * `params: {}` will produce `-32602 Invalid params` from a conformant server,\n * masking auth rejections — supply a minimal message when probing auth paths.\n * - A2A JSON-RPC error codes differ from MCP's. Notably `-32002` means\n * `TaskNotCancelable` in A2A (not session-not-initialized). The probe\n * surfaces raw numeric codes without protocol-specific aliasing so\n * storyboards can assert on the exact code.\n * - SSE (streaming) responses are handled the same way as `rawMcpProbe`:\n * `Accept: application/json` is sent; non-JSON bodies surface a distinct\n * error so callers don't mistake an event-stream for a silent success.\n *\n * **Args are not secret** — must not contain credentials or PII. The\n * server's response body lands in `httpResult.body` and is written to\n * compliance reports.\n *\n * Returns an `HttpProbeResult` plus an optional `TaskResult` (same shape as\n * `rawMcpProbe`) so the storyboard `ValidationContext` can consume both probes\n * interchangeably. The A2A success `_extraction_path` is `'text_fallback'`\n * (not `'structured_content'`) because A2A's `result` field is a plain object,\n * not an MCP structured-content envelope.\n */\nexport async function rawA2aProbe(options: {\n /** Base URL of the A2A agent endpoint (e.g. `https://agent.example.com/a2a`). */\n agentUrl: string;\n /** A2A/JSON-RPC 2.0 method name (e.g. `\"message/send\"`, `\"tasks/get\"`). */\n method: string;\n /** JSON-RPC params. Defaults to `{}` so the probe always emits a valid envelope. */\n params?: Record<string, unknown>;\n headers?: Record<string, string>;\n /** Allow http:// and private-IP agent URLs (dev loops). Default false. */\n allowPrivateIp?: boolean;\n}): Promise<{ httpResult: HttpProbeResult; taskResult?: TaskResult }> {\n const { agentUrl, method, params, headers = {}, allowPrivateIp = false } = options;\n const body = JSON.stringify({\n jsonrpc: '2.0',\n id: ++probeRequestId,\n method,\n params: params ?? {},\n });\n\n const httpResult: HttpProbeResult = { url: agentUrl, status: 0, headers: {}, body: null };\n try {\n const res = await ssrfSafeFetch(agentUrl, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json',\n ...headers,\n },\n body,\n allowPrivateIp,\n });\n httpResult.status = res.status;\n httpResult.headers = res.headers;\n\n const text = Buffer.from(res.body.buffer, res.body.byteOffset, res.body.byteLength).toString('utf8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n httpResult.body = text;\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error: `Non-JSON response body (content-type: ${httpResult.headers['content-type'] ?? 'unknown'}).`,\n _extraction_path: 'error',\n },\n };\n }\n httpResult.body = parsed;\n\n const rpc = parsed as {\n result?: unknown;\n error?: { message?: string; code?: number };\n };\n\n if (httpResult.status >= 400) {\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error: rpc.error?.message ?? `HTTP ${httpResult.status}`,\n _extraction_path: 'error',\n },\n };\n }\n\n if (rpc.error) {\n const code = rpc.error.code;\n return {\n httpResult,\n taskResult: {\n success: false,\n data: undefined,\n error:\n code !== undefined\n ? `JSON-RPC error ${code}: ${rpc.error.message ?? 'no message'}`\n : (rpc.error.message ?? 'JSON-RPC error (no code)'),\n _extraction_path: 'error',\n },\n };\n }\n\n const data = rpc.result;\n const extractionPath: 'text_fallback' | 'none' = data !== undefined && data !== null ? 'text_fallback' : 'none';\n return { httpResult, taskResult: { success: true, data, _extraction_path: extractionPath } };\n } catch (err) {\n httpResult.error = err instanceof Error ? err.message : String(err);\n return { httpResult };\n }\n}\n\n// IP classifiers live in `src/lib/net/address-guards.ts` so the SSRF-safe\n// fetch primitive can use them without depending on the testing module.\n// Re-exported here for existing import sites (storyboard-security test + any\n// external probe consumers).\nexport const isAlwaysBlocked = sharedIsAlwaysBlocked;\nexport const isPrivateIp = sharedIsPrivateIp;\nexport { SsrfRefusedError };\n"],"mappings":"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","names":[]}
@@ -1,9 +1,3 @@
1
- import { fileURLToPath as __adcpFileURLToPath } from 'node:url';
2
- import { dirname as __adcpDirname } from 'node:path';
3
- import { createRequire as __adcpCreateRequire } from 'node:module';
4
- const __filename = __adcpFileURLToPath(import.meta.url);
5
- const __dirname = __adcpDirname(__filename);
6
- const require = __adcpCreateRequire(import.meta.url);
7
1
  import { randomUUID } from "node:crypto";
8
2
  import { ADCPError, ProtocolError, ResponseTooLargeError, TaskTimeoutError } from "../../errors/index.mjs";
9
3
  import { extractAdcpErrorInfo } from "../../utils/error-extraction.mjs";