@adcp/sdk 12.0.0 → 12.0.1

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 (942) 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.mjs +0 -6
  174. package/dist/lib/index.mjs.map +1 -1
  175. package/dist/lib/media-buy/available-actions.mjs +0 -6
  176. package/dist/lib/media-buy/available-actions.mjs.map +1 -1
  177. package/dist/lib/media-buy/index.mjs +0 -6
  178. package/dist/lib/media-buy/index.mjs.map +1 -1
  179. package/dist/lib/media-buy/preflight.mjs +0 -6
  180. package/dist/lib/media-buy/preflight.mjs.map +1 -1
  181. package/dist/lib/media-buy/property-policy.mjs +0 -6
  182. package/dist/lib/media-buy/property-policy.mjs.map +1 -1
  183. package/dist/lib/media-buy/types.mjs +0 -6
  184. package/dist/lib/media-buy/types.mjs.map +1 -1
  185. package/dist/lib/media-buy/update-fields.generated.mjs +0 -6
  186. package/dist/lib/media-buy/update-fields.generated.mjs.map +1 -1
  187. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs +0 -6
  188. package/dist/lib/mock-server/creative-ad-server/seed-data.mjs.map +1 -1
  189. package/dist/lib/mock-server/creative-ad-server/server.mjs +0 -6
  190. package/dist/lib/mock-server/creative-ad-server/server.mjs.map +1 -1
  191. package/dist/lib/mock-server/creative-template/seed-data.mjs +0 -6
  192. package/dist/lib/mock-server/creative-template/seed-data.mjs.map +1 -1
  193. package/dist/lib/mock-server/creative-template/server.mjs +0 -6
  194. package/dist/lib/mock-server/creative-template/server.mjs.map +1 -1
  195. package/dist/lib/mock-server/index.mjs +0 -6
  196. package/dist/lib/mock-server/index.mjs.map +1 -1
  197. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs +0 -6
  198. package/dist/lib/mock-server/sales-guaranteed/recipe.mjs.map +1 -1
  199. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs +0 -6
  200. package/dist/lib/mock-server/sales-guaranteed/seed-data.mjs.map +1 -1
  201. package/dist/lib/mock-server/sales-guaranteed/server.mjs +0 -6
  202. package/dist/lib/mock-server/sales-guaranteed/server.mjs.map +1 -1
  203. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs +0 -6
  204. package/dist/lib/mock-server/sales-non-guaranteed/recipe.mjs.map +1 -1
  205. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs +0 -6
  206. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.mjs.map +1 -1
  207. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs +0 -6
  208. package/dist/lib/mock-server/sales-non-guaranteed/server.mjs.map +1 -1
  209. package/dist/lib/mock-server/sales-social/seed-data.mjs +0 -6
  210. package/dist/lib/mock-server/sales-social/seed-data.mjs.map +1 -1
  211. package/dist/lib/mock-server/sales-social/server.mjs +0 -6
  212. package/dist/lib/mock-server/sales-social/server.mjs.map +1 -1
  213. package/dist/lib/mock-server/scenario.mjs +0 -6
  214. package/dist/lib/mock-server/scenario.mjs.map +1 -1
  215. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs +0 -6
  216. package/dist/lib/mock-server/signal-marketplace/seed-data.mjs.map +1 -1
  217. package/dist/lib/mock-server/signal-marketplace/server.mjs +0 -6
  218. package/dist/lib/mock-server/signal-marketplace/server.mjs.map +1 -1
  219. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs +0 -6
  220. package/dist/lib/mock-server/sponsored-intelligence/seed-data.mjs.map +1 -1
  221. package/dist/lib/mock-server/sponsored-intelligence/server.mjs +0 -6
  222. package/dist/lib/mock-server/sponsored-intelligence/server.mjs.map +1 -1
  223. package/dist/lib/net/address-guards.mjs +0 -6
  224. package/dist/lib/net/address-guards.mjs.map +1 -1
  225. package/dist/lib/net/index.mjs +0 -6
  226. package/dist/lib/net/index.mjs.map +1 -1
  227. package/dist/lib/net/ssrf-fetch.mjs +0 -6
  228. package/dist/lib/net/ssrf-fetch.mjs.map +1 -1
  229. package/dist/lib/observability/index.mjs +0 -6
  230. package/dist/lib/observability/index.mjs.map +1 -1
  231. package/dist/lib/observability/tracing.mjs +6 -7
  232. package/dist/lib/observability/tracing.mjs.map +1 -1
  233. package/dist/lib/protocols/a2a.mjs +0 -6
  234. package/dist/lib/protocols/a2a.mjs.map +1 -1
  235. package/dist/lib/protocols/abort.mjs +0 -6
  236. package/dist/lib/protocols/abort.mjs.map +1 -1
  237. package/dist/lib/protocols/index.mjs +0 -6
  238. package/dist/lib/protocols/index.mjs.map +1 -1
  239. package/dist/lib/protocols/mcp-modern.mjs +0 -6
  240. package/dist/lib/protocols/mcp-modern.mjs.map +1 -1
  241. package/dist/lib/protocols/mcp-tasks.mjs +0 -6
  242. package/dist/lib/protocols/mcp-tasks.mjs.map +1 -1
  243. package/dist/lib/protocols/mcp.mjs +0 -6
  244. package/dist/lib/protocols/mcp.mjs.map +1 -1
  245. package/dist/lib/protocols/rawResponseCapture.mjs +0 -6
  246. package/dist/lib/protocols/rawResponseCapture.mjs.map +1 -1
  247. package/dist/lib/protocols/responseSizeLimit.mjs +0 -6
  248. package/dist/lib/protocols/responseSizeLimit.mjs.map +1 -1
  249. package/dist/lib/protocols/transportDiagnostics.mjs +0 -6
  250. package/dist/lib/protocols/transportDiagnostics.mjs.map +1 -1
  251. package/dist/lib/registry/cursor-store.mjs +0 -6
  252. package/dist/lib/registry/cursor-store.mjs.map +1 -1
  253. package/dist/lib/registry/feed-stream.mjs +0 -6
  254. package/dist/lib/registry/feed-stream.mjs.map +1 -1
  255. package/dist/lib/registry/index.mjs +0 -6
  256. package/dist/lib/registry/index.mjs.map +1 -1
  257. package/dist/lib/registry/property-registry.mjs +0 -6
  258. package/dist/lib/registry/property-registry.mjs.map +1 -1
  259. package/dist/lib/registry/sync.mjs +0 -6
  260. package/dist/lib/registry/sync.mjs.map +1 -1
  261. package/dist/lib/registry/types.generated.mjs +0 -6
  262. package/dist/lib/registry/types.mjs +0 -6
  263. package/dist/lib/schemas/index.mjs +0 -6
  264. package/dist/lib/schemas/index.mjs.map +1 -1
  265. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  266. package/dist/lib/server/a2a-adapter.mjs +0 -6
  267. package/dist/lib/server/a2a-adapter.mjs.map +1 -1
  268. package/dist/lib/server/account-mode.mjs +0 -6
  269. package/dist/lib/server/account-mode.mjs.map +1 -1
  270. package/dist/lib/server/adcp-server.mjs +0 -6
  271. package/dist/lib/server/adcp-server.mjs.map +1 -1
  272. package/dist/lib/server/auth-introspection.mjs +0 -6
  273. package/dist/lib/server/auth-introspection.mjs.map +1 -1
  274. package/dist/lib/server/auth-signature.mjs +0 -6
  275. package/dist/lib/server/auth-signature.mjs.map +1 -1
  276. package/dist/lib/server/auth.mjs +0 -6
  277. package/dist/lib/server/auth.mjs.map +1 -1
  278. package/dist/lib/server/create-adcp-server.mjs +0 -6
  279. package/dist/lib/server/create-adcp-server.mjs.map +1 -1
  280. package/dist/lib/server/credential-policy.mjs +0 -6
  281. package/dist/lib/server/credential-policy.mjs.map +1 -1
  282. package/dist/lib/server/ctx-metadata/backends/memory.mjs +0 -6
  283. package/dist/lib/server/ctx-metadata/backends/memory.mjs.map +1 -1
  284. package/dist/lib/server/ctx-metadata/backends/pg.mjs +0 -6
  285. package/dist/lib/server/ctx-metadata/backends/pg.mjs.map +1 -1
  286. package/dist/lib/server/ctx-metadata/backends/redis.mjs +0 -6
  287. package/dist/lib/server/ctx-metadata/backends/redis.mjs.map +1 -1
  288. package/dist/lib/server/ctx-metadata/index.mjs +0 -6
  289. package/dist/lib/server/ctx-metadata/index.mjs.map +1 -1
  290. package/dist/lib/server/ctx-metadata/store.mjs +0 -6
  291. package/dist/lib/server/ctx-metadata/store.mjs.map +1 -1
  292. package/dist/lib/server/ctx-metadata/wire-shape.mjs +0 -6
  293. package/dist/lib/server/ctx-metadata/wire-shape.mjs.map +1 -1
  294. package/dist/lib/server/decisioning/account.mjs +0 -6
  295. package/dist/lib/server/decisioning/account.mjs.map +1 -1
  296. package/dist/lib/server/decisioning/admin-router.mjs +0 -6
  297. package/dist/lib/server/decisioning/admin-router.mjs.map +1 -1
  298. package/dist/lib/server/decisioning/assembly-helpers.mjs +0 -6
  299. package/dist/lib/server/decisioning/assembly-helpers.mjs.map +1 -1
  300. package/dist/lib/server/decisioning/async-outcome.mjs +0 -6
  301. package/dist/lib/server/decisioning/async-outcome.mjs.map +1 -1
  302. package/dist/lib/server/decisioning/buyer-agent.mjs +0 -6
  303. package/dist/lib/server/decisioning/buyer-agent.mjs.map +1 -1
  304. package/dist/lib/server/decisioning/capabilities.mjs +0 -6
  305. package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
  306. package/dist/lib/server/decisioning/compose.mjs +0 -6
  307. package/dist/lib/server/decisioning/compose.mjs.map +1 -1
  308. package/dist/lib/server/decisioning/context.mjs +0 -6
  309. package/dist/lib/server/decisioning/errors-typed.mjs +0 -6
  310. package/dist/lib/server/decisioning/errors-typed.mjs.map +1 -1
  311. package/dist/lib/server/decisioning/helpers.mjs +0 -6
  312. package/dist/lib/server/decisioning/helpers.mjs.map +1 -1
  313. package/dist/lib/server/decisioning/index.mjs +0 -6
  314. package/dist/lib/server/decisioning/index.mjs.map +1 -1
  315. package/dist/lib/server/decisioning/list-helpers.mjs +0 -6
  316. package/dist/lib/server/decisioning/list-helpers.mjs.map +1 -1
  317. package/dist/lib/server/decisioning/manifest-helpers.mjs +0 -6
  318. package/dist/lib/server/decisioning/manifest-helpers.mjs.map +1 -1
  319. package/dist/lib/server/decisioning/pagination.mjs +0 -6
  320. package/dist/lib/server/decisioning/platform-helpers.mjs +0 -6
  321. package/dist/lib/server/decisioning/platform-helpers.mjs.map +1 -1
  322. package/dist/lib/server/decisioning/platform.mjs +0 -6
  323. package/dist/lib/server/decisioning/proposal/dispatch.mjs +0 -6
  324. package/dist/lib/server/decisioning/proposal/dispatch.mjs.map +1 -1
  325. package/dist/lib/server/decisioning/proposal/index.mjs +0 -6
  326. package/dist/lib/server/decisioning/proposal/index.mjs.map +1 -1
  327. package/dist/lib/server/decisioning/proposal/lifecycle.mjs +0 -6
  328. package/dist/lib/server/decisioning/proposal/lifecycle.mjs.map +1 -1
  329. package/dist/lib/server/decisioning/proposal/mock-manager.mjs +0 -6
  330. package/dist/lib/server/decisioning/proposal/mock-manager.mjs.map +1 -1
  331. package/dist/lib/server/decisioning/proposal/store.mjs +0 -6
  332. package/dist/lib/server/decisioning/proposal/store.mjs.map +1 -1
  333. package/dist/lib/server/decisioning/proposal/types.mjs +0 -6
  334. package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
  335. package/dist/lib/server/decisioning/resolve-presets.mjs +0 -6
  336. package/dist/lib/server/decisioning/resolve-presets.mjs.map +1 -1
  337. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs +0 -6
  338. package/dist/lib/server/decisioning/runtime/entity-hydration.generated.mjs.map +1 -1
  339. package/dist/lib/server/decisioning/runtime/from-platform.mjs +0 -6
  340. package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
  341. package/dist/lib/server/decisioning/runtime/observed-modes.mjs +0 -6
  342. package/dist/lib/server/decisioning/runtime/observed-modes.mjs.map +1 -1
  343. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +0 -6
  344. package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
  345. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +0 -6
  346. package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs.map +1 -1
  347. package/dist/lib/server/decisioning/runtime/task-registry.mjs +0 -6
  348. package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
  349. package/dist/lib/server/decisioning/runtime/to-context.mjs +0 -6
  350. package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
  351. package/dist/lib/server/decisioning/runtime/validate-platform.mjs +0 -6
  352. package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
  353. package/dist/lib/server/decisioning/specialisms/audiences.mjs +0 -6
  354. package/dist/lib/server/decisioning/specialisms/brand-rights.mjs +0 -6
  355. package/dist/lib/server/decisioning/specialisms/campaign-governance.mjs +0 -6
  356. package/dist/lib/server/decisioning/specialisms/content-standards.mjs +0 -6
  357. package/dist/lib/server/decisioning/specialisms/creative-ad-server.mjs +0 -6
  358. package/dist/lib/server/decisioning/specialisms/creative.mjs +0 -6
  359. package/dist/lib/server/decisioning/specialisms/lists.mjs +0 -6
  360. package/dist/lib/server/decisioning/specialisms/sales.mjs +0 -6
  361. package/dist/lib/server/decisioning/specialisms/signals.mjs +0 -6
  362. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.mjs +0 -6
  363. package/dist/lib/server/decisioning/start-time.mjs +0 -6
  364. package/dist/lib/server/decisioning/start-time.mjs.map +1 -1
  365. package/dist/lib/server/decisioning/status-changes.mjs +0 -6
  366. package/dist/lib/server/decisioning/status-changes.mjs.map +1 -1
  367. package/dist/lib/server/decisioning/status-mappers.mjs +0 -6
  368. package/dist/lib/server/decisioning/status-mappers.mjs.map +1 -1
  369. package/dist/lib/server/decisioning/tenant-registry.mjs +0 -6
  370. package/dist/lib/server/decisioning/tenant-registry.mjs.map +1 -1
  371. package/dist/lib/server/decisioning/tenant-store.mjs +0 -6
  372. package/dist/lib/server/decisioning/tenant-store.mjs.map +1 -1
  373. package/dist/lib/server/decisioning/validate-specialisms.mjs +0 -6
  374. package/dist/lib/server/decisioning/validate-specialisms.mjs.map +1 -1
  375. package/dist/lib/server/dynamic-registry.mjs +0 -6
  376. package/dist/lib/server/dynamic-registry.mjs.map +1 -1
  377. package/dist/lib/server/envelope-allowlist.mjs +0 -6
  378. package/dist/lib/server/envelope-allowlist.mjs.map +1 -1
  379. package/dist/lib/server/error-arm-tools.mjs +5 -6
  380. package/dist/lib/server/error-arm-tools.mjs.map +1 -1
  381. package/dist/lib/server/errors.mjs +0 -6
  382. package/dist/lib/server/errors.mjs.map +1 -1
  383. package/dist/lib/server/example-tld-guard.mjs +0 -6
  384. package/dist/lib/server/example-tld-guard.mjs.map +1 -1
  385. package/dist/lib/server/express-adapter.mjs +0 -6
  386. package/dist/lib/server/express-adapter.mjs.map +1 -1
  387. package/dist/lib/server/governance.mjs +0 -6
  388. package/dist/lib/server/governance.mjs.map +1 -1
  389. package/dist/lib/server/idempotency/backends/lazy.mjs +0 -6
  390. package/dist/lib/server/idempotency/backends/lazy.mjs.map +1 -1
  391. package/dist/lib/server/idempotency/backends/memory.mjs +0 -6
  392. package/dist/lib/server/idempotency/backends/memory.mjs.map +1 -1
  393. package/dist/lib/server/idempotency/backends/pg.mjs +0 -6
  394. package/dist/lib/server/idempotency/backends/pg.mjs.map +1 -1
  395. package/dist/lib/server/idempotency/backends/redis.mjs +0 -6
  396. package/dist/lib/server/idempotency/backends/redis.mjs.map +1 -1
  397. package/dist/lib/server/idempotency/index.mjs +0 -6
  398. package/dist/lib/server/idempotency/index.mjs.map +1 -1
  399. package/dist/lib/server/idempotency/store.mjs +0 -6
  400. package/dist/lib/server/idempotency/store.mjs.map +1 -1
  401. package/dist/lib/server/index.mjs +0 -6
  402. package/dist/lib/server/index.mjs.map +1 -1
  403. package/dist/lib/server/legacy/v5/index.mjs +0 -6
  404. package/dist/lib/server/legacy/v5/index.mjs.map +1 -1
  405. package/dist/lib/server/mcp-modern-server.mjs +0 -6
  406. package/dist/lib/server/mcp-modern-server.mjs.map +1 -1
  407. package/dist/lib/server/media-buy-actions.mjs +0 -6
  408. package/dist/lib/server/media-buy-actions.mjs.map +1 -1
  409. package/dist/lib/server/media-buy-helpers.mjs +0 -6
  410. package/dist/lib/server/media-buy-helpers.mjs.map +1 -1
  411. package/dist/lib/server/media-buy-store.mjs +0 -6
  412. package/dist/lib/server/media-buy-store.mjs.map +1 -1
  413. package/dist/lib/server/normalize-errors.mjs +0 -6
  414. package/dist/lib/server/normalize-errors.mjs.map +1 -1
  415. package/dist/lib/server/operational-platform.mjs +0 -6
  416. package/dist/lib/server/operational-platform.mjs.map +1 -1
  417. package/dist/lib/server/pick-safe-details.mjs +0 -6
  418. package/dist/lib/server/pick-safe-details.mjs.map +1 -1
  419. package/dist/lib/server/pin-and-bind-fetch.mjs +0 -6
  420. package/dist/lib/server/pin-and-bind-fetch.mjs.map +1 -1
  421. package/dist/lib/server/postgres-state-store.mjs +0 -6
  422. package/dist/lib/server/postgres-state-store.mjs.map +1 -1
  423. package/dist/lib/server/postgres-task-store.mjs +0 -6
  424. package/dist/lib/server/postgres-task-store.mjs.map +1 -1
  425. package/dist/lib/server/product-defaults.mjs +0 -6
  426. package/dist/lib/server/product-defaults.mjs.map +1 -1
  427. package/dist/lib/server/redact.mjs +0 -6
  428. package/dist/lib/server/redact.mjs.map +1 -1
  429. package/dist/lib/server/responses.mjs +0 -6
  430. package/dist/lib/server/responses.mjs.map +1 -1
  431. package/dist/lib/server/serve.mjs +0 -6
  432. package/dist/lib/server/serve.mjs.map +1 -1
  433. package/dist/lib/server/socket-mode/conformance-client.mjs +0 -6
  434. package/dist/lib/server/socket-mode/conformance-client.mjs.map +1 -1
  435. package/dist/lib/server/socket-mode/index.mjs +0 -6
  436. package/dist/lib/server/socket-mode/index.mjs.map +1 -1
  437. package/dist/lib/server/socket-mode/ws-transport.mjs +0 -6
  438. package/dist/lib/server/socket-mode/ws-transport.mjs.map +1 -1
  439. package/dist/lib/server/state-machine.mjs +0 -6
  440. package/dist/lib/server/state-machine.mjs.map +1 -1
  441. package/dist/lib/server/state-store.mjs +0 -6
  442. package/dist/lib/server/state-store.mjs.map +1 -1
  443. package/dist/lib/server/structured-serialize.mjs +0 -6
  444. package/dist/lib/server/structured-serialize.mjs.map +1 -1
  445. package/dist/lib/server/targeting-helpers.mjs +0 -6
  446. package/dist/lib/server/targeting-helpers.mjs.map +1 -1
  447. package/dist/lib/server/tasks.mjs +0 -6
  448. package/dist/lib/server/tasks.mjs.map +1 -1
  449. package/dist/lib/server/test-controller-bridge.mjs +0 -6
  450. package/dist/lib/server/test-controller-bridge.mjs.map +1 -1
  451. package/dist/lib/server/test-controller.mjs +0 -6
  452. package/dist/lib/server/test-controller.mjs.map +1 -1
  453. package/dist/lib/server/upstream-helpers.mjs +0 -6
  454. package/dist/lib/server/upstream-helpers.mjs.map +1 -1
  455. package/dist/lib/server/webhook-emitter.mjs +0 -6
  456. package/dist/lib/server/webhook-emitter.mjs.map +1 -1
  457. package/dist/lib/server/wire-safe.mjs +0 -6
  458. package/dist/lib/server/wire-safe.mjs.map +1 -1
  459. package/dist/lib/server/wire-spec-fields.generated.mjs +0 -6
  460. package/dist/lib/server/wire-spec-fields.generated.mjs.map +1 -1
  461. package/dist/lib/server/wrap-envelope.mjs +0 -6
  462. package/dist/lib/server/wrap-envelope.mjs.map +1 -1
  463. package/dist/lib/signing/agent-context.mjs +0 -6
  464. package/dist/lib/signing/agent-context.mjs.map +1 -1
  465. package/dist/lib/signing/agent-fetch.mjs +0 -6
  466. package/dist/lib/signing/agent-fetch.mjs.map +1 -1
  467. package/dist/lib/signing/agent-resolver/canonicalize.mjs +0 -6
  468. package/dist/lib/signing/agent-resolver/canonicalize.mjs.map +1 -1
  469. package/dist/lib/signing/agent-resolver/capabilities-types.mjs +0 -6
  470. package/dist/lib/signing/agent-resolver/capabilities-types.mjs.map +1 -1
  471. package/dist/lib/signing/agent-resolver/consistency.mjs +0 -6
  472. package/dist/lib/signing/agent-resolver/consistency.mjs.map +1 -1
  473. package/dist/lib/signing/agent-resolver/errors.mjs +0 -6
  474. package/dist/lib/signing/agent-resolver/errors.mjs.map +1 -1
  475. package/dist/lib/signing/agent-resolver/etld.mjs +0 -6
  476. package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
  477. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +0 -6
  478. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs.map +1 -1
  479. package/dist/lib/signing/agent-resolver/index.mjs +0 -6
  480. package/dist/lib/signing/agent-resolver/index.mjs.map +1 -1
  481. package/dist/lib/signing/agent-resolver/jwks-set.mjs +0 -6
  482. package/dist/lib/signing/agent-resolver/jwks-set.mjs.map +1 -1
  483. package/dist/lib/signing/agent-resolver/resolve-agent.mjs +0 -6
  484. package/dist/lib/signing/agent-resolver/resolve-agent.mjs.map +1 -1
  485. package/dist/lib/signing/agent-resolver/select-agent.mjs +0 -6
  486. package/dist/lib/signing/agent-resolver/select-agent.mjs.map +1 -1
  487. package/dist/lib/signing/agent-resolver/strict-json.mjs +0 -6
  488. package/dist/lib/signing/agent-resolver/strict-json.mjs.map +1 -1
  489. package/dist/lib/signing/brand-jwks.mjs +0 -6
  490. package/dist/lib/signing/brand-jwks.mjs.map +1 -1
  491. package/dist/lib/signing/canonicalize.mjs +0 -6
  492. package/dist/lib/signing/canonicalize.mjs.map +1 -1
  493. package/dist/lib/signing/capability-cache.mjs +0 -6
  494. package/dist/lib/signing/capability-cache.mjs.map +1 -1
  495. package/dist/lib/signing/capability-priming.mjs +0 -6
  496. package/dist/lib/signing/capability-priming.mjs.map +1 -1
  497. package/dist/lib/signing/client.mjs +0 -6
  498. package/dist/lib/signing/client.mjs.map +1 -1
  499. package/dist/lib/signing/content-digest.mjs +0 -6
  500. package/dist/lib/signing/content-digest.mjs.map +1 -1
  501. package/dist/lib/signing/crypto.mjs +0 -6
  502. package/dist/lib/signing/crypto.mjs.map +1 -1
  503. package/dist/lib/signing/ecdsa-encoding.mjs +0 -6
  504. package/dist/lib/signing/ecdsa-encoding.mjs.map +1 -1
  505. package/dist/lib/signing/errors.mjs +0 -6
  506. package/dist/lib/signing/errors.mjs.map +1 -1
  507. package/dist/lib/signing/fetch-async.mjs +0 -6
  508. package/dist/lib/signing/fetch-async.mjs.map +1 -1
  509. package/dist/lib/signing/fetch.mjs +0 -6
  510. package/dist/lib/signing/fetch.mjs.map +1 -1
  511. package/dist/lib/signing/index.mjs +0 -6
  512. package/dist/lib/signing/index.mjs.map +1 -1
  513. package/dist/lib/signing/jwks-helpers.mjs +0 -6
  514. package/dist/lib/signing/jwks-helpers.mjs.map +1 -1
  515. package/dist/lib/signing/jwks-https.mjs +0 -6
  516. package/dist/lib/signing/jwks-https.mjs.map +1 -1
  517. package/dist/lib/signing/jwks.mjs +0 -6
  518. package/dist/lib/signing/jwks.mjs.map +1 -1
  519. package/dist/lib/signing/middleware.mjs +0 -6
  520. package/dist/lib/signing/middleware.mjs.map +1 -1
  521. package/dist/lib/signing/parser.mjs +0 -6
  522. package/dist/lib/signing/parser.mjs.map +1 -1
  523. package/dist/lib/signing/postgres-replay-store.mjs +0 -6
  524. package/dist/lib/signing/postgres-replay-store.mjs.map +1 -1
  525. package/dist/lib/signing/protocol-response.mjs +0 -6
  526. package/dist/lib/signing/protocol-response.mjs.map +1 -1
  527. package/dist/lib/signing/provider.mjs +0 -6
  528. package/dist/lib/signing/redis-replay-store.mjs +0 -6
  529. package/dist/lib/signing/redis-replay-store.mjs.map +1 -1
  530. package/dist/lib/signing/replay.mjs +0 -6
  531. package/dist/lib/signing/replay.mjs.map +1 -1
  532. package/dist/lib/signing/request-context.mjs +0 -6
  533. package/dist/lib/signing/request-context.mjs.map +1 -1
  534. package/dist/lib/signing/revocation-https.mjs +0 -6
  535. package/dist/lib/signing/revocation-https.mjs.map +1 -1
  536. package/dist/lib/signing/revocation.mjs +0 -6
  537. package/dist/lib/signing/revocation.mjs.map +1 -1
  538. package/dist/lib/signing/server.mjs +0 -6
  539. package/dist/lib/signing/server.mjs.map +1 -1
  540. package/dist/lib/signing/signer-async.mjs +0 -6
  541. package/dist/lib/signing/signer-async.mjs.map +1 -1
  542. package/dist/lib/signing/signer.mjs +0 -6
  543. package/dist/lib/signing/signer.mjs.map +1 -1
  544. package/dist/lib/signing/testing.mjs +0 -6
  545. package/dist/lib/signing/testing.mjs.map +1 -1
  546. package/dist/lib/signing/types.mjs +0 -6
  547. package/dist/lib/signing/types.mjs.map +1 -1
  548. package/dist/lib/signing/verifier.mjs +0 -6
  549. package/dist/lib/signing/verifier.mjs.map +1 -1
  550. package/dist/lib/signing/webhook-auth-detection.mjs +0 -6
  551. package/dist/lib/signing/webhook-auth-detection.mjs.map +1 -1
  552. package/dist/lib/signing/webhook-verifier.mjs +0 -6
  553. package/dist/lib/signing/webhook-verifier.mjs.map +1 -1
  554. package/dist/lib/storage/MemoryStorage.mjs +0 -6
  555. package/dist/lib/storage/MemoryStorage.mjs.map +1 -1
  556. package/dist/lib/storage/interfaces.mjs +0 -6
  557. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs +0 -6
  558. package/dist/lib/substitution/encoder/SubstitutionEncoder.mjs.map +1 -1
  559. package/dist/lib/substitution/encoder/index.mjs +0 -6
  560. package/dist/lib/substitution/encoder/index.mjs.map +1 -1
  561. package/dist/lib/substitution/index.mjs +0 -6
  562. package/dist/lib/substitution/index.mjs.map +1 -1
  563. package/dist/lib/substitution/observer/SubstitutionObserver.mjs +0 -6
  564. package/dist/lib/substitution/observer/SubstitutionObserver.mjs.map +1 -1
  565. package/dist/lib/substitution/observer/alignment.mjs +0 -6
  566. package/dist/lib/substitution/observer/alignment.mjs.map +1 -1
  567. package/dist/lib/substitution/observer/assertions.mjs +0 -6
  568. package/dist/lib/substitution/observer/assertions.mjs.map +1 -1
  569. package/dist/lib/substitution/observer/html-parser.mjs +0 -6
  570. package/dist/lib/substitution/observer/html-parser.mjs.map +1 -1
  571. package/dist/lib/substitution/observer/index.mjs +0 -6
  572. package/dist/lib/substitution/observer/index.mjs.map +1 -1
  573. package/dist/lib/substitution/observer/ssrf.mjs +0 -6
  574. package/dist/lib/substitution/observer/ssrf.mjs.map +1 -1
  575. package/dist/lib/substitution/rfc3986.mjs +0 -6
  576. package/dist/lib/substitution/rfc3986.mjs.map +1 -1
  577. package/dist/lib/substitution/translate.mjs +0 -6
  578. package/dist/lib/substitution/translate.mjs.map +1 -1
  579. package/dist/lib/substitution/types.mjs +0 -6
  580. package/dist/lib/substitution/vectors.mjs +0 -6
  581. package/dist/lib/substitution/vectors.mjs.map +1 -1
  582. package/dist/lib/testing/agent-tester.mjs +0 -6
  583. package/dist/lib/testing/agent-tester.mjs.map +1 -1
  584. package/dist/lib/testing/client.mjs +0 -6
  585. package/dist/lib/testing/client.mjs.map +1 -1
  586. package/dist/lib/testing/compliance/briefs.mjs +0 -6
  587. package/dist/lib/testing/compliance/briefs.mjs.map +1 -1
  588. package/dist/lib/testing/compliance/comply.mjs +0 -6
  589. package/dist/lib/testing/compliance/comply.mjs.map +1 -1
  590. package/dist/lib/testing/compliance/index.mjs +0 -6
  591. package/dist/lib/testing/compliance/index.mjs.map +1 -1
  592. package/dist/lib/testing/compliance/spec-conformance.mjs +0 -6
  593. package/dist/lib/testing/compliance/spec-conformance.mjs.map +1 -1
  594. package/dist/lib/testing/compliance/storyboard-tracks.mjs +0 -6
  595. package/dist/lib/testing/compliance/storyboard-tracks.mjs.map +1 -1
  596. package/dist/lib/testing/compliance/summary.mjs +0 -6
  597. package/dist/lib/testing/compliance/summary.mjs.map +1 -1
  598. package/dist/lib/testing/compliance/types.mjs +0 -6
  599. package/dist/lib/testing/comply-controller.mjs +0 -6
  600. package/dist/lib/testing/comply-controller.mjs.map +1 -1
  601. package/dist/lib/testing/controller-assertions.mjs +0 -6
  602. package/dist/lib/testing/controller-assertions.mjs.map +1 -1
  603. package/dist/lib/testing/formatter.mjs +0 -6
  604. package/dist/lib/testing/formatter.mjs.map +1 -1
  605. package/dist/lib/testing/index.mjs +0 -6
  606. package/dist/lib/testing/index.mjs.map +1 -1
  607. package/dist/lib/testing/local-agent-runner.mjs +0 -6
  608. package/dist/lib/testing/local-agent-runner.mjs.map +1 -1
  609. package/dist/lib/testing/orchestrator.mjs +0 -6
  610. package/dist/lib/testing/orchestrator.mjs.map +1 -1
  611. package/dist/lib/testing/personas/index.mjs +0 -6
  612. package/dist/lib/testing/personas/index.mjs.map +1 -1
  613. package/dist/lib/testing/scenarios/brand-rights.mjs +0 -6
  614. package/dist/lib/testing/scenarios/brand-rights.mjs.map +1 -1
  615. package/dist/lib/testing/scenarios/capabilities.mjs +0 -6
  616. package/dist/lib/testing/scenarios/capabilities.mjs.map +1 -1
  617. package/dist/lib/testing/scenarios/creative.mjs +0 -6
  618. package/dist/lib/testing/scenarios/creative.mjs.map +1 -1
  619. package/dist/lib/testing/scenarios/deterministic.mjs +0 -6
  620. package/dist/lib/testing/scenarios/deterministic.mjs.map +1 -1
  621. package/dist/lib/testing/scenarios/discovery.mjs +0 -6
  622. package/dist/lib/testing/scenarios/discovery.mjs.map +1 -1
  623. package/dist/lib/testing/scenarios/edge-cases.mjs +0 -6
  624. package/dist/lib/testing/scenarios/edge-cases.mjs.map +1 -1
  625. package/dist/lib/testing/scenarios/error-compliance.mjs +0 -6
  626. package/dist/lib/testing/scenarios/error-compliance.mjs.map +1 -1
  627. package/dist/lib/testing/scenarios/governance.mjs +0 -6
  628. package/dist/lib/testing/scenarios/governance.mjs.map +1 -1
  629. package/dist/lib/testing/scenarios/health.mjs +0 -6
  630. package/dist/lib/testing/scenarios/health.mjs.map +1 -1
  631. package/dist/lib/testing/scenarios/index.mjs +0 -6
  632. package/dist/lib/testing/scenarios/index.mjs.map +1 -1
  633. package/dist/lib/testing/scenarios/media-buy.mjs +0 -6
  634. package/dist/lib/testing/scenarios/media-buy.mjs.map +1 -1
  635. package/dist/lib/testing/scenarios/schema-compliance.mjs +0 -6
  636. package/dist/lib/testing/scenarios/schema-compliance.mjs.map +1 -1
  637. package/dist/lib/testing/scenarios/signals.mjs +0 -6
  638. package/dist/lib/testing/scenarios/signals.mjs.map +1 -1
  639. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs +0 -6
  640. package/dist/lib/testing/scenarios/sponsored-intelligence.mjs.map +1 -1
  641. package/dist/lib/testing/scenarios/trusted-match.mjs +0 -6
  642. package/dist/lib/testing/scenarios/trusted-match.mjs.map +1 -1
  643. package/dist/lib/testing/seed-merge.mjs +0 -6
  644. package/dist/lib/testing/seed-merge.mjs.map +1 -1
  645. package/dist/lib/testing/storyboard/agent-routing.mjs +0 -6
  646. package/dist/lib/testing/storyboard/agent-routing.mjs.map +1 -1
  647. package/dist/lib/testing/storyboard/assertions.mjs +0 -6
  648. package/dist/lib/testing/storyboard/assertions.mjs.map +1 -1
  649. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +0 -6
  650. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs.map +1 -1
  651. package/dist/lib/testing/storyboard/compliance.mjs +5 -6
  652. package/dist/lib/testing/storyboard/compliance.mjs.map +1 -1
  653. package/dist/lib/testing/storyboard/context.mjs +0 -6
  654. package/dist/lib/testing/storyboard/context.mjs.map +1 -1
  655. package/dist/lib/testing/storyboard/default-invariants.mjs +0 -6
  656. package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
  657. package/dist/lib/testing/storyboard/index.mjs +0 -6
  658. package/dist/lib/testing/storyboard/index.mjs.map +1 -1
  659. package/dist/lib/testing/storyboard/junit.mjs +0 -6
  660. package/dist/lib/testing/storyboard/junit.mjs.map +1 -1
  661. package/dist/lib/testing/storyboard/loader.mjs +0 -6
  662. package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
  663. package/dist/lib/testing/storyboard/parallel-dispatch.mjs +0 -6
  664. package/dist/lib/testing/storyboard/parallel-dispatch.mjs.map +1 -1
  665. package/dist/lib/testing/storyboard/path.mjs +0 -6
  666. package/dist/lib/testing/storyboard/path.mjs.map +1 -1
  667. package/dist/lib/testing/storyboard/probes.mjs +0 -6
  668. package/dist/lib/testing/storyboard/probes.mjs.map +1 -1
  669. package/dist/lib/testing/storyboard/rate-limit-trip.mjs +0 -6
  670. package/dist/lib/testing/storyboard/rate-limit-trip.mjs.map +1 -1
  671. package/dist/lib/testing/storyboard/rejection-hints.mjs +0 -6
  672. package/dist/lib/testing/storyboard/rejection-hints.mjs.map +1 -1
  673. package/dist/lib/testing/storyboard/request-builder.mjs +0 -6
  674. package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
  675. package/dist/lib/testing/storyboard/request-signing/builder.mjs +0 -6
  676. package/dist/lib/testing/storyboard/request-signing/builder.mjs.map +1 -1
  677. package/dist/lib/testing/storyboard/request-signing/grader.mjs +0 -6
  678. package/dist/lib/testing/storyboard/request-signing/grader.mjs.map +1 -1
  679. package/dist/lib/testing/storyboard/request-signing/index.mjs +0 -6
  680. package/dist/lib/testing/storyboard/request-signing/index.mjs.map +1 -1
  681. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs +0 -6
  682. package/dist/lib/testing/storyboard/request-signing/probe-dispatch.mjs.map +1 -1
  683. package/dist/lib/testing/storyboard/request-signing/probe.mjs +0 -6
  684. package/dist/lib/testing/storyboard/request-signing/probe.mjs.map +1 -1
  685. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs +0 -6
  686. package/dist/lib/testing/storyboard/request-signing/synthesize.mjs.map +1 -1
  687. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +0 -6
  688. package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
  689. package/dist/lib/testing/storyboard/request-signing/types.mjs +0 -6
  690. package/dist/lib/testing/storyboard/request-signing/types.mjs.map +1 -1
  691. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +0 -6
  692. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
  693. package/dist/lib/testing/storyboard/runner.mjs +0 -6
  694. package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
  695. package/dist/lib/testing/storyboard/sandbox-entities.mjs +0 -6
  696. package/dist/lib/testing/storyboard/sandbox-entities.mjs.map +1 -1
  697. package/dist/lib/testing/storyboard/seeding.mjs +0 -6
  698. package/dist/lib/testing/storyboard/seeding.mjs.map +1 -1
  699. package/dist/lib/testing/storyboard/shape-drift-hints.mjs +0 -6
  700. package/dist/lib/testing/storyboard/shape-drift-hints.mjs.map +1 -1
  701. package/dist/lib/testing/storyboard/signer-grader/grader.mjs +0 -6
  702. package/dist/lib/testing/storyboard/signer-grader/grader.mjs.map +1 -1
  703. package/dist/lib/testing/storyboard/signer-grader/index.mjs +0 -6
  704. package/dist/lib/testing/storyboard/signer-grader/index.mjs.map +1 -1
  705. package/dist/lib/testing/storyboard/signer-grader/types.mjs +0 -6
  706. package/dist/lib/testing/storyboard/strict-validation-hints.mjs +0 -6
  707. package/dist/lib/testing/storyboard/strict-validation-hints.mjs.map +1 -1
  708. package/dist/lib/testing/storyboard/task-map.mjs +0 -6
  709. package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
  710. package/dist/lib/testing/storyboard/test-kit.mjs +0 -6
  711. package/dist/lib/testing/storyboard/test-kit.mjs.map +1 -1
  712. package/dist/lib/testing/storyboard/types.mjs +0 -6
  713. package/dist/lib/testing/storyboard/types.mjs.map +1 -1
  714. package/dist/lib/testing/storyboard/validations.mjs +0 -6
  715. package/dist/lib/testing/storyboard/validations.mjs.map +1 -1
  716. package/dist/lib/testing/storyboard/webhook-assertions.mjs +0 -6
  717. package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
  718. package/dist/lib/testing/storyboard/webhook-receiver.mjs +0 -6
  719. package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
  720. package/dist/lib/testing/stubs/governance-agent-stub.mjs +0 -6
  721. package/dist/lib/testing/stubs/governance-agent-stub.mjs.map +1 -1
  722. package/dist/lib/testing/stubs/index.mjs +0 -6
  723. package/dist/lib/testing/stubs/index.mjs.map +1 -1
  724. package/dist/lib/testing/test-controller.mjs +0 -6
  725. package/dist/lib/testing/test-controller.mjs.map +1 -1
  726. package/dist/lib/testing/test-helpers.mjs +0 -6
  727. package/dist/lib/testing/test-helpers.mjs.map +1 -1
  728. package/dist/lib/testing/types.mjs +0 -6
  729. package/dist/lib/types/adcp.mjs +0 -6
  730. package/dist/lib/types/adcp.mjs.map +1 -1
  731. package/dist/lib/types/asset-instances.mjs +0 -6
  732. package/dist/lib/types/compat.mjs +0 -6
  733. package/dist/lib/types/compat.mjs.map +1 -1
  734. package/dist/lib/types/core.generated.mjs +0 -6
  735. package/dist/lib/types/enums.generated.mjs +0 -6
  736. package/dist/lib/types/enums.generated.mjs.map +1 -1
  737. package/dist/lib/types/error-codes.mjs +0 -6
  738. package/dist/lib/types/error-codes.mjs.map +1 -1
  739. package/dist/lib/types/error-details.aliases.mjs +0 -6
  740. package/dist/lib/types/error-details.aliases.mjs.map +1 -1
  741. package/dist/lib/types/format-asset-slots.mjs +0 -6
  742. package/dist/lib/types/forward-compat-error-codes.mjs +0 -6
  743. package/dist/lib/types/forward-compat-error-codes.mjs.map +1 -1
  744. package/dist/lib/types/index.mjs +0 -6
  745. package/dist/lib/types/index.mjs.map +1 -1
  746. package/dist/lib/types/inline-enums.aliases.mjs +0 -6
  747. package/dist/lib/types/inline-enums.aliases.mjs.map +1 -1
  748. package/dist/lib/types/inline-enums.generated.mjs +0 -6
  749. package/dist/lib/types/inline-enums.generated.mjs.map +1 -1
  750. package/dist/lib/types/manifest.generated.mjs +0 -6
  751. package/dist/lib/types/manifest.generated.mjs.map +1 -1
  752. package/dist/lib/types/schemas.generated.mjs +0 -6
  753. package/dist/lib/types/schemas.generated.mjs.map +1 -1
  754. package/dist/lib/types/server-payload-aliases.mjs +0 -6
  755. package/dist/lib/types/server-payload.mjs +0 -6
  756. package/dist/lib/types/sync-rows.mjs +0 -6
  757. package/dist/lib/types/tools.generated.mjs +0 -6
  758. package/dist/lib/types/v2-5/index.mjs +0 -6
  759. package/dist/lib/types/v2-5/index.mjs.map +1 -1
  760. package/dist/lib/types/v2-5/tools.generated.mjs +0 -6
  761. package/dist/lib/types/v3-1-beta/index.mjs +0 -6
  762. package/dist/lib/types/v3-1-beta/index.mjs.map +1 -1
  763. package/dist/lib/types/v3-1-beta/tools.generated.mjs +0 -6
  764. package/dist/lib/types/wellknown-schemas.generated.mjs +0 -6
  765. package/dist/lib/types/wellknown-schemas.generated.mjs.map +1 -1
  766. package/dist/lib/upstream-recorder/constants.mjs +0 -6
  767. package/dist/lib/upstream-recorder/constants.mjs.map +1 -1
  768. package/dist/lib/upstream-recorder/index.mjs +0 -6
  769. package/dist/lib/upstream-recorder/index.mjs.map +1 -1
  770. package/dist/lib/upstream-recorder/recorder.mjs +0 -6
  771. package/dist/lib/upstream-recorder/recorder.mjs.map +1 -1
  772. package/dist/lib/upstream-recorder/types.mjs +0 -6
  773. package/dist/lib/upstream-recorder/types.mjs.map +1 -1
  774. package/dist/lib/utils/a2a-artifacts.mjs +0 -6
  775. package/dist/lib/utils/a2a-artifacts.mjs.map +1 -1
  776. package/dist/lib/utils/a2a-discovery.mjs +0 -6
  777. package/dist/lib/utils/a2a-discovery.mjs.map +1 -1
  778. package/dist/lib/utils/activation-key-builders.mjs +0 -6
  779. package/dist/lib/utils/activation-key-builders.mjs.map +1 -1
  780. package/dist/lib/utils/adcp-version-config.mjs +0 -6
  781. package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
  782. package/dist/lib/utils/asset-builders.mjs +0 -6
  783. package/dist/lib/utils/asset-builders.mjs.map +1 -1
  784. package/dist/lib/utils/build-creative-return-builders.mjs +0 -6
  785. package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
  786. package/dist/lib/utils/buyer-retry-policy.mjs +0 -6
  787. package/dist/lib/utils/buyer-retry-policy.mjs.map +1 -1
  788. package/dist/lib/utils/capabilities.mjs +0 -6
  789. package/dist/lib/utils/capabilities.mjs.map +1 -1
  790. package/dist/lib/utils/capability-rollups.mjs +0 -6
  791. package/dist/lib/utils/capability-rollups.mjs.map +1 -1
  792. package/dist/lib/utils/creative-adapter.mjs +0 -6
  793. package/dist/lib/utils/creative-adapter.mjs.map +1 -1
  794. package/dist/lib/utils/creative-delivery.mjs +0 -6
  795. package/dist/lib/utils/creative-delivery.mjs.map +1 -1
  796. package/dist/lib/utils/deprecation.mjs +0 -6
  797. package/dist/lib/utils/deprecation.mjs.map +1 -1
  798. package/dist/lib/utils/envelope-status-compat.mjs +0 -6
  799. package/dist/lib/utils/envelope-status-compat.mjs.map +1 -1
  800. package/dist/lib/utils/error-extraction.mjs +0 -6
  801. package/dist/lib/utils/error-extraction.mjs.map +1 -1
  802. package/dist/lib/utils/extract-result.mjs +0 -6
  803. package/dist/lib/utils/extract-result.mjs.map +1 -1
  804. package/dist/lib/utils/format-asset-slot-builders.mjs +0 -6
  805. package/dist/lib/utils/format-asset-slot-builders.mjs.map +1 -1
  806. package/dist/lib/utils/format-assets.mjs +0 -6
  807. package/dist/lib/utils/format-assets.mjs.map +1 -1
  808. package/dist/lib/utils/format-render-builders.mjs +0 -6
  809. package/dist/lib/utils/format-render-builders.mjs.map +1 -1
  810. package/dist/lib/utils/format-renders.mjs +0 -6
  811. package/dist/lib/utils/format-renders.mjs.map +1 -1
  812. package/dist/lib/utils/get-products-cache-scope.mjs +0 -6
  813. package/dist/lib/utils/get-products-cache-scope.mjs.map +1 -1
  814. package/dist/lib/utils/glob.mjs +0 -6
  815. package/dist/lib/utils/glob.mjs.map +1 -1
  816. package/dist/lib/utils/global-async-local-storage.mjs +0 -6
  817. package/dist/lib/utils/global-async-local-storage.mjs.map +1 -1
  818. package/dist/lib/utils/idempotency.mjs +0 -6
  819. package/dist/lib/utils/idempotency.mjs.map +1 -1
  820. package/dist/lib/utils/index.mjs +0 -6
  821. package/dist/lib/utils/index.mjs.map +1 -1
  822. package/dist/lib/utils/jcs.mjs +0 -6
  823. package/dist/lib/utils/jcs.mjs.map +1 -1
  824. package/dist/lib/utils/json-depth.mjs +0 -6
  825. package/dist/lib/utils/json-depth.mjs.map +1 -1
  826. package/dist/lib/utils/logger.mjs +0 -6
  827. package/dist/lib/utils/logger.mjs.map +1 -1
  828. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs +0 -6
  829. package/dist/lib/utils/media-buy-delivery-notification-builders.mjs.map +1 -1
  830. package/dist/lib/utils/media-buy-status.mjs +0 -6
  831. package/dist/lib/utils/media-buy-status.mjs.map +1 -1
  832. package/dist/lib/utils/pagination.mjs +0 -6
  833. package/dist/lib/utils/pagination.mjs.map +1 -1
  834. package/dist/lib/utils/preview-creative-builders.mjs +0 -6
  835. package/dist/lib/utils/preview-creative-builders.mjs.map +1 -1
  836. package/dist/lib/utils/preview-normalizer.mjs +0 -6
  837. package/dist/lib/utils/preview-normalizer.mjs.map +1 -1
  838. package/dist/lib/utils/preview-utils.mjs +0 -6
  839. package/dist/lib/utils/preview-utils.mjs.map +1 -1
  840. package/dist/lib/utils/pricing-adapter.mjs +0 -6
  841. package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
  842. package/dist/lib/utils/probe-policy.mjs +0 -6
  843. package/dist/lib/utils/probe-policy.mjs.map +1 -1
  844. package/dist/lib/utils/protocol-detection.mjs +0 -6
  845. package/dist/lib/utils/protocol-detection.mjs.map +1 -1
  846. package/dist/lib/utils/redact-secrets.mjs +0 -6
  847. package/dist/lib/utils/redact-secrets.mjs.map +1 -1
  848. package/dist/lib/utils/redis-default-prefix-warn.mjs +0 -6
  849. package/dist/lib/utils/redis-default-prefix-warn.mjs.map +1 -1
  850. package/dist/lib/utils/render-builders.mjs +0 -6
  851. package/dist/lib/utils/render-builders.mjs.map +1 -1
  852. package/dist/lib/utils/request-normalizer.mjs +0 -6
  853. package/dist/lib/utils/request-normalizer.mjs.map +1 -1
  854. package/dist/lib/utils/response-schemas.mjs +0 -6
  855. package/dist/lib/utils/response-schemas.mjs.map +1 -1
  856. package/dist/lib/utils/response-unwrapper.mjs +0 -6
  857. package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
  858. package/dist/lib/utils/retry.mjs +0 -6
  859. package/dist/lib/utils/retry.mjs.map +1 -1
  860. package/dist/lib/utils/signal-discovery-helpers.mjs +0 -6
  861. package/dist/lib/utils/signal-discovery-helpers.mjs.map +1 -1
  862. package/dist/lib/utils/signal-id-builders.mjs +0 -6
  863. package/dist/lib/utils/signal-id-builders.mjs.map +1 -1
  864. package/dist/lib/utils/sync-creatives-adapter.mjs +0 -6
  865. package/dist/lib/utils/sync-creatives-adapter.mjs.map +1 -1
  866. package/dist/lib/utils/task-state.mjs +0 -6
  867. package/dist/lib/utils/task-state.mjs.map +1 -1
  868. package/dist/lib/utils/tool-request-schemas.mjs +0 -6
  869. package/dist/lib/utils/tool-request-schemas.mjs.map +1 -1
  870. package/dist/lib/utils/typeGuards.mjs +0 -6
  871. package/dist/lib/utils/typeGuards.mjs.map +1 -1
  872. package/dist/lib/utils/union-errors.mjs +0 -6
  873. package/dist/lib/utils/union-errors.mjs.map +1 -1
  874. package/dist/lib/utils/validate-user-agent.mjs +0 -6
  875. package/dist/lib/utils/validate-user-agent.mjs.map +1 -1
  876. package/dist/lib/v2/format-schema/fetch.mjs +0 -6
  877. package/dist/lib/v2/format-schema/fetch.mjs.map +1 -1
  878. package/dist/lib/v2/format-schema/index.mjs +0 -6
  879. package/dist/lib/v2/format-schema/index.mjs.map +1 -1
  880. package/dist/lib/v2/format-schema/regex-safety.mjs +0 -6
  881. package/dist/lib/v2/format-schema/regex-safety.mjs.map +1 -1
  882. package/dist/lib/v2/format-schema/resolver.mjs +7 -8
  883. package/dist/lib/v2/format-schema/resolver.mjs.map +1 -1
  884. package/dist/lib/v2/format-schema/sandbox-refs.mjs +0 -6
  885. package/dist/lib/v2/format-schema/sandbox-refs.mjs.map +1 -1
  886. package/dist/lib/v2/projection/augment-response.mjs +0 -6
  887. package/dist/lib/v2/projection/augment-response.mjs.map +1 -1
  888. package/dist/lib/v2/projection/builders.mjs +0 -6
  889. package/dist/lib/v2/projection/builders.mjs.map +1 -1
  890. package/dist/lib/v2/projection/cache-versions.mjs +0 -6
  891. package/dist/lib/v2/projection/cache-versions.mjs.map +1 -1
  892. package/dist/lib/v2/projection/canonical-properties.mjs +5 -6
  893. package/dist/lib/v2/projection/canonical-properties.mjs.map +1 -1
  894. package/dist/lib/v2/projection/catalog.mjs +5 -6
  895. package/dist/lib/v2/projection/catalog.mjs.map +1 -1
  896. package/dist/lib/v2/projection/constants.mjs +0 -6
  897. package/dist/lib/v2/projection/constants.mjs.map +1 -1
  898. package/dist/lib/v2/projection/index.mjs +0 -6
  899. package/dist/lib/v2/projection/index.mjs.map +1 -1
  900. package/dist/lib/v2/projection/registry.mjs +5 -6
  901. package/dist/lib/v2/projection/registry.mjs.map +1 -1
  902. package/dist/lib/v2/projection/types.mjs +0 -6
  903. package/dist/lib/v2/projection/v1-to-v2.mjs +0 -6
  904. package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
  905. package/dist/lib/v2/projection/v2-to-v1.mjs +0 -6
  906. package/dist/lib/v2/projection/v2-to-v1.mjs.map +1 -1
  907. package/dist/lib/v2/projection/write-side.mjs +0 -6
  908. package/dist/lib/v2/projection/write-side.mjs.map +1 -1
  909. package/dist/lib/v2/publisher-catalog/formats.mjs +0 -6
  910. package/dist/lib/v2/publisher-catalog/formats.mjs.map +1 -1
  911. package/dist/lib/v2/publisher-catalog/index.mjs +0 -6
  912. package/dist/lib/v2/publisher-catalog/index.mjs.map +1 -1
  913. package/dist/lib/validation/client-hooks.mjs +0 -6
  914. package/dist/lib/validation/client-hooks.mjs.map +1 -1
  915. package/dist/lib/validation/hints.mjs +0 -6
  916. package/dist/lib/validation/hints.mjs.map +1 -1
  917. package/dist/lib/validation/index.mjs +0 -6
  918. package/dist/lib/validation/index.mjs.map +1 -1
  919. package/dist/lib/validation/schema-errors.mjs +0 -6
  920. package/dist/lib/validation/schema-errors.mjs.map +1 -1
  921. package/dist/lib/validation/schema-loader.mjs +5 -6
  922. package/dist/lib/validation/schema-loader.mjs.map +1 -1
  923. package/dist/lib/validation/schema-validator.mjs +0 -6
  924. package/dist/lib/validation/schema-validator.mjs.map +1 -1
  925. package/dist/lib/validation/sync-creatives.mjs +0 -6
  926. package/dist/lib/validation/sync-creatives.mjs.map +1 -1
  927. package/dist/lib/version.d.mts +3 -3
  928. package/dist/lib/version.d.ts +3 -3
  929. package/dist/lib/version.js +3 -3
  930. package/dist/lib/version.js.map +1 -1
  931. package/dist/lib/version.mjs +3 -9
  932. package/dist/lib/version.mjs.map +1 -1
  933. package/dist/lib/webhooks/index.mjs +0 -6
  934. package/dist/lib/webhooks/index.mjs.map +1 -1
  935. package/dist/lib/wholesale-feed-sync/index.mjs +0 -6
  936. package/dist/lib/wholesale-feed-sync/index.mjs.map +1 -1
  937. package/dist/lib/wholesale-feed-sync/sync.mjs +0 -6
  938. package/dist/lib/wholesale-feed-sync/sync.mjs.map +1 -1
  939. package/dist/lib/wholesale-feed-sync/types.mjs +0 -6
  940. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs +0 -6
  941. package/dist/lib/wholesale-feed-sync/webhook-notification.mjs.map +1 -1
  942. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/media-buy-actions.ts"],"sourcesContent":["/**\n * Server/adopter helpers for enforcing the update_media_buy action surface.\n *\n * The media-buy module owns pure decomposition and preflight. This wrapper\n * converts denied preflights into the canonical server-side `AdcpError` shape\n * so DecisioningPlatform implementations can reject unavailable mutations\n * without hand-building ACTION_NOT_ALLOWED envelopes.\n */\n\nimport { ValidationError } from '../errors';\nimport {\n getAvailableActions,\n preflightUpdateMediaBuy,\n type ActionNotAllowedReason,\n type MediaBuyActionContext,\n type MediaBuyActionMode,\n type MediaBuyAvailableAction,\n type MediaBuyValidAction,\n type PreflightAllowed,\n type PreflightDenied,\n type PreflightDenial,\n type UpdateMediaBuyRequestLike,\n} from '../media-buy';\nimport { AdcpError } from './decisioning/async-outcome';\n\nexport interface AssertUpdateMediaBuyAllowedOptions {\n /**\n * Restrict the modes this call path may execute directly. Omit to enforce\n * availability only. Pass `['self_serve']` when the handler cannot queue\n * proposal / approval flows and should reject those as `mode_mismatch`.\n */\n allowedModes?: readonly MediaBuyActionMode[];\n /**\n * Override the reason used for missing actions. Defaults to the preflight\n * denial reason (`not_supported_on_buy` for buyer-side preflight misses).\n */\n reason?: ActionNotAllowedReason | ((denial: PreflightDenial, result: PreflightDenied) => ActionNotAllowedReason);\n}\n\n/**\n * Assert that an `update_media_buy` patch only requests actions currently\n * available on the supplied media buy. On success, returns the same enriched\n * preflight result callers can use to dispatch `result.mutations`.\n *\n * Throws:\n * - `AdcpError('INVALID_REQUEST')` when the patch contains no recognized\n * update mutation.\n * - `AdcpError('ACTION_NOT_ALLOWED')` with spec details when at least one\n * requested action is unavailable or disallowed by `allowedModes`.\n */\nexport function assertUpdateMediaBuyAllowed(\n currentBuy: MediaBuyActionContext,\n request: UpdateMediaBuyRequestLike,\n options: AssertUpdateMediaBuyAllowedOptions = {}\n): PreflightAllowed {\n let result: ReturnType<typeof preflightUpdateMediaBuy>;\n try {\n result = preflightUpdateMediaBuy(currentBuy, request);\n } catch (err) {\n if (err instanceof ValidationError) {\n throw new AdcpError('INVALID_REQUEST', {\n message: err.message,\n recovery: 'correctable',\n field: 'request',\n });\n }\n throw err;\n }\n\n const currentlyAvailable = getAvailableActions(currentBuy, { silent: true }).actions;\n\n if (!result.ok) {\n throw actionNotAllowedFromDenied(result, currentlyAvailable, options);\n }\n\n if (options.allowedModes && options.allowedModes.length > 0) {\n const modeMismatch = result.matched.findIndex(match => !options.allowedModes!.includes(match.mode));\n if (modeMismatch >= 0) {\n const action = result.actions[modeMismatch]?.action ?? result.matched[modeMismatch]!.action;\n throw actionNotAllowed(action, 'mode_mismatch', currentlyAvailable);\n }\n }\n\n return result;\n}\n\nfunction actionNotAllowedFromDenied(\n result: PreflightDenied,\n currentlyAvailable: MediaBuyAvailableAction[],\n options: AssertUpdateMediaBuyAllowedOptions\n): AdcpError {\n const denial = result.denials[0];\n if (!denial) {\n return new AdcpError('INVALID_REQUEST', {\n message: 'update_media_buy request could not be mapped to an allowed action',\n recovery: 'correctable',\n field: 'request',\n });\n }\n\n const reason =\n typeof options.reason === 'function' ? options.reason(denial, result) : (options.reason ?? denial.reason);\n\n return actionNotAllowed(denial.action, reason, currentlyAvailable);\n}\n\nfunction actionNotAllowed(\n attemptedAction: MediaBuyValidAction,\n reason: ActionNotAllowedReason,\n currentlyAvailable: MediaBuyAvailableAction[]\n): AdcpError {\n const details = {\n attempted_action: attemptedAction,\n reason,\n currently_available_actions: currentlyAvailable,\n };\n\n return new AdcpError('ACTION_NOT_ALLOWED', {\n message: buildActionNotAllowedMessage(attemptedAction, reason),\n recovery: 'correctable',\n field: 'update_media_buy',\n details,\n });\n}\n\nfunction buildActionNotAllowedMessage(action: MediaBuyValidAction, reason: ActionNotAllowedReason): string {\n return `update_media_buy rejected: \\`${action}\\` not allowed (${reason}).`;\n}\n"],"mappings":";;;;;;AASA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OAUK;AACP,SAAS,iBAAiB;AA2BnB,SAAS,4BACd,YACA,SACA,UAA8C,CAAC,GAC7B;AAClB,MAAI;AACJ,MAAI;AACF,aAAS,wBAAwB,YAAY,OAAO;AAAA,EACtD,SAAS,KAAK;AACZ,QAAI,eAAe,iBAAiB;AAClC,YAAM,IAAI,UAAU,mBAAmB;AAAA,QACrC,SAAS,IAAI;AAAA,QACb,UAAU;AAAA,QACV,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,qBAAqB,oBAAoB,YAAY,EAAE,QAAQ,KAAK,CAAC,EAAE;AAE7E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,2BAA2B,QAAQ,oBAAoB,OAAO;AAAA,EACtE;AAEA,MAAI,QAAQ,gBAAgB,QAAQ,aAAa,SAAS,GAAG;AAC3D,UAAM,eAAe,OAAO,QAAQ,UAAU,WAAS,CAAC,QAAQ,aAAc,SAAS,MAAM,IAAI,CAAC;AAClG,QAAI,gBAAgB,GAAG;AACrB,YAAM,SAAS,OAAO,QAAQ,YAAY,GAAG,UAAU,OAAO,QAAQ,YAAY,EAAG;AACrF,YAAM,iBAAiB,QAAQ,iBAAiB,kBAAkB;AAAA,IACpE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,2BACP,QACA,oBACA,SACW;AACX,QAAM,SAAS,OAAO,QAAQ,CAAC;AAC/B,MAAI,CAAC,QAAQ;AACX,WAAO,IAAI,UAAU,mBAAmB;AAAA,MACtC,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,SACJ,OAAO,QAAQ,WAAW,aAAa,QAAQ,OAAO,QAAQ,MAAM,IAAK,QAAQ,UAAU,OAAO;AAEpG,SAAO,iBAAiB,OAAO,QAAQ,QAAQ,kBAAkB;AACnE;AAEA,SAAS,iBACP,iBACA,QACA,oBACW;AACX,QAAM,UAAU;AAAA,IACd,kBAAkB;AAAA,IAClB;AAAA,IACA,6BAA6B;AAAA,EAC/B;AAEA,SAAO,IAAI,UAAU,sBAAsB;AAAA,IACzC,SAAS,6BAA6B,iBAAiB,MAAM;AAAA,IAC7D,UAAU;AAAA,IACV,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAEA,SAAS,6BAA6B,QAA6B,QAAwC;AACzG,SAAO,gCAAgC,MAAM,mBAAmB,MAAM;AACxE;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/media-buy-actions.ts"],"sourcesContent":["/**\n * Server/adopter helpers for enforcing the update_media_buy action surface.\n *\n * The media-buy module owns pure decomposition and preflight. This wrapper\n * converts denied preflights into the canonical server-side `AdcpError` shape\n * so DecisioningPlatform implementations can reject unavailable mutations\n * without hand-building ACTION_NOT_ALLOWED envelopes.\n */\n\nimport { ValidationError } from '../errors';\nimport {\n getAvailableActions,\n preflightUpdateMediaBuy,\n type ActionNotAllowedReason,\n type MediaBuyActionContext,\n type MediaBuyActionMode,\n type MediaBuyAvailableAction,\n type MediaBuyValidAction,\n type PreflightAllowed,\n type PreflightDenied,\n type PreflightDenial,\n type UpdateMediaBuyRequestLike,\n} from '../media-buy';\nimport { AdcpError } from './decisioning/async-outcome';\n\nexport interface AssertUpdateMediaBuyAllowedOptions {\n /**\n * Restrict the modes this call path may execute directly. Omit to enforce\n * availability only. Pass `['self_serve']` when the handler cannot queue\n * proposal / approval flows and should reject those as `mode_mismatch`.\n */\n allowedModes?: readonly MediaBuyActionMode[];\n /**\n * Override the reason used for missing actions. Defaults to the preflight\n * denial reason (`not_supported_on_buy` for buyer-side preflight misses).\n */\n reason?: ActionNotAllowedReason | ((denial: PreflightDenial, result: PreflightDenied) => ActionNotAllowedReason);\n}\n\n/**\n * Assert that an `update_media_buy` patch only requests actions currently\n * available on the supplied media buy. On success, returns the same enriched\n * preflight result callers can use to dispatch `result.mutations`.\n *\n * Throws:\n * - `AdcpError('INVALID_REQUEST')` when the patch contains no recognized\n * update mutation.\n * - `AdcpError('ACTION_NOT_ALLOWED')` with spec details when at least one\n * requested action is unavailable or disallowed by `allowedModes`.\n */\nexport function assertUpdateMediaBuyAllowed(\n currentBuy: MediaBuyActionContext,\n request: UpdateMediaBuyRequestLike,\n options: AssertUpdateMediaBuyAllowedOptions = {}\n): PreflightAllowed {\n let result: ReturnType<typeof preflightUpdateMediaBuy>;\n try {\n result = preflightUpdateMediaBuy(currentBuy, request);\n } catch (err) {\n if (err instanceof ValidationError) {\n throw new AdcpError('INVALID_REQUEST', {\n message: err.message,\n recovery: 'correctable',\n field: 'request',\n });\n }\n throw err;\n }\n\n const currentlyAvailable = getAvailableActions(currentBuy, { silent: true }).actions;\n\n if (!result.ok) {\n throw actionNotAllowedFromDenied(result, currentlyAvailable, options);\n }\n\n if (options.allowedModes && options.allowedModes.length > 0) {\n const modeMismatch = result.matched.findIndex(match => !options.allowedModes!.includes(match.mode));\n if (modeMismatch >= 0) {\n const action = result.actions[modeMismatch]?.action ?? result.matched[modeMismatch]!.action;\n throw actionNotAllowed(action, 'mode_mismatch', currentlyAvailable);\n }\n }\n\n return result;\n}\n\nfunction actionNotAllowedFromDenied(\n result: PreflightDenied,\n currentlyAvailable: MediaBuyAvailableAction[],\n options: AssertUpdateMediaBuyAllowedOptions\n): AdcpError {\n const denial = result.denials[0];\n if (!denial) {\n return new AdcpError('INVALID_REQUEST', {\n message: 'update_media_buy request could not be mapped to an allowed action',\n recovery: 'correctable',\n field: 'request',\n });\n }\n\n const reason =\n typeof options.reason === 'function' ? options.reason(denial, result) : (options.reason ?? denial.reason);\n\n return actionNotAllowed(denial.action, reason, currentlyAvailable);\n}\n\nfunction actionNotAllowed(\n attemptedAction: MediaBuyValidAction,\n reason: ActionNotAllowedReason,\n currentlyAvailable: MediaBuyAvailableAction[]\n): AdcpError {\n const details = {\n attempted_action: attemptedAction,\n reason,\n currently_available_actions: currentlyAvailable,\n };\n\n return new AdcpError('ACTION_NOT_ALLOWED', {\n message: buildActionNotAllowedMessage(attemptedAction, reason),\n recovery: 'correctable',\n field: 'update_media_buy',\n details,\n });\n}\n\nfunction buildActionNotAllowedMessage(action: MediaBuyValidAction, reason: ActionNotAllowedReason): string {\n return `update_media_buy rejected: \\`${action}\\` not allowed (${reason}).`;\n}\n"],"mappings":"AASA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OAUK;AACP,SAAS,iBAAiB;AA2BnB,SAAS,4BACd,YACA,SACA,UAA8C,CAAC,GAC7B;AAClB,MAAI;AACJ,MAAI;AACF,aAAS,wBAAwB,YAAY,OAAO;AAAA,EACtD,SAAS,KAAK;AACZ,QAAI,eAAe,iBAAiB;AAClC,YAAM,IAAI,UAAU,mBAAmB;AAAA,QACrC,SAAS,IAAI;AAAA,QACb,UAAU;AAAA,QACV,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,qBAAqB,oBAAoB,YAAY,EAAE,QAAQ,KAAK,CAAC,EAAE;AAE7E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,2BAA2B,QAAQ,oBAAoB,OAAO;AAAA,EACtE;AAEA,MAAI,QAAQ,gBAAgB,QAAQ,aAAa,SAAS,GAAG;AAC3D,UAAM,eAAe,OAAO,QAAQ,UAAU,WAAS,CAAC,QAAQ,aAAc,SAAS,MAAM,IAAI,CAAC;AAClG,QAAI,gBAAgB,GAAG;AACrB,YAAM,SAAS,OAAO,QAAQ,YAAY,GAAG,UAAU,OAAO,QAAQ,YAAY,EAAG;AACrF,YAAM,iBAAiB,QAAQ,iBAAiB,kBAAkB;AAAA,IACpE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,2BACP,QACA,oBACA,SACW;AACX,QAAM,SAAS,OAAO,QAAQ,CAAC;AAC/B,MAAI,CAAC,QAAQ;AACX,WAAO,IAAI,UAAU,mBAAmB;AAAA,MACtC,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,SACJ,OAAO,QAAQ,WAAW,aAAa,QAAQ,OAAO,QAAQ,MAAM,IAAK,QAAQ,UAAU,OAAO;AAEpG,SAAO,iBAAiB,OAAO,QAAQ,QAAQ,kBAAkB;AACnE;AAEA,SAAS,iBACP,iBACA,QACA,oBACW;AACX,QAAM,UAAU;AAAA,IACd,kBAAkB;AAAA,IAClB;AAAA,IACA,6BAA6B;AAAA,EAC/B;AAEA,SAAO,IAAI,UAAU,sBAAsB;AAAA,IACzC,SAAS,6BAA6B,iBAAiB,MAAM;AAAA,IAC7D,UAAU;AAAA,IACV,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;AAEA,SAAS,6BAA6B,QAA6B,QAAwC;AACzG,SAAO,gCAAgC,MAAM,mBAAmB,MAAM;AACxE;","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
  function validActionsForStatus(status) {
8
2
  switch (status) {
9
3
  case "pending_creatives":
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/media-buy-helpers.ts"],"sourcesContent":["/**\n * Media buy response helpers that eliminate common implementation traps.\n *\n * These helpers encode protocol rules (status→valid_actions mapping,\n * required cancellation metadata, initial revision numbers) so agent\n * builders get the right shape by default.\n */\n\nimport type { MediaBuyStatus, CanceledBy, CreateMediaBuySuccess, Package } from '../types/core.generated';\n\n/**\n * Actions a buyer can perform on a media buy.\n * Derived from the generated schema to stay in sync automatically.\n */\nexport type ValidAction = NonNullable<CreateMediaBuySuccess['valid_actions']>[number];\n\n/**\n * Returns the default set of valid buyer actions for a given media buy status.\n *\n * Terminal statuses (completed, rejected, canceled) return an empty array.\n * Active statuses return the full set of actions; paused restricts to\n * resume, cancel, and budget/date updates.\n *\n * Both pending statuses allow full modification — the protocol permits\n * restructuring a buy (packages, budget, dates) while awaiting creatives\n * or start date.\n *\n * Sellers with restricted capabilities can filter the result:\n * ```typescript\n * const actions = validActionsForStatus('active')\n * .filter(a => a !== 'sync_creatives'); // no creative management\n * ```\n */\nexport function validActionsForStatus(status: MediaBuyStatus): ValidAction[] {\n switch (status) {\n case 'pending_creatives':\n case 'pending_start':\n return ['cancel', 'update_budget', 'update_dates', 'update_packages', 'add_packages', 'sync_creatives'];\n case 'active':\n return ['pause', 'cancel', 'update_budget', 'update_dates', 'update_packages', 'add_packages', 'sync_creatives'];\n case 'paused':\n return ['resume', 'cancel', 'update_budget', 'update_dates'];\n case 'completed':\n case 'rejected':\n case 'canceled':\n return [];\n }\n}\n\n/**\n * Input for cancelMediaBuyResponse(). Requires the fields that agent builders\n * commonly forget — canceled_by and revision are mandatory,\n * canceled_at defaults to now.\n */\nexport interface CancelMediaBuyInput {\n media_buy_id: string;\n canceled_by: CanceledBy;\n /** Current revision after the cancellation update. */\n revision: number;\n reason?: string;\n canceled_at?: string;\n affected_packages?: Package[];\n sandbox?: boolean;\n}\n"],"mappings":";;;;;;AAiCO,SAAS,sBAAsB,QAAuC;AAC3E,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC,UAAU,iBAAiB,gBAAgB,mBAAmB,gBAAgB,gBAAgB;AAAA,IACxG,KAAK;AACH,aAAO,CAAC,SAAS,UAAU,iBAAiB,gBAAgB,mBAAmB,gBAAgB,gBAAgB;AAAA,IACjH,KAAK;AACH,aAAO,CAAC,UAAU,UAAU,iBAAiB,cAAc;AAAA,IAC7D,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC;AAAA,EACZ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/media-buy-helpers.ts"],"sourcesContent":["/**\n * Media buy response helpers that eliminate common implementation traps.\n *\n * These helpers encode protocol rules (status→valid_actions mapping,\n * required cancellation metadata, initial revision numbers) so agent\n * builders get the right shape by default.\n */\n\nimport type { MediaBuyStatus, CanceledBy, CreateMediaBuySuccess, Package } from '../types/core.generated';\n\n/**\n * Actions a buyer can perform on a media buy.\n * Derived from the generated schema to stay in sync automatically.\n */\nexport type ValidAction = NonNullable<CreateMediaBuySuccess['valid_actions']>[number];\n\n/**\n * Returns the default set of valid buyer actions for a given media buy status.\n *\n * Terminal statuses (completed, rejected, canceled) return an empty array.\n * Active statuses return the full set of actions; paused restricts to\n * resume, cancel, and budget/date updates.\n *\n * Both pending statuses allow full modification — the protocol permits\n * restructuring a buy (packages, budget, dates) while awaiting creatives\n * or start date.\n *\n * Sellers with restricted capabilities can filter the result:\n * ```typescript\n * const actions = validActionsForStatus('active')\n * .filter(a => a !== 'sync_creatives'); // no creative management\n * ```\n */\nexport function validActionsForStatus(status: MediaBuyStatus): ValidAction[] {\n switch (status) {\n case 'pending_creatives':\n case 'pending_start':\n return ['cancel', 'update_budget', 'update_dates', 'update_packages', 'add_packages', 'sync_creatives'];\n case 'active':\n return ['pause', 'cancel', 'update_budget', 'update_dates', 'update_packages', 'add_packages', 'sync_creatives'];\n case 'paused':\n return ['resume', 'cancel', 'update_budget', 'update_dates'];\n case 'completed':\n case 'rejected':\n case 'canceled':\n return [];\n }\n}\n\n/**\n * Input for cancelMediaBuyResponse(). Requires the fields that agent builders\n * commonly forget — canceled_by and revision are mandatory,\n * canceled_at defaults to now.\n */\nexport interface CancelMediaBuyInput {\n media_buy_id: string;\n canceled_by: CanceledBy;\n /** Current revision after the cancellation update. */\n revision: number;\n reason?: string;\n canceled_at?: string;\n affected_packages?: Package[];\n sandbox?: boolean;\n}\n"],"mappings":"AAiCO,SAAS,sBAAsB,QAAuC;AAC3E,UAAQ,QAAQ;AAAA,IACd,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC,UAAU,iBAAiB,gBAAgB,mBAAmB,gBAAgB,gBAAgB;AAAA,IACxG,KAAK;AACH,aAAO,CAAC,SAAS,UAAU,iBAAiB,gBAAgB,mBAAmB,gBAAgB,gBAAgB;AAAA,IACjH,KAAK;AACH,aAAO,CAAC,UAAU,UAAU,iBAAiB,cAAc;AAAA,IAC7D,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,CAAC;AAAA,EACZ;AACF;","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 { scopedStore } from "./state-store.mjs";
8
2
  const DEFAULT_MEDIA_BUY_STORE_COLLECTION = "media_buys_targeting";
9
3
  function createMediaBuyStore(options) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/media-buy-store.ts"],"sourcesContent":["/**\n * Opinionated media-buy store that satisfies the seller's spec contract:\n * persist `packages[].targeting_overlay` from `create_media_buy`, echo it on\n * `get_media_buys`, and deep-merge updates without dropping prior\n * `property_list` / `collection_list` references.\n *\n * Per `schemas/cache/<v>/media-buy/get-media-buys-response.json` the seller\n * SHOULD echo persisted targeting; sellers claiming `property-lists` or\n * `collection-lists` MUST include the persisted references inside the\n * echoed `targeting_overlay`. Wiring this store is the framework-side\n * way to honor that contract without each adapter persisting + merging\n * by hand.\n *\n * Adopters opt in by passing `mediaBuyStore` to\n * `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore` —\n * `InMemoryStateStore` for development, `PostgresStateStore` for\n * production.\n *\n * @example\n * ```ts\n * import {\n * createAdcpServerFromPlatform,\n * createMediaBuyStore,\n * InMemoryStateStore,\n * } from '@adcp/sdk/server';\n *\n * const stateStore = new InMemoryStateStore();\n *\n * createAdcpServerFromPlatform(platform, {\n * mediaBuyStore: createMediaBuyStore({ store: stateStore }),\n * });\n * ```\n */\n\nimport type { TargetingOverlay } from '../types/core.generated';\nimport type { AdcpStateStore } from './state-store';\nimport { scopedStore } from './state-store';\n\n/** Default state-store collection name. Adopters can override per-store. */\nexport const DEFAULT_MEDIA_BUY_STORE_COLLECTION = 'media_buys_targeting';\n\ninterface PersistedPackage {\n package_id: string;\n targeting_overlay: TargetingOverlay;\n}\n\ninterface PersistedRecord extends Record<string, unknown> {\n media_buy_id: string;\n packages: PersistedPackage[];\n}\n\n/**\n * Subset of `CreateMediaBuyRequest` the store cares about. Typed loosely\n * so the wrapper code in `from-platform.ts` doesn't have to upcast the\n * request to the full generated type just to thread it through.\n */\nexport interface CreateMediaBuyInputForStore {\n packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\n/**\n * Subset of `CreateMediaBuyResponse` (the success arm) the store needs to\n * pin persisted-from-request packages to seller-assigned `package_id`s.\n */\nexport interface CreateMediaBuyResultForStore {\n media_buy_id: string;\n packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\nexport interface UpdateMediaBuyInputForStore {\n packages?: Array<{\n package_id?: string;\n targeting_overlay?: TargetingOverlay | null;\n }>;\n new_packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\n/**\n * Subset of `GetMediaBuysResponse` mirroring the fields the store reads\n * + writes. Echoing is non-mutating from the buyer's perspective: every\n * package the seller already returned with `targeting_overlay` is left\n * alone.\n */\nexport interface GetMediaBuysResultForStore {\n media_buys?: Array<{\n media_buy_id?: string;\n packages?: Array<{\n package_id?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n }>;\n}\n\nexport interface MediaBuyStore {\n /**\n * Persist `packages[].targeting_overlay` from a successful\n * `create_media_buy`. Joins the request's per-package targeting\n * overlay with the response's seller-assigned `package_id` (or\n * `buyer_ref` when the request used buyer-supplied refs).\n */\n persistFromCreate(\n accountId: string,\n request: CreateMediaBuyInputForStore,\n result: CreateMediaBuyResultForStore\n ): Promise<void>;\n\n /**\n * Apply an `update_media_buy` patch to the persisted record.\n *\n * Per-field merge semantics inside `targeting_overlay`:\n * - field omitted from the patch → keep prior value\n * - field present with a non-null value → replace\n * - field present and `null` → clear (drop the field)\n *\n * `new_packages` from the patch are persisted as fresh entries when\n * they declare `targeting_overlay`. Entries that omit it are\n * intentionally NOT tracked — this store is overlay-only, and a\n * later patch can still seed an overlay onto the package_id when\n * one becomes relevant.\n */\n mergeFromUpdate(accountId: string, mediaBuyId: string, patch: UpdateMediaBuyInputForStore): Promise<void>;\n\n /**\n * Fill in missing `packages[].targeting_overlay` on the seller's\n * `get_media_buys` response from the persisted store. **Mutates the\n * response in place** (and returns it for fluent chaining). Packages\n * the seller already echoed are left untouched.\n */\n backfill<T extends GetMediaBuysResultForStore>(accountId: string, result: T): Promise<T>;\n}\n\nexport interface CreateMediaBuyStoreOptions {\n /** Backing state store. Reuses your existing `InMemoryStateStore` / `PostgresStateStore`. */\n store: AdcpStateStore;\n /** Override the logical collection name. Defaults to {@link DEFAULT_MEDIA_BUY_STORE_COLLECTION}. */\n collection?: string;\n}\n\nexport function createMediaBuyStore(options: CreateMediaBuyStoreOptions): MediaBuyStore {\n const collection = options.collection ?? DEFAULT_MEDIA_BUY_STORE_COLLECTION;\n\n function viewFor(accountId: string): AdcpStateStore {\n return scopedStore(options.store, accountId);\n }\n\n async function loadRecord(accountId: string, mediaBuyId: string): Promise<PersistedRecord | null> {\n const view = viewFor(accountId);\n return view.get<PersistedRecord>(collection, mediaBuyId);\n }\n\n async function writeRecord(accountId: string, record: PersistedRecord): Promise<void> {\n const view = viewFor(accountId);\n await view.put(collection, record.media_buy_id, record);\n }\n\n return {\n async persistFromCreate(accountId, request, result) {\n const requestPackages = request.packages ?? [];\n const responsePackages = result.packages ?? [];\n if (requestPackages.length === 0 || !result.media_buy_id) return;\n\n const persistedPackages: PersistedPackage[] = [];\n for (let i = 0; i < requestPackages.length; i++) {\n const reqPkg = requestPackages[i];\n if (!reqPkg?.targeting_overlay) continue;\n\n // Resolve the seller's assigned package_id. Prefer matching by\n // buyer_ref (deterministic across reorderings); fall back to\n // positional alignment which is the wire convention when the\n // request did not supply buyer refs.\n const buyerRef = reqPkg.buyer_ref;\n const matchedByRef =\n buyerRef && buyerRef.length > 0 ? responsePackages.find(p => p?.buyer_ref === buyerRef) : undefined;\n const respPkg = matchedByRef ?? responsePackages[i];\n const packageId = respPkg?.package_id;\n if (!packageId) continue;\n\n persistedPackages.push({\n package_id: packageId,\n targeting_overlay: respPkg?.targeting_overlay ?? reqPkg.targeting_overlay,\n });\n }\n\n if (persistedPackages.length === 0) return;\n await writeRecord(accountId, {\n media_buy_id: result.media_buy_id,\n packages: persistedPackages,\n });\n },\n\n async mergeFromUpdate(accountId, mediaBuyId, patch) {\n const prior = (await loadRecord(accountId, mediaBuyId)) ?? {\n media_buy_id: mediaBuyId,\n packages: [],\n };\n\n const byId = new Map(prior.packages.map(p => [p.package_id, p.targeting_overlay]));\n\n for (const pkg of patch.packages ?? []) {\n const packageId = pkg?.package_id;\n if (!packageId) continue;\n // `'targeting_overlay' in pkg` distinguishes \"patch did not mention\n // overlay\" (keep prior) from \"patch sent null/empty overlay\"\n // (process the clear). With the wire-shape coming through JSON\n // parse, omitted fields are absent from the object entirely.\n if (!('targeting_overlay' in pkg)) continue;\n const incoming = pkg.targeting_overlay;\n if (incoming === null) {\n byId.delete(packageId);\n continue;\n }\n if (incoming === undefined) continue;\n const priorOverlay = byId.get(packageId);\n byId.set(packageId, mergeOverlay(priorOverlay, incoming));\n }\n\n for (const pkg of patch.new_packages ?? []) {\n if (!pkg?.targeting_overlay || !pkg.package_id) continue;\n byId.set(pkg.package_id, pkg.targeting_overlay);\n }\n\n await writeRecord(accountId, {\n media_buy_id: mediaBuyId,\n packages: Array.from(byId.entries()).map(([package_id, targeting_overlay]) => ({\n package_id,\n targeting_overlay,\n })),\n });\n },\n\n async backfill(accountId, result) {\n const buys = result.media_buys;\n if (!buys || buys.length === 0) return result;\n for (const buy of buys) {\n if (!buy?.media_buy_id || !buy.packages) continue;\n const record = await loadRecord(accountId, buy.media_buy_id);\n if (!record) continue;\n const overlayById = new Map(record.packages.map(p => [p.package_id, p.targeting_overlay]));\n for (const pkg of buy.packages) {\n if (!pkg?.package_id || pkg.targeting_overlay !== undefined) continue;\n const persisted = overlayById.get(pkg.package_id);\n if (persisted) pkg.targeting_overlay = persisted;\n }\n }\n return result;\n },\n };\n}\n\n/**\n * Per-key merge of an incoming `TargetingOverlay` patch against the prior\n * persisted overlay. Each key the patch sets to `null` is dropped; each\n * key the patch sets to a value replaces the prior; keys absent from the\n * patch are preserved.\n *\n * The merge is one level deep — `property_list` / `collection_list` are\n * reference objects keyed by `list_id`, so a \"partial\" property-list\n * update is meaningless and a top-level replace is the right semantics.\n */\nfunction mergeOverlay(prior: TargetingOverlay | undefined, patch: TargetingOverlay): TargetingOverlay {\n const merged: Record<string, unknown> = { ...(prior ?? {}) };\n for (const [key, value] of Object.entries(patch)) {\n if (value === null) {\n delete merged[key];\n } else if (value !== undefined) {\n merged[key] = value;\n }\n }\n return merged as TargetingOverlay;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/media-buy-store.ts"],"sourcesContent":["/**\n * Opinionated media-buy store that satisfies the seller's spec contract:\n * persist `packages[].targeting_overlay` from `create_media_buy`, echo it on\n * `get_media_buys`, and deep-merge updates without dropping prior\n * `property_list` / `collection_list` references.\n *\n * Per `schemas/cache/<v>/media-buy/get-media-buys-response.json` the seller\n * SHOULD echo persisted targeting; sellers claiming `property-lists` or\n * `collection-lists` MUST include the persisted references inside the\n * echoed `targeting_overlay`. Wiring this store is the framework-side\n * way to honor that contract without each adapter persisting + merging\n * by hand.\n *\n * Adopters opt in by passing `mediaBuyStore` to\n * `createAdcpServerFromPlatform`. Backed by any `AdcpStateStore` —\n * `InMemoryStateStore` for development, `PostgresStateStore` for\n * production.\n *\n * @example\n * ```ts\n * import {\n * createAdcpServerFromPlatform,\n * createMediaBuyStore,\n * InMemoryStateStore,\n * } from '@adcp/sdk/server';\n *\n * const stateStore = new InMemoryStateStore();\n *\n * createAdcpServerFromPlatform(platform, {\n * mediaBuyStore: createMediaBuyStore({ store: stateStore }),\n * });\n * ```\n */\n\nimport type { TargetingOverlay } from '../types/core.generated';\nimport type { AdcpStateStore } from './state-store';\nimport { scopedStore } from './state-store';\n\n/** Default state-store collection name. Adopters can override per-store. */\nexport const DEFAULT_MEDIA_BUY_STORE_COLLECTION = 'media_buys_targeting';\n\ninterface PersistedPackage {\n package_id: string;\n targeting_overlay: TargetingOverlay;\n}\n\ninterface PersistedRecord extends Record<string, unknown> {\n media_buy_id: string;\n packages: PersistedPackage[];\n}\n\n/**\n * Subset of `CreateMediaBuyRequest` the store cares about. Typed loosely\n * so the wrapper code in `from-platform.ts` doesn't have to upcast the\n * request to the full generated type just to thread it through.\n */\nexport interface CreateMediaBuyInputForStore {\n packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\n/**\n * Subset of `CreateMediaBuyResponse` (the success arm) the store needs to\n * pin persisted-from-request packages to seller-assigned `package_id`s.\n */\nexport interface CreateMediaBuyResultForStore {\n media_buy_id: string;\n packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\nexport interface UpdateMediaBuyInputForStore {\n packages?: Array<{\n package_id?: string;\n targeting_overlay?: TargetingOverlay | null;\n }>;\n new_packages?: Array<{\n package_id?: string;\n buyer_ref?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n}\n\n/**\n * Subset of `GetMediaBuysResponse` mirroring the fields the store reads\n * + writes. Echoing is non-mutating from the buyer's perspective: every\n * package the seller already returned with `targeting_overlay` is left\n * alone.\n */\nexport interface GetMediaBuysResultForStore {\n media_buys?: Array<{\n media_buy_id?: string;\n packages?: Array<{\n package_id?: string;\n targeting_overlay?: TargetingOverlay;\n }>;\n }>;\n}\n\nexport interface MediaBuyStore {\n /**\n * Persist `packages[].targeting_overlay` from a successful\n * `create_media_buy`. Joins the request's per-package targeting\n * overlay with the response's seller-assigned `package_id` (or\n * `buyer_ref` when the request used buyer-supplied refs).\n */\n persistFromCreate(\n accountId: string,\n request: CreateMediaBuyInputForStore,\n result: CreateMediaBuyResultForStore\n ): Promise<void>;\n\n /**\n * Apply an `update_media_buy` patch to the persisted record.\n *\n * Per-field merge semantics inside `targeting_overlay`:\n * - field omitted from the patch → keep prior value\n * - field present with a non-null value → replace\n * - field present and `null` → clear (drop the field)\n *\n * `new_packages` from the patch are persisted as fresh entries when\n * they declare `targeting_overlay`. Entries that omit it are\n * intentionally NOT tracked — this store is overlay-only, and a\n * later patch can still seed an overlay onto the package_id when\n * one becomes relevant.\n */\n mergeFromUpdate(accountId: string, mediaBuyId: string, patch: UpdateMediaBuyInputForStore): Promise<void>;\n\n /**\n * Fill in missing `packages[].targeting_overlay` on the seller's\n * `get_media_buys` response from the persisted store. **Mutates the\n * response in place** (and returns it for fluent chaining). Packages\n * the seller already echoed are left untouched.\n */\n backfill<T extends GetMediaBuysResultForStore>(accountId: string, result: T): Promise<T>;\n}\n\nexport interface CreateMediaBuyStoreOptions {\n /** Backing state store. Reuses your existing `InMemoryStateStore` / `PostgresStateStore`. */\n store: AdcpStateStore;\n /** Override the logical collection name. Defaults to {@link DEFAULT_MEDIA_BUY_STORE_COLLECTION}. */\n collection?: string;\n}\n\nexport function createMediaBuyStore(options: CreateMediaBuyStoreOptions): MediaBuyStore {\n const collection = options.collection ?? DEFAULT_MEDIA_BUY_STORE_COLLECTION;\n\n function viewFor(accountId: string): AdcpStateStore {\n return scopedStore(options.store, accountId);\n }\n\n async function loadRecord(accountId: string, mediaBuyId: string): Promise<PersistedRecord | null> {\n const view = viewFor(accountId);\n return view.get<PersistedRecord>(collection, mediaBuyId);\n }\n\n async function writeRecord(accountId: string, record: PersistedRecord): Promise<void> {\n const view = viewFor(accountId);\n await view.put(collection, record.media_buy_id, record);\n }\n\n return {\n async persistFromCreate(accountId, request, result) {\n const requestPackages = request.packages ?? [];\n const responsePackages = result.packages ?? [];\n if (requestPackages.length === 0 || !result.media_buy_id) return;\n\n const persistedPackages: PersistedPackage[] = [];\n for (let i = 0; i < requestPackages.length; i++) {\n const reqPkg = requestPackages[i];\n if (!reqPkg?.targeting_overlay) continue;\n\n // Resolve the seller's assigned package_id. Prefer matching by\n // buyer_ref (deterministic across reorderings); fall back to\n // positional alignment which is the wire convention when the\n // request did not supply buyer refs.\n const buyerRef = reqPkg.buyer_ref;\n const matchedByRef =\n buyerRef && buyerRef.length > 0 ? responsePackages.find(p => p?.buyer_ref === buyerRef) : undefined;\n const respPkg = matchedByRef ?? responsePackages[i];\n const packageId = respPkg?.package_id;\n if (!packageId) continue;\n\n persistedPackages.push({\n package_id: packageId,\n targeting_overlay: respPkg?.targeting_overlay ?? reqPkg.targeting_overlay,\n });\n }\n\n if (persistedPackages.length === 0) return;\n await writeRecord(accountId, {\n media_buy_id: result.media_buy_id,\n packages: persistedPackages,\n });\n },\n\n async mergeFromUpdate(accountId, mediaBuyId, patch) {\n const prior = (await loadRecord(accountId, mediaBuyId)) ?? {\n media_buy_id: mediaBuyId,\n packages: [],\n };\n\n const byId = new Map(prior.packages.map(p => [p.package_id, p.targeting_overlay]));\n\n for (const pkg of patch.packages ?? []) {\n const packageId = pkg?.package_id;\n if (!packageId) continue;\n // `'targeting_overlay' in pkg` distinguishes \"patch did not mention\n // overlay\" (keep prior) from \"patch sent null/empty overlay\"\n // (process the clear). With the wire-shape coming through JSON\n // parse, omitted fields are absent from the object entirely.\n if (!('targeting_overlay' in pkg)) continue;\n const incoming = pkg.targeting_overlay;\n if (incoming === null) {\n byId.delete(packageId);\n continue;\n }\n if (incoming === undefined) continue;\n const priorOverlay = byId.get(packageId);\n byId.set(packageId, mergeOverlay(priorOverlay, incoming));\n }\n\n for (const pkg of patch.new_packages ?? []) {\n if (!pkg?.targeting_overlay || !pkg.package_id) continue;\n byId.set(pkg.package_id, pkg.targeting_overlay);\n }\n\n await writeRecord(accountId, {\n media_buy_id: mediaBuyId,\n packages: Array.from(byId.entries()).map(([package_id, targeting_overlay]) => ({\n package_id,\n targeting_overlay,\n })),\n });\n },\n\n async backfill(accountId, result) {\n const buys = result.media_buys;\n if (!buys || buys.length === 0) return result;\n for (const buy of buys) {\n if (!buy?.media_buy_id || !buy.packages) continue;\n const record = await loadRecord(accountId, buy.media_buy_id);\n if (!record) continue;\n const overlayById = new Map(record.packages.map(p => [p.package_id, p.targeting_overlay]));\n for (const pkg of buy.packages) {\n if (!pkg?.package_id || pkg.targeting_overlay !== undefined) continue;\n const persisted = overlayById.get(pkg.package_id);\n if (persisted) pkg.targeting_overlay = persisted;\n }\n }\n return result;\n },\n };\n}\n\n/**\n * Per-key merge of an incoming `TargetingOverlay` patch against the prior\n * persisted overlay. Each key the patch sets to `null` is dropped; each\n * key the patch sets to a value replaces the prior; keys absent from the\n * patch are preserved.\n *\n * The merge is one level deep — `property_list` / `collection_list` are\n * reference objects keyed by `list_id`, so a \"partial\" property-list\n * update is meaningless and a top-level replace is the right semantics.\n */\nfunction mergeOverlay(prior: TargetingOverlay | undefined, patch: TargetingOverlay): TargetingOverlay {\n const merged: Record<string, unknown> = { ...(prior ?? {}) };\n for (const [key, value] of Object.entries(patch)) {\n if (value === null) {\n delete merged[key];\n } else if (value !== undefined) {\n merged[key] = value;\n }\n }\n return merged as TargetingOverlay;\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
  function normalizeError(input) {
8
2
  if (input == null) {
9
3
  return { code: "GENERIC_ERROR", message: "Unknown error", recovery: "terminal" };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/normalize-errors.ts"],"sourcesContent":["/**\n * Wire-shape normalizer for the AdCP `Error` row used in tool responses\n * carrying per-row failures (`sync_creatives`, `sync_audiences`,\n * `sync_accounts`, `report_usage`, `acquire_rights` error arm).\n *\n * Adopters return errors in whichever shape their codebase already\n * speaks: bare strings, native `Error` instances, plain\n * `{ code, message }` objects, `AdcpError` instances thrown internally,\n * upstream-platform error objects with vendor-specific fields. This\n * helper coerces all of those into the canonical wire `Error` shape\n * (`code`, `message`, optional `field` / `suggestion` / `retry_after`\n * / `details` / `recovery`) so the framework's response validator\n * accepts the projected response without forcing every adopter to\n * hand-shape the wire envelope.\n *\n * @see AdCP wire spec: `core/error.json`\n *\n * @public\n */\n\nimport type { ErrorCode } from './decisioning/async-outcome';\n\n/**\n * Canonical wire `Error` row. Mirrors `core/error.json` —\n * `code` + `message` are required; everything else optional.\n *\n * Differs from the SDK's `AdcpStructuredError` in only one detail —\n * `recovery` is optional here (per the wire spec) but required on\n * `AdcpStructuredError` (the SDK's stricter shape for thrown errors).\n *\n * @public\n */\nexport interface NormalizedError {\n code: string;\n message: string;\n field?: string;\n suggestion?: string;\n retry_after?: number;\n details?: Record<string, unknown>;\n recovery?: 'transient' | 'correctable' | 'terminal';\n}\n\n/**\n * Coerce a single adopter-returned error value into the canonical\n * wire `Error` shape. Handles:\n *\n * - `string` → `{ code: 'GENERIC_ERROR', message: <input>, recovery: 'terminal' }`\n * - `Error` instance → `{ code: 'GENERIC_ERROR', message: err.message, recovery: 'terminal' }`\n * - `AdcpError` instance → projected to wire shape using its `code` /\n * `recovery` / `field` / `suggestion` / `retry_after` / `details`\n * - Plain object with `code` + `message` → fields whitelisted to the\n * wire shape; vendor-specific fields dropped (use `details` for\n * vendor extensions)\n * - Any other object → `{ code: 'GENERIC_ERROR', message: <safeStringify>, recovery: 'terminal' }`\n * - `null` / `undefined` → `{ code: 'GENERIC_ERROR', message: 'Unknown error', recovery: 'terminal' }`\n *\n * The `details` field, when present on the input, is shallow-copied\n * and SHOULD be passed through {@link pickSafeDetails} on the\n * adopter side before reaching this helper. `normalizeError` does NOT\n * sanitize `details` — it's the adopter's job to ensure no\n * credentials / PII / stack traces land there.\n *\n * @public\n */\nexport function normalizeError(input: unknown): NormalizedError {\n if (input == null) {\n return { code: 'GENERIC_ERROR', message: 'Unknown error', recovery: 'terminal' };\n }\n if (typeof input === 'string') {\n return { code: 'GENERIC_ERROR', message: input, recovery: 'terminal' };\n }\n // AdcpError-shaped (has `code`, optional structured fields). Detected\n // structurally rather than via instanceof so framework code in different\n // module realms (test fixtures, server-side renderers) still gets the\n // typed projection.\n if (typeof input === 'object' && 'code' in input) {\n const obj = input as Record<string, unknown>;\n const code = typeof obj.code === 'string' && obj.code.length > 0 ? obj.code : 'GENERIC_ERROR';\n const message = typeof obj.message === 'string' && obj.message.length > 0 ? obj.message : code; // fall back to code when message missing — never empty-string\n const out: NormalizedError = { code, message };\n if (typeof obj.field === 'string') out.field = obj.field;\n if (typeof obj.suggestion === 'string') out.suggestion = obj.suggestion;\n if (typeof obj.retry_after === 'number' && Number.isFinite(obj.retry_after)) {\n // Wire spec clamps retry_after to [1, 3600]\n out.retry_after = Math.max(1, Math.min(3600, Math.floor(obj.retry_after)));\n }\n if (obj.recovery === 'transient' || obj.recovery === 'correctable' || obj.recovery === 'terminal') {\n out.recovery = obj.recovery;\n }\n if (typeof obj.details === 'object' && obj.details !== null) {\n // Shallow copy to break aliasing; adopter is responsible for sanitizing\n // via pickSafeDetails before reaching here.\n out.details = { ...(obj.details as Record<string, unknown>) };\n }\n return out;\n }\n // Native Error (no `code` field, has `message`).\n if (input instanceof Error) {\n return { code: 'GENERIC_ERROR', message: input.message || 'Unknown error', recovery: 'terminal' };\n }\n // Last-resort: stringify whatever was passed.\n return {\n code: 'GENERIC_ERROR',\n message: safeStringify(input),\n recovery: 'terminal',\n };\n}\n\n/**\n * Coerce an adopter-returned errors collection into a wire-shaped\n * `Error[]`. Accepts `undefined` / `null` (returns `undefined`),\n * a single error value (wraps in array), or an array of error values\n * (each normalized via {@link normalizeError}).\n *\n * Empty arrays and arrays where every entry normalizes to the same\n * sentinel \"Unknown error\" are still emitted — the framework lets the\n * wire validator decide whether `errors: []` is acceptable for the\n * specific tool response (sync_creatives accepts empty;\n * sync_creatives_error requires non-empty).\n *\n * Use at the v6 wire-projection seam:\n *\n * ```ts\n * import { normalizeErrors } from '@adcp/client/server';\n *\n * const projected = adopterRows.map(row => ({\n * ...row,\n * errors: normalizeErrors(row.errors),\n * }));\n * ```\n *\n * @public\n */\nexport function normalizeErrors(input: unknown): NormalizedError[] | undefined {\n if (input == null) return undefined;\n if (Array.isArray(input)) {\n return input.map(normalizeError);\n }\n return [normalizeError(input)];\n}\n\n/**\n * Coerce an `ErrorCode`-typed input back to the underlying string —\n * useful when adopters pass an enum-narrowed code into a place that\n * expects the wire string. Pure-function alias for clarity at call\n * sites; the runtime is identity.\n *\n * @internal\n */\nexport function _coerceErrorCode(code: ErrorCode | string): string {\n return code;\n}\n\n/** Best-effort `JSON.stringify` that swallows circular-reference errors. */\nfunction safeStringify(input: unknown): string {\n try {\n const s = JSON.stringify(input);\n return typeof s === 'string' ? s : String(input);\n } catch {\n return '[unserializable error]';\n }\n}\n"],"mappings":";;;;;;AAgEO,SAAS,eAAe,OAAiC;AAC9D,MAAI,SAAS,MAAM;AACjB,WAAO,EAAE,MAAM,iBAAiB,SAAS,iBAAiB,UAAU,WAAW;AAAA,EACjF;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,MAAM,iBAAiB,SAAS,OAAO,UAAU,WAAW;AAAA,EACvE;AAKA,MAAI,OAAO,UAAU,YAAY,UAAU,OAAO;AAChD,UAAM,MAAM;AACZ,UAAM,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO;AAC9E,UAAM,UAAU,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,IAAI,IAAI,UAAU;AAC1F,UAAM,MAAuB,EAAE,MAAM,QAAQ;AAC7C,QAAI,OAAO,IAAI,UAAU,SAAU,KAAI,QAAQ,IAAI;AACnD,QAAI,OAAO,IAAI,eAAe,SAAU,KAAI,aAAa,IAAI;AAC7D,QAAI,OAAO,IAAI,gBAAgB,YAAY,OAAO,SAAS,IAAI,WAAW,GAAG;AAE3E,UAAI,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC;AAAA,IAC3E;AACA,QAAI,IAAI,aAAa,eAAe,IAAI,aAAa,iBAAiB,IAAI,aAAa,YAAY;AACjG,UAAI,WAAW,IAAI;AAAA,IACrB;AACA,QAAI,OAAO,IAAI,YAAY,YAAY,IAAI,YAAY,MAAM;AAG3D,UAAI,UAAU,EAAE,GAAI,IAAI,QAAoC;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,EAAE,MAAM,iBAAiB,SAAS,MAAM,WAAW,iBAAiB,UAAU,WAAW;AAAA,EAClG;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,cAAc,KAAK;AAAA,IAC5B,UAAU;AAAA,EACZ;AACF;AA2BO,SAAS,gBAAgB,OAA+C;AAC7E,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,cAAc;AAAA,EACjC;AACA,SAAO,CAAC,eAAe,KAAK,CAAC;AAC/B;AAUO,SAAS,iBAAiB,MAAkC;AACjE,SAAO;AACT;AAGA,SAAS,cAAc,OAAwB;AAC7C,MAAI;AACF,UAAM,IAAI,KAAK,UAAU,KAAK;AAC9B,WAAO,OAAO,MAAM,WAAW,IAAI,OAAO,KAAK;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/normalize-errors.ts"],"sourcesContent":["/**\n * Wire-shape normalizer for the AdCP `Error` row used in tool responses\n * carrying per-row failures (`sync_creatives`, `sync_audiences`,\n * `sync_accounts`, `report_usage`, `acquire_rights` error arm).\n *\n * Adopters return errors in whichever shape their codebase already\n * speaks: bare strings, native `Error` instances, plain\n * `{ code, message }` objects, `AdcpError` instances thrown internally,\n * upstream-platform error objects with vendor-specific fields. This\n * helper coerces all of those into the canonical wire `Error` shape\n * (`code`, `message`, optional `field` / `suggestion` / `retry_after`\n * / `details` / `recovery`) so the framework's response validator\n * accepts the projected response without forcing every adopter to\n * hand-shape the wire envelope.\n *\n * @see AdCP wire spec: `core/error.json`\n *\n * @public\n */\n\nimport type { ErrorCode } from './decisioning/async-outcome';\n\n/**\n * Canonical wire `Error` row. Mirrors `core/error.json` —\n * `code` + `message` are required; everything else optional.\n *\n * Differs from the SDK's `AdcpStructuredError` in only one detail —\n * `recovery` is optional here (per the wire spec) but required on\n * `AdcpStructuredError` (the SDK's stricter shape for thrown errors).\n *\n * @public\n */\nexport interface NormalizedError {\n code: string;\n message: string;\n field?: string;\n suggestion?: string;\n retry_after?: number;\n details?: Record<string, unknown>;\n recovery?: 'transient' | 'correctable' | 'terminal';\n}\n\n/**\n * Coerce a single adopter-returned error value into the canonical\n * wire `Error` shape. Handles:\n *\n * - `string` → `{ code: 'GENERIC_ERROR', message: <input>, recovery: 'terminal' }`\n * - `Error` instance → `{ code: 'GENERIC_ERROR', message: err.message, recovery: 'terminal' }`\n * - `AdcpError` instance → projected to wire shape using its `code` /\n * `recovery` / `field` / `suggestion` / `retry_after` / `details`\n * - Plain object with `code` + `message` → fields whitelisted to the\n * wire shape; vendor-specific fields dropped (use `details` for\n * vendor extensions)\n * - Any other object → `{ code: 'GENERIC_ERROR', message: <safeStringify>, recovery: 'terminal' }`\n * - `null` / `undefined` → `{ code: 'GENERIC_ERROR', message: 'Unknown error', recovery: 'terminal' }`\n *\n * The `details` field, when present on the input, is shallow-copied\n * and SHOULD be passed through {@link pickSafeDetails} on the\n * adopter side before reaching this helper. `normalizeError` does NOT\n * sanitize `details` — it's the adopter's job to ensure no\n * credentials / PII / stack traces land there.\n *\n * @public\n */\nexport function normalizeError(input: unknown): NormalizedError {\n if (input == null) {\n return { code: 'GENERIC_ERROR', message: 'Unknown error', recovery: 'terminal' };\n }\n if (typeof input === 'string') {\n return { code: 'GENERIC_ERROR', message: input, recovery: 'terminal' };\n }\n // AdcpError-shaped (has `code`, optional structured fields). Detected\n // structurally rather than via instanceof so framework code in different\n // module realms (test fixtures, server-side renderers) still gets the\n // typed projection.\n if (typeof input === 'object' && 'code' in input) {\n const obj = input as Record<string, unknown>;\n const code = typeof obj.code === 'string' && obj.code.length > 0 ? obj.code : 'GENERIC_ERROR';\n const message = typeof obj.message === 'string' && obj.message.length > 0 ? obj.message : code; // fall back to code when message missing — never empty-string\n const out: NormalizedError = { code, message };\n if (typeof obj.field === 'string') out.field = obj.field;\n if (typeof obj.suggestion === 'string') out.suggestion = obj.suggestion;\n if (typeof obj.retry_after === 'number' && Number.isFinite(obj.retry_after)) {\n // Wire spec clamps retry_after to [1, 3600]\n out.retry_after = Math.max(1, Math.min(3600, Math.floor(obj.retry_after)));\n }\n if (obj.recovery === 'transient' || obj.recovery === 'correctable' || obj.recovery === 'terminal') {\n out.recovery = obj.recovery;\n }\n if (typeof obj.details === 'object' && obj.details !== null) {\n // Shallow copy to break aliasing; adopter is responsible for sanitizing\n // via pickSafeDetails before reaching here.\n out.details = { ...(obj.details as Record<string, unknown>) };\n }\n return out;\n }\n // Native Error (no `code` field, has `message`).\n if (input instanceof Error) {\n return { code: 'GENERIC_ERROR', message: input.message || 'Unknown error', recovery: 'terminal' };\n }\n // Last-resort: stringify whatever was passed.\n return {\n code: 'GENERIC_ERROR',\n message: safeStringify(input),\n recovery: 'terminal',\n };\n}\n\n/**\n * Coerce an adopter-returned errors collection into a wire-shaped\n * `Error[]`. Accepts `undefined` / `null` (returns `undefined`),\n * a single error value (wraps in array), or an array of error values\n * (each normalized via {@link normalizeError}).\n *\n * Empty arrays and arrays where every entry normalizes to the same\n * sentinel \"Unknown error\" are still emitted — the framework lets the\n * wire validator decide whether `errors: []` is acceptable for the\n * specific tool response (sync_creatives accepts empty;\n * sync_creatives_error requires non-empty).\n *\n * Use at the v6 wire-projection seam:\n *\n * ```ts\n * import { normalizeErrors } from '@adcp/client/server';\n *\n * const projected = adopterRows.map(row => ({\n * ...row,\n * errors: normalizeErrors(row.errors),\n * }));\n * ```\n *\n * @public\n */\nexport function normalizeErrors(input: unknown): NormalizedError[] | undefined {\n if (input == null) return undefined;\n if (Array.isArray(input)) {\n return input.map(normalizeError);\n }\n return [normalizeError(input)];\n}\n\n/**\n * Coerce an `ErrorCode`-typed input back to the underlying string —\n * useful when adopters pass an enum-narrowed code into a place that\n * expects the wire string. Pure-function alias for clarity at call\n * sites; the runtime is identity.\n *\n * @internal\n */\nexport function _coerceErrorCode(code: ErrorCode | string): string {\n return code;\n}\n\n/** Best-effort `JSON.stringify` that swallows circular-reference errors. */\nfunction safeStringify(input: unknown): string {\n try {\n const s = JSON.stringify(input);\n return typeof s === 'string' ? s : String(input);\n } catch {\n return '[unserializable error]';\n }\n}\n"],"mappings":"AAgEO,SAAS,eAAe,OAAiC;AAC9D,MAAI,SAAS,MAAM;AACjB,WAAO,EAAE,MAAM,iBAAiB,SAAS,iBAAiB,UAAU,WAAW;AAAA,EACjF;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,MAAM,iBAAiB,SAAS,OAAO,UAAU,WAAW;AAAA,EACvE;AAKA,MAAI,OAAO,UAAU,YAAY,UAAU,OAAO;AAChD,UAAM,MAAM;AACZ,UAAM,OAAO,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,SAAS,IAAI,IAAI,OAAO;AAC9E,UAAM,UAAU,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,IAAI,IAAI,UAAU;AAC1F,UAAM,MAAuB,EAAE,MAAM,QAAQ;AAC7C,QAAI,OAAO,IAAI,UAAU,SAAU,KAAI,QAAQ,IAAI;AACnD,QAAI,OAAO,IAAI,eAAe,SAAU,KAAI,aAAa,IAAI;AAC7D,QAAI,OAAO,IAAI,gBAAgB,YAAY,OAAO,SAAS,IAAI,WAAW,GAAG;AAE3E,UAAI,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC;AAAA,IAC3E;AACA,QAAI,IAAI,aAAa,eAAe,IAAI,aAAa,iBAAiB,IAAI,aAAa,YAAY;AACjG,UAAI,WAAW,IAAI;AAAA,IACrB;AACA,QAAI,OAAO,IAAI,YAAY,YAAY,IAAI,YAAY,MAAM;AAG3D,UAAI,UAAU,EAAE,GAAI,IAAI,QAAoC;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,EAAE,MAAM,iBAAiB,SAAS,MAAM,WAAW,iBAAiB,UAAU,WAAW;AAAA,EAClG;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,cAAc,KAAK;AAAA,IAC5B,UAAU;AAAA,EACZ;AACF;AA2BO,SAAS,gBAAgB,OAA+C;AAC7E,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,cAAc;AAAA,EACjC;AACA,SAAO,CAAC,eAAe,KAAK,CAAC;AAC/B;AAUO,SAAS,iBAAiB,MAAkC;AACjE,SAAO;AACT;AAGA,SAAS,cAAc,OAAwB;AAC7C,MAAI;AACF,UAAM,IAAI,KAAK,UAAU,KAAK;AAC9B,WAAO,OAAO,MAAM,WAAW,IAAI,OAAO,KAAK;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","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
  function defineOperationalPlatform(ops) {
8
2
  return ops;
9
3
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/operational-platform.ts"],"sourcesContent":["/**\n * `OperationalPlatform` — in-process operational contract.\n *\n * `DecisioningPlatform` covers buyer-facing MCP request dispatch:\n * `platform.sales.updateMediaBuy(req, ctx)` etc., where `ctx` is a\n * `RequestContext` built by the framework from `authInfo` via\n * `AccountStore.resolve`, threading `state`, `resolve`, `ctxMetadata`,\n * and `handoffToTask`.\n *\n * In-process consumers are different. The price-optimization poller,\n * audience-sync task poller, scheduled jobs, and the storefront\n * fan-out path do NOT have an MCP request to derive auth from. They\n * have a stored task with an access token (or, for fan-out, no token\n * — the storefront synthesizes one per upstream target). They cannot\n * honestly satisfy `RequestContext`. Every adopter doing operational\n * work would otherwise reinvent this seam.\n *\n * `OperationalPlatform` is the named contract for that seam. Five\n * methods covering the real operational surface:\n *\n * 1. `extractContext` — synthesize a per-call platform context from\n * a stored token (and optional request args, for fan-out callers).\n * The single CTX-METADATA-SAFETY boundary outside\n * `AccountStore.resolve`: anything touching credentials in an\n * in-process consumer flows through here.\n * 2. `updateMediaBuy` — required. Fan-out callers dispatch one of\n * these per upstream target.\n * 3. `getMediaBuyDelivery` — required. Pollers read delivery metrics\n * here.\n * 4. `pollAudienceStatuses` — optional. Audience-sync pollers only.\n * 5. `getProducts` — optional. Storefront bundle composition only;\n * server-side internal call, not buyer-facing dispatch.\n *\n * Naming the contract honestly — \"operational\" rather than \"adapter\"\n * — separates it from any v5 `PlatformAdapter` baggage and from\n * `DecisioningPlatform`'s MCP-request flow. Tests mock\n * `OperationalPlatform`, not the broader v6 interface.\n *\n * Errors: methods throw `AdcpError` for structured rejection, matching\n * `DecisioningPlatform`'s convention. Generic thrown `Error` /\n * `TypeError` propagate; callers catch and log per their needs.\n *\n * Status: 6.10. See adcontextprotocol/adcp-client#1530.\n *\n * @see DecisioningPlatform — buyer-facing MCP dispatch\n * @see docs/guides/CTX-METADATA-SAFETY.md — credential discipline\n * @public\n */\n\nimport type {\n GetMediaBuyDeliveryResponse,\n GetProductsResponse,\n UpdateMediaBuyRequest,\n UpdateMediaBuyResponse,\n} from '../types/tools.generated';\nimport type { RequireCacheScopeWhenProducts, ServerPayload } from '../types/server-payload';\nimport type { AudienceStatus } from './decisioning/specialisms/audiences';\n\n/**\n * Minimal context for in-process operational calls. Adopters extend\n * with platform-specific fields (advertiser id, sandbox mode, region,\n * etc.); the type parameter on `OperationalPlatform<TCtx>` carries\n * the extension through.\n *\n * `accessToken` is the only field shared across adopters: the rest of\n * the context shape is platform-internal. Pollers and scheduled jobs\n * that legitimately have no token (server-side internal scans) leave\n * it `undefined`.\n *\n * @example\n * ```ts\n * interface SnapOpCtx extends OperationalContext {\n * advertiserId: string;\n * sandbox: boolean;\n * }\n *\n * const snapOps = defineOperationalPlatform<SnapOpCtx>({\n * platformId: 'snap',\n * extractContext: async (args, sessionToken) => ({\n * accessToken: sessionToken,\n * advertiserId: String(args.advertiser_id ?? ''),\n * sandbox: Boolean(args.sandbox),\n * }),\n * // ...\n * });\n * ```\n */\nexport interface OperationalContext {\n /**\n * The access token used by upstream HTTP calls. `undefined` for\n * server-side internal scans that don't authenticate against a\n * specific tenant.\n */\n accessToken: string | undefined;\n}\n\n/**\n * In-process operational contract. Implementations dispatch to\n * upstream platform APIs from pollers, scheduled jobs, fan-out paths,\n * and other contexts that don't carry an MCP request.\n *\n * Type parameter `TCtx` extends {@link OperationalContext} to carry\n * platform-specific context fields through every method.\n */\nexport interface OperationalPlatform<TCtx extends OperationalContext = OperationalContext> {\n /**\n * Stable platform identifier matching `DecisioningPlatform`'s\n * registered name. Used by registries and routing layers to look up\n * the operational delegate by platform.\n */\n readonly platformId: string;\n\n /**\n * Synthesize an operational context from a stored token (and\n * optional request args for fan-out callers). The single\n * documented credential-synthesis path outside\n * `AccountStore.resolve` — so the only place adopters need\n * CTX-METADATA-SAFETY review on the operational side.\n *\n * Three call patterns this method serves:\n * - **Poller / scheduled job**: `args` is `{}`, `sessionToken` is\n * the stored token. Returns a context bound to that token.\n * - **Storefront fan-out**: `args` is the (scrubbed) buyer\n * request body, `sessionToken` is the storefront's master\n * credential. Returns a context for one upstream target.\n * - **Server-side internal scan**: `args` is `{}`, `sessionToken`\n * is `undefined`, `requireAuth` is `false`. Returns a\n * no-token context.\n *\n * @param args - Optional request args (storefront fan-out path)\n * @param sessionToken - Stored access token (poller path)\n * @param requireAuth - Throw `AuthMissingError` when no token is\n * available. Defaults to `true`.\n *\n * @remarks Post-migration the SDK will likely split this into\n * `synthesizeFromToken` / `synthesizeFromArgs` (see #1530 for the\n * follow-up). The combined signature today matches the v5\n * `PlatformAdapter.extractContext` shape so v5 adapters duck-type\n * satisfy this interface during migration without a wrapper.\n */\n extractContext(args: Record<string, unknown>, sessionToken?: string, requireAuth?: boolean): Promise<TCtx>;\n\n /**\n * Update a media buy upstream. Required because every operational\n * consumer assumes it — adapters that can't update media buys have\n * no business registering as operational.\n *\n * Throw `AdcpError` for structured rejection (`NOT_CANCELLABLE`,\n * `CONFLICT`, etc.). Generic thrown errors propagate to the caller.\n */\n updateMediaBuy(ctx: TCtx, request: UpdateMediaBuyRequest): Promise<ServerPayload<UpdateMediaBuyResponse>>;\n\n /**\n * Fetch delivery metrics for one or more media buys. Required for\n * the same reason as `updateMediaBuy`: every operational consumer\n * assumes it.\n *\n * `mediaBuyIds` is plural — matches the wire-spec\n * `GetMediaBuyDeliveryRequest.media_buy_ids` field (per AdCP 3.0\n * and PR #1342). Pollers that batch-query N buys in one upstream\n * call pass an array; single-buy callers pass `[id]`. Decomposed\n * here (vs. taking the full request shape) because pollers\n * synthesize requests internally and don't have a typed wire\n * payload to thread.\n *\n * `args` carries optional adopter-specific pass-through (e.g.\n * tenant-scoped query parameters); pollers leave it `undefined`.\n */\n getMediaBuyDelivery(\n ctx: TCtx,\n mediaBuyIds: readonly string[],\n startTime: string,\n endTime: string,\n args?: Record<string, unknown>\n ): Promise<ServerPayload<GetMediaBuyDeliveryResponse>>;\n\n /**\n * Poll upstream for the current status of one or more audiences.\n * Optional — only audience-sync pollers need this.\n *\n * Takes opaque `platformData` (whatever the adapter stored when\n * initiating the sync) plus a fresh access token. No operational\n * context is threaded because the original sync may have been\n * initiated under a now-expired auth principal; the poller carries\n * a freshly-resolved token from its own credential store.\n *\n * **`platformData` is for opaque upstream IDs only — never for\n * bearer tokens.** The fresh `accessToken` argument is the blessed\n * credential channel; reading a stale token from `platformData`\n * defeats the design and lands requests with revoked auth.\n *\n * Returns a `Map<audience_id, AudienceStatus>`. Audiences not\n * resolvable upstream are omitted from the map. Throw\n * `AdcpError('REFERENCE_NOT_FOUND')` only when the entire batch\n * is unresolvable for the tenant.\n *\n * Plural method name aligns with `AudiencePlatform.pollAudienceStatuses`\n * (the buyer-facing analog), which also returns\n * `Map<string, AudienceStatus>`. Signature differs because operational\n * callers don't have a `RequestContext` to thread.\n */\n pollAudienceStatuses?(\n platformData: Record<string, unknown>,\n accessToken: string\n ): Promise<Map<string, AudienceStatus>>;\n\n /**\n * Discover advertising products. Used by storefront bundle services\n * to query upstream platforms for products available for bundling\n * — server-side internal call, not buyer-facing dispatch.\n *\n * Optional: bundle-search is opt-in per storefront, and not every\n * upstream platform exposes a product-discovery surface.\n *\n * Signature differs from `SalesPlatform.getProducts` because the\n * caller is a storefront bundle service, not an MCP request\n * handler — they have a brief and brand context, not a typed\n * `GetProductsRequest` wire payload.\n */\n getProducts?(\n ctx: TCtx,\n brief: string,\n contextId?: string,\n brand?: Record<string, unknown>,\n sourceChain?: readonly string[]\n ): Promise<RequireCacheScopeWhenProducts<ServerPayload<GetProductsResponse>>>;\n}\n\n/**\n * Type-level identity for an `OperationalPlatform` object literal.\n * Forces the contextual type so handler bodies get typed `ctx` and\n * `request` parameters in TypeScript without an explicit annotation.\n *\n * Mirrors the `definePlatform` family for `DecisioningPlatform`\n * sub-interfaces — see `decisioning/platform-helpers.ts`.\n *\n * @example\n * ```ts\n * import { AuthMissingError, defineOperationalPlatform, type OperationalContext } from '@adcp/sdk/server';\n *\n * interface SnapOpCtx extends OperationalContext {\n * advertiserId: string;\n * }\n *\n * export const snapOperational = defineOperationalPlatform<SnapOpCtx>({\n * platformId: 'snap',\n * extractContext: async (args, sessionToken, requireAuth = true) => {\n * if (!sessionToken && requireAuth) {\n * throw new AuthMissingError({ message: 'No Snap token available' });\n * }\n * return {\n * accessToken: sessionToken,\n * advertiserId: String(args.advertiser_id ?? ''),\n * };\n * },\n * updateMediaBuy: async (ctx, request) => {\n * // ctx.advertiserId typed ✓; request: UpdateMediaBuyRequest ✓\n * return upstream.update(ctx, request);\n * },\n * getMediaBuyDelivery: async (ctx, id, start, end) => {\n * return upstream.delivery(ctx, id, start, end);\n * },\n * });\n * ```\n */\nexport function defineOperationalPlatform<TCtx extends OperationalContext = OperationalContext>(\n ops: OperationalPlatform<TCtx>\n): OperationalPlatform<TCtx> {\n return ops;\n}\n"],"mappings":";;;;;;AAyQO,SAAS,0BACd,KAC2B;AAC3B,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/operational-platform.ts"],"sourcesContent":["/**\n * `OperationalPlatform` — in-process operational contract.\n *\n * `DecisioningPlatform` covers buyer-facing MCP request dispatch:\n * `platform.sales.updateMediaBuy(req, ctx)` etc., where `ctx` is a\n * `RequestContext` built by the framework from `authInfo` via\n * `AccountStore.resolve`, threading `state`, `resolve`, `ctxMetadata`,\n * and `handoffToTask`.\n *\n * In-process consumers are different. The price-optimization poller,\n * audience-sync task poller, scheduled jobs, and the storefront\n * fan-out path do NOT have an MCP request to derive auth from. They\n * have a stored task with an access token (or, for fan-out, no token\n * — the storefront synthesizes one per upstream target). They cannot\n * honestly satisfy `RequestContext`. Every adopter doing operational\n * work would otherwise reinvent this seam.\n *\n * `OperationalPlatform` is the named contract for that seam. Five\n * methods covering the real operational surface:\n *\n * 1. `extractContext` — synthesize a per-call platform context from\n * a stored token (and optional request args, for fan-out callers).\n * The single CTX-METADATA-SAFETY boundary outside\n * `AccountStore.resolve`: anything touching credentials in an\n * in-process consumer flows through here.\n * 2. `updateMediaBuy` — required. Fan-out callers dispatch one of\n * these per upstream target.\n * 3. `getMediaBuyDelivery` — required. Pollers read delivery metrics\n * here.\n * 4. `pollAudienceStatuses` — optional. Audience-sync pollers only.\n * 5. `getProducts` — optional. Storefront bundle composition only;\n * server-side internal call, not buyer-facing dispatch.\n *\n * Naming the contract honestly — \"operational\" rather than \"adapter\"\n * — separates it from any v5 `PlatformAdapter` baggage and from\n * `DecisioningPlatform`'s MCP-request flow. Tests mock\n * `OperationalPlatform`, not the broader v6 interface.\n *\n * Errors: methods throw `AdcpError` for structured rejection, matching\n * `DecisioningPlatform`'s convention. Generic thrown `Error` /\n * `TypeError` propagate; callers catch and log per their needs.\n *\n * Status: 6.10. See adcontextprotocol/adcp-client#1530.\n *\n * @see DecisioningPlatform — buyer-facing MCP dispatch\n * @see docs/guides/CTX-METADATA-SAFETY.md — credential discipline\n * @public\n */\n\nimport type {\n GetMediaBuyDeliveryResponse,\n GetProductsResponse,\n UpdateMediaBuyRequest,\n UpdateMediaBuyResponse,\n} from '../types/tools.generated';\nimport type { RequireCacheScopeWhenProducts, ServerPayload } from '../types/server-payload';\nimport type { AudienceStatus } from './decisioning/specialisms/audiences';\n\n/**\n * Minimal context for in-process operational calls. Adopters extend\n * with platform-specific fields (advertiser id, sandbox mode, region,\n * etc.); the type parameter on `OperationalPlatform<TCtx>` carries\n * the extension through.\n *\n * `accessToken` is the only field shared across adopters: the rest of\n * the context shape is platform-internal. Pollers and scheduled jobs\n * that legitimately have no token (server-side internal scans) leave\n * it `undefined`.\n *\n * @example\n * ```ts\n * interface SnapOpCtx extends OperationalContext {\n * advertiserId: string;\n * sandbox: boolean;\n * }\n *\n * const snapOps = defineOperationalPlatform<SnapOpCtx>({\n * platformId: 'snap',\n * extractContext: async (args, sessionToken) => ({\n * accessToken: sessionToken,\n * advertiserId: String(args.advertiser_id ?? ''),\n * sandbox: Boolean(args.sandbox),\n * }),\n * // ...\n * });\n * ```\n */\nexport interface OperationalContext {\n /**\n * The access token used by upstream HTTP calls. `undefined` for\n * server-side internal scans that don't authenticate against a\n * specific tenant.\n */\n accessToken: string | undefined;\n}\n\n/**\n * In-process operational contract. Implementations dispatch to\n * upstream platform APIs from pollers, scheduled jobs, fan-out paths,\n * and other contexts that don't carry an MCP request.\n *\n * Type parameter `TCtx` extends {@link OperationalContext} to carry\n * platform-specific context fields through every method.\n */\nexport interface OperationalPlatform<TCtx extends OperationalContext = OperationalContext> {\n /**\n * Stable platform identifier matching `DecisioningPlatform`'s\n * registered name. Used by registries and routing layers to look up\n * the operational delegate by platform.\n */\n readonly platformId: string;\n\n /**\n * Synthesize an operational context from a stored token (and\n * optional request args for fan-out callers). The single\n * documented credential-synthesis path outside\n * `AccountStore.resolve` — so the only place adopters need\n * CTX-METADATA-SAFETY review on the operational side.\n *\n * Three call patterns this method serves:\n * - **Poller / scheduled job**: `args` is `{}`, `sessionToken` is\n * the stored token. Returns a context bound to that token.\n * - **Storefront fan-out**: `args` is the (scrubbed) buyer\n * request body, `sessionToken` is the storefront's master\n * credential. Returns a context for one upstream target.\n * - **Server-side internal scan**: `args` is `{}`, `sessionToken`\n * is `undefined`, `requireAuth` is `false`. Returns a\n * no-token context.\n *\n * @param args - Optional request args (storefront fan-out path)\n * @param sessionToken - Stored access token (poller path)\n * @param requireAuth - Throw `AuthMissingError` when no token is\n * available. Defaults to `true`.\n *\n * @remarks Post-migration the SDK will likely split this into\n * `synthesizeFromToken` / `synthesizeFromArgs` (see #1530 for the\n * follow-up). The combined signature today matches the v5\n * `PlatformAdapter.extractContext` shape so v5 adapters duck-type\n * satisfy this interface during migration without a wrapper.\n */\n extractContext(args: Record<string, unknown>, sessionToken?: string, requireAuth?: boolean): Promise<TCtx>;\n\n /**\n * Update a media buy upstream. Required because every operational\n * consumer assumes it — adapters that can't update media buys have\n * no business registering as operational.\n *\n * Throw `AdcpError` for structured rejection (`NOT_CANCELLABLE`,\n * `CONFLICT`, etc.). Generic thrown errors propagate to the caller.\n */\n updateMediaBuy(ctx: TCtx, request: UpdateMediaBuyRequest): Promise<ServerPayload<UpdateMediaBuyResponse>>;\n\n /**\n * Fetch delivery metrics for one or more media buys. Required for\n * the same reason as `updateMediaBuy`: every operational consumer\n * assumes it.\n *\n * `mediaBuyIds` is plural — matches the wire-spec\n * `GetMediaBuyDeliveryRequest.media_buy_ids` field (per AdCP 3.0\n * and PR #1342). Pollers that batch-query N buys in one upstream\n * call pass an array; single-buy callers pass `[id]`. Decomposed\n * here (vs. taking the full request shape) because pollers\n * synthesize requests internally and don't have a typed wire\n * payload to thread.\n *\n * `args` carries optional adopter-specific pass-through (e.g.\n * tenant-scoped query parameters); pollers leave it `undefined`.\n */\n getMediaBuyDelivery(\n ctx: TCtx,\n mediaBuyIds: readonly string[],\n startTime: string,\n endTime: string,\n args?: Record<string, unknown>\n ): Promise<ServerPayload<GetMediaBuyDeliveryResponse>>;\n\n /**\n * Poll upstream for the current status of one or more audiences.\n * Optional — only audience-sync pollers need this.\n *\n * Takes opaque `platformData` (whatever the adapter stored when\n * initiating the sync) plus a fresh access token. No operational\n * context is threaded because the original sync may have been\n * initiated under a now-expired auth principal; the poller carries\n * a freshly-resolved token from its own credential store.\n *\n * **`platformData` is for opaque upstream IDs only — never for\n * bearer tokens.** The fresh `accessToken` argument is the blessed\n * credential channel; reading a stale token from `platformData`\n * defeats the design and lands requests with revoked auth.\n *\n * Returns a `Map<audience_id, AudienceStatus>`. Audiences not\n * resolvable upstream are omitted from the map. Throw\n * `AdcpError('REFERENCE_NOT_FOUND')` only when the entire batch\n * is unresolvable for the tenant.\n *\n * Plural method name aligns with `AudiencePlatform.pollAudienceStatuses`\n * (the buyer-facing analog), which also returns\n * `Map<string, AudienceStatus>`. Signature differs because operational\n * callers don't have a `RequestContext` to thread.\n */\n pollAudienceStatuses?(\n platformData: Record<string, unknown>,\n accessToken: string\n ): Promise<Map<string, AudienceStatus>>;\n\n /**\n * Discover advertising products. Used by storefront bundle services\n * to query upstream platforms for products available for bundling\n * — server-side internal call, not buyer-facing dispatch.\n *\n * Optional: bundle-search is opt-in per storefront, and not every\n * upstream platform exposes a product-discovery surface.\n *\n * Signature differs from `SalesPlatform.getProducts` because the\n * caller is a storefront bundle service, not an MCP request\n * handler — they have a brief and brand context, not a typed\n * `GetProductsRequest` wire payload.\n */\n getProducts?(\n ctx: TCtx,\n brief: string,\n contextId?: string,\n brand?: Record<string, unknown>,\n sourceChain?: readonly string[]\n ): Promise<RequireCacheScopeWhenProducts<ServerPayload<GetProductsResponse>>>;\n}\n\n/**\n * Type-level identity for an `OperationalPlatform` object literal.\n * Forces the contextual type so handler bodies get typed `ctx` and\n * `request` parameters in TypeScript without an explicit annotation.\n *\n * Mirrors the `definePlatform` family for `DecisioningPlatform`\n * sub-interfaces — see `decisioning/platform-helpers.ts`.\n *\n * @example\n * ```ts\n * import { AuthMissingError, defineOperationalPlatform, type OperationalContext } from '@adcp/sdk/server';\n *\n * interface SnapOpCtx extends OperationalContext {\n * advertiserId: string;\n * }\n *\n * export const snapOperational = defineOperationalPlatform<SnapOpCtx>({\n * platformId: 'snap',\n * extractContext: async (args, sessionToken, requireAuth = true) => {\n * if (!sessionToken && requireAuth) {\n * throw new AuthMissingError({ message: 'No Snap token available' });\n * }\n * return {\n * accessToken: sessionToken,\n * advertiserId: String(args.advertiser_id ?? ''),\n * };\n * },\n * updateMediaBuy: async (ctx, request) => {\n * // ctx.advertiserId typed ✓; request: UpdateMediaBuyRequest ✓\n * return upstream.update(ctx, request);\n * },\n * getMediaBuyDelivery: async (ctx, id, start, end) => {\n * return upstream.delivery(ctx, id, start, end);\n * },\n * });\n * ```\n */\nexport function defineOperationalPlatform<TCtx extends OperationalContext = OperationalContext>(\n ops: OperationalPlatform<TCtx>\n): OperationalPlatform<TCtx> {\n return ops;\n}\n"],"mappings":"AAyQO,SAAS,0BACd,KAC2B;AAC3B,SAAO;AACT;","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 DEFAULT_OPTIONS = {
8
2
  maxDepth: 2,
9
3
  maxSizeBytes: 2048
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/pick-safe-details.ts"],"sourcesContent":["/**\n * Security primitive for the `details` field on `AdcpError` and the\n * `Error` wire row. Adopters fronting upstream platforms (GAM, Snap,\n * retail-media APIs, internal billing systems) often want to surface\n * upstream error context to buyers — but raw upstream errors carry\n * credentials, PII, internal stack traces, request IDs that leak\n * tenant identity, and other liability surfaces that MUST NOT cross\n * the wire boundary.\n *\n * `pickSafeDetails(input, allowlist, opts?)` is an explicit-allowlist\n * sanitizer: only keys in the allowlist survive, with optional caps\n * on depth and serialized size. Returns `undefined` when the input is\n * not a plain object or the allowlist filter produces an empty\n * result, so callers can spread the return into an optional `details`\n * field without polluting it with `{}`.\n *\n * Adopters should call this BEFORE constructing the `AdcpError` /\n * wire `Error` row. The framework's `normalizeError` does NOT\n * sanitize details — it shallow-copies whatever was passed.\n *\n * @example\n * ```ts\n * import { pickSafeDetails } from '@adcp/client/server';\n *\n * try {\n * await gamClient.createOrder(req);\n * } catch (upstreamErr) {\n * throw new AdcpError('UPSTREAM_REJECTED', {\n * recovery: 'transient',\n * message: 'Ad server rejected the order',\n * // Allowlist: only safe upstream fields cross the wire\n * details: pickSafeDetails(upstreamErr, [\n * 'http_status',\n * 'request_id',\n * 'gam_error_code',\n * ]),\n * });\n * }\n * ```\n *\n * @public\n */\n\nexport interface PickSafeDetailsOptions {\n /**\n * Maximum nesting depth retained in the result. `undefined` keeps\n * the input unchanged at any depth; values like `2` keep top-level\n * + one nested level. Strings, numbers, booleans, and null are\n * leaves; arrays and plain objects count as a level.\n *\n * Default: `2` — top-level + one nested level. Caps cardinality\n * blast radius from accidentally-recursive upstream error objects.\n */\n maxDepth?: number;\n\n /**\n * Maximum serialized JSON byte size of the result (best-effort\n * UTF-8 estimate via `JSON.stringify().length`). When the projected\n * result exceeds this, returns `undefined` rather than truncating —\n * adopters should choose a tighter allowlist if they hit the cap.\n *\n * Default: `2048` bytes. Wire envelopes shouldn't carry kilobytes\n * of details; if you need that, ship via `publishStatusChange` or\n * `task_registry.progress`.\n */\n maxSizeBytes?: number;\n}\n\nconst DEFAULT_OPTIONS: Required<PickSafeDetailsOptions> = {\n maxDepth: 2,\n maxSizeBytes: 2048,\n};\n\n/**\n * Filter `input` to keys named in `allowlist`, depth-capped and\n * size-capped. Returns `undefined` when the result is empty or\n * exceeds the size cap so callers can spread the value into an\n * optional `details` field without polluting it.\n *\n * Properties NOT in the allowlist are dropped silently (no warning;\n * the design assumes the allowlist is the contract). Nested objects\n * are recursively filtered with the SAME allowlist — there is no\n * per-key allowlist for nested fields. Adopters who need per-level\n * filtering should call `pickSafeDetails` recursively on each\n * nested value.\n *\n * Common-sense behaviors:\n * - `null` / `undefined` / non-object input → `undefined`\n * - Empty result after filtering → `undefined`\n * - Arrays at the top level → `undefined` (use a wrapping object)\n * - Functions and Symbols are dropped\n * - Date / RegExp / Error / Map / Set are dropped (use a string\n * allowlist of primitive fields, or pre-shape the input)\n *\n * @public\n */\nexport function pickSafeDetails(\n input: unknown,\n allowlist: readonly string[],\n opts?: PickSafeDetailsOptions\n): Record<string, unknown> | undefined {\n if (!isPlainObject(input)) return undefined;\n if (allowlist.length === 0) return undefined;\n\n const maxDepth = opts?.maxDepth ?? DEFAULT_OPTIONS.maxDepth;\n const maxSize = opts?.maxSizeBytes ?? DEFAULT_OPTIONS.maxSizeBytes;\n const allowSet = new Set(allowlist);\n\n const result = filterByAllowlist(input, allowSet, maxDepth);\n if (result == null || Object.keys(result).length === 0) return undefined;\n\n // Size cap. Use JSON.stringify length as a UTF-8-ish proxy.\n // Adopters who need exact byte counting should sanitize ahead of\n // pickSafeDetails.\n let serialized: string;\n try {\n serialized = JSON.stringify(result);\n } catch {\n // Circular reference snuck through (shouldn't happen for plain\n // objects but defensive). Return undefined rather than half-data.\n return undefined;\n }\n if (serialized.length > maxSize) return undefined;\n\n return result;\n}\n\nfunction filterByAllowlist(\n obj: Record<string, unknown>,\n allow: ReadonlySet<string>,\n remainingDepth: number\n): Record<string, unknown> | null {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (!allow.has(key)) continue;\n const value = obj[key];\n const safe = sanitizeValue(value, allow, remainingDepth - 1);\n // Drop undefined results so the caller sees only present keys.\n if (safe !== undefined) out[key] = safe;\n }\n return Object.keys(out).length === 0 ? null : out;\n}\n\nfunction sanitizeValue(value: unknown, allow: ReadonlySet<string>, remainingDepth: number): unknown {\n // Primitives pass through.\n if (value === null) return null;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value;\n if (t === 'function' || t === 'symbol' || t === 'undefined' || t === 'bigint') return undefined;\n\n if (Array.isArray(value)) {\n // Arrays don't count as a depth level — only plain objects do.\n // Pass items through with the SAME remainingDepth so an array-of-\n // objects gets the same nesting budget as a bare object would.\n const mapped = value.map(v => sanitizeValue(v, allow, remainingDepth));\n return mapped.filter(v => v !== undefined);\n }\n\n if (isPlainObject(value)) {\n if (remainingDepth <= 0) return undefined;\n const filtered = filterByAllowlist(value, allow, remainingDepth);\n return filtered ?? undefined;\n }\n\n // Date / RegExp / Map / Set / Error / class instances — drop.\n // Adopters who need these should pre-shape into primitives.\n return undefined;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n // Only plain objects (not Date, RegExp, Map, Set, class instances).\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n"],"mappings":";;;;;;AAoEA,MAAM,kBAAoD;AAAA,EACxD,UAAU;AAAA,EACV,cAAc;AAChB;AAyBO,SAAS,gBACd,OACA,WACA,MACqC;AACrC,MAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAM,WAAW,MAAM,YAAY,gBAAgB;AACnD,QAAM,UAAU,MAAM,gBAAgB,gBAAgB;AACtD,QAAM,WAAW,IAAI,IAAI,SAAS;AAElC,QAAM,SAAS,kBAAkB,OAAO,UAAU,QAAQ;AAC1D,MAAI,UAAU,QAAQ,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AAK/D,MAAI;AACJ,MAAI;AACF,iBAAa,KAAK,UAAU,MAAM;AAAA,EACpC,QAAQ;AAGN,WAAO;AAAA,EACT;AACA,MAAI,WAAW,SAAS,QAAS,QAAO;AAExC,SAAO;AACT;AAEA,SAAS,kBACP,KACA,OACA,gBACgC;AAChC,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AAClC,QAAI,CAAC,MAAM,IAAI,GAAG,EAAG;AACrB,UAAM,QAAQ,IAAI,GAAG;AACrB,UAAM,OAAO,cAAc,OAAO,OAAO,iBAAiB,CAAC;AAE3D,QAAI,SAAS,OAAW,KAAI,GAAG,IAAI;AAAA,EACrC;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW,IAAI,OAAO;AAChD;AAEA,SAAS,cAAc,OAAgB,OAA4B,gBAAiC;AAElG,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,YAAY,MAAM,YAAY,MAAM,UAAW,QAAO;AAChE,MAAI,MAAM,cAAc,MAAM,YAAY,MAAM,eAAe,MAAM,SAAU,QAAO;AAEtF,MAAI,MAAM,QAAQ,KAAK,GAAG;AAIxB,UAAM,SAAS,MAAM,IAAI,OAAK,cAAc,GAAG,OAAO,cAAc,CAAC;AACrE,WAAO,OAAO,OAAO,OAAK,MAAM,MAAS;AAAA,EAC3C;AAEA,MAAI,cAAc,KAAK,GAAG;AACxB,QAAI,kBAAkB,EAAG,QAAO;AAChC,UAAM,WAAW,kBAAkB,OAAO,OAAO,cAAc;AAC/D,WAAO,YAAY;AAAA,EACrB;AAIA,SAAO;AACT;AAEA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AAEjC,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,SAAO,UAAU,OAAO,aAAa,UAAU;AACjD;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/pick-safe-details.ts"],"sourcesContent":["/**\n * Security primitive for the `details` field on `AdcpError` and the\n * `Error` wire row. Adopters fronting upstream platforms (GAM, Snap,\n * retail-media APIs, internal billing systems) often want to surface\n * upstream error context to buyers — but raw upstream errors carry\n * credentials, PII, internal stack traces, request IDs that leak\n * tenant identity, and other liability surfaces that MUST NOT cross\n * the wire boundary.\n *\n * `pickSafeDetails(input, allowlist, opts?)` is an explicit-allowlist\n * sanitizer: only keys in the allowlist survive, with optional caps\n * on depth and serialized size. Returns `undefined` when the input is\n * not a plain object or the allowlist filter produces an empty\n * result, so callers can spread the return into an optional `details`\n * field without polluting it with `{}`.\n *\n * Adopters should call this BEFORE constructing the `AdcpError` /\n * wire `Error` row. The framework's `normalizeError` does NOT\n * sanitize details — it shallow-copies whatever was passed.\n *\n * @example\n * ```ts\n * import { pickSafeDetails } from '@adcp/client/server';\n *\n * try {\n * await gamClient.createOrder(req);\n * } catch (upstreamErr) {\n * throw new AdcpError('UPSTREAM_REJECTED', {\n * recovery: 'transient',\n * message: 'Ad server rejected the order',\n * // Allowlist: only safe upstream fields cross the wire\n * details: pickSafeDetails(upstreamErr, [\n * 'http_status',\n * 'request_id',\n * 'gam_error_code',\n * ]),\n * });\n * }\n * ```\n *\n * @public\n */\n\nexport interface PickSafeDetailsOptions {\n /**\n * Maximum nesting depth retained in the result. `undefined` keeps\n * the input unchanged at any depth; values like `2` keep top-level\n * + one nested level. Strings, numbers, booleans, and null are\n * leaves; arrays and plain objects count as a level.\n *\n * Default: `2` — top-level + one nested level. Caps cardinality\n * blast radius from accidentally-recursive upstream error objects.\n */\n maxDepth?: number;\n\n /**\n * Maximum serialized JSON byte size of the result (best-effort\n * UTF-8 estimate via `JSON.stringify().length`). When the projected\n * result exceeds this, returns `undefined` rather than truncating —\n * adopters should choose a tighter allowlist if they hit the cap.\n *\n * Default: `2048` bytes. Wire envelopes shouldn't carry kilobytes\n * of details; if you need that, ship via `publishStatusChange` or\n * `task_registry.progress`.\n */\n maxSizeBytes?: number;\n}\n\nconst DEFAULT_OPTIONS: Required<PickSafeDetailsOptions> = {\n maxDepth: 2,\n maxSizeBytes: 2048,\n};\n\n/**\n * Filter `input` to keys named in `allowlist`, depth-capped and\n * size-capped. Returns `undefined` when the result is empty or\n * exceeds the size cap so callers can spread the value into an\n * optional `details` field without polluting it.\n *\n * Properties NOT in the allowlist are dropped silently (no warning;\n * the design assumes the allowlist is the contract). Nested objects\n * are recursively filtered with the SAME allowlist — there is no\n * per-key allowlist for nested fields. Adopters who need per-level\n * filtering should call `pickSafeDetails` recursively on each\n * nested value.\n *\n * Common-sense behaviors:\n * - `null` / `undefined` / non-object input → `undefined`\n * - Empty result after filtering → `undefined`\n * - Arrays at the top level → `undefined` (use a wrapping object)\n * - Functions and Symbols are dropped\n * - Date / RegExp / Error / Map / Set are dropped (use a string\n * allowlist of primitive fields, or pre-shape the input)\n *\n * @public\n */\nexport function pickSafeDetails(\n input: unknown,\n allowlist: readonly string[],\n opts?: PickSafeDetailsOptions\n): Record<string, unknown> | undefined {\n if (!isPlainObject(input)) return undefined;\n if (allowlist.length === 0) return undefined;\n\n const maxDepth = opts?.maxDepth ?? DEFAULT_OPTIONS.maxDepth;\n const maxSize = opts?.maxSizeBytes ?? DEFAULT_OPTIONS.maxSizeBytes;\n const allowSet = new Set(allowlist);\n\n const result = filterByAllowlist(input, allowSet, maxDepth);\n if (result == null || Object.keys(result).length === 0) return undefined;\n\n // Size cap. Use JSON.stringify length as a UTF-8-ish proxy.\n // Adopters who need exact byte counting should sanitize ahead of\n // pickSafeDetails.\n let serialized: string;\n try {\n serialized = JSON.stringify(result);\n } catch {\n // Circular reference snuck through (shouldn't happen for plain\n // objects but defensive). Return undefined rather than half-data.\n return undefined;\n }\n if (serialized.length > maxSize) return undefined;\n\n return result;\n}\n\nfunction filterByAllowlist(\n obj: Record<string, unknown>,\n allow: ReadonlySet<string>,\n remainingDepth: number\n): Record<string, unknown> | null {\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n if (!allow.has(key)) continue;\n const value = obj[key];\n const safe = sanitizeValue(value, allow, remainingDepth - 1);\n // Drop undefined results so the caller sees only present keys.\n if (safe !== undefined) out[key] = safe;\n }\n return Object.keys(out).length === 0 ? null : out;\n}\n\nfunction sanitizeValue(value: unknown, allow: ReadonlySet<string>, remainingDepth: number): unknown {\n // Primitives pass through.\n if (value === null) return null;\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') return value;\n if (t === 'function' || t === 'symbol' || t === 'undefined' || t === 'bigint') return undefined;\n\n if (Array.isArray(value)) {\n // Arrays don't count as a depth level — only plain objects do.\n // Pass items through with the SAME remainingDepth so an array-of-\n // objects gets the same nesting budget as a bare object would.\n const mapped = value.map(v => sanitizeValue(v, allow, remainingDepth));\n return mapped.filter(v => v !== undefined);\n }\n\n if (isPlainObject(value)) {\n if (remainingDepth <= 0) return undefined;\n const filtered = filterByAllowlist(value, allow, remainingDepth);\n return filtered ?? undefined;\n }\n\n // Date / RegExp / Map / Set / Error / class instances — drop.\n // Adopters who need these should pre-shape into primitives.\n return undefined;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n // Only plain objects (not Date, RegExp, Map, Set, class instances).\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n"],"mappings":"AAoEA,MAAM,kBAAoD;AAAA,EACxD,UAAU;AAAA,EACV,cAAc;AAChB;AAyBO,SAAS,gBACd,OACA,WACA,MACqC;AACrC,MAAI,CAAC,cAAc,KAAK,EAAG,QAAO;AAClC,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QAAM,WAAW,MAAM,YAAY,gBAAgB;AACnD,QAAM,UAAU,MAAM,gBAAgB,gBAAgB;AACtD,QAAM,WAAW,IAAI,IAAI,SAAS;AAElC,QAAM,SAAS,kBAAkB,OAAO,UAAU,QAAQ;AAC1D,MAAI,UAAU,QAAQ,OAAO,KAAK,MAAM,EAAE,WAAW,EAAG,QAAO;AAK/D,MAAI;AACJ,MAAI;AACF,iBAAa,KAAK,UAAU,MAAM;AAAA,EACpC,QAAQ;AAGN,WAAO;AAAA,EACT;AACA,MAAI,WAAW,SAAS,QAAS,QAAO;AAExC,SAAO;AACT;AAEA,SAAS,kBACP,KACA,OACA,gBACgC;AAChC,QAAM,MAA+B,CAAC;AACtC,aAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AAClC,QAAI,CAAC,MAAM,IAAI,GAAG,EAAG;AACrB,UAAM,QAAQ,IAAI,GAAG;AACrB,UAAM,OAAO,cAAc,OAAO,OAAO,iBAAiB,CAAC;AAE3D,QAAI,SAAS,OAAW,KAAI,GAAG,IAAI;AAAA,EACrC;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW,IAAI,OAAO;AAChD;AAEA,SAAS,cAAc,OAAgB,OAA4B,gBAAiC;AAElG,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,IAAI,OAAO;AACjB,MAAI,MAAM,YAAY,MAAM,YAAY,MAAM,UAAW,QAAO;AAChE,MAAI,MAAM,cAAc,MAAM,YAAY,MAAM,eAAe,MAAM,SAAU,QAAO;AAEtF,MAAI,MAAM,QAAQ,KAAK,GAAG;AAIxB,UAAM,SAAS,MAAM,IAAI,OAAK,cAAc,GAAG,OAAO,cAAc,CAAC;AACrE,WAAO,OAAO,OAAO,OAAK,MAAM,MAAS;AAAA,EAC3C;AAEA,MAAI,cAAc,KAAK,GAAG;AACxB,QAAI,kBAAkB,EAAG,QAAO;AAChC,UAAM,WAAW,kBAAkB,OAAO,OAAO,cAAc;AAC/D,WAAO,YAAY;AAAA,EACrB;AAIA,SAAO;AACT;AAEA,SAAS,cAAc,OAAkD;AACvE,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AAEjC,QAAM,QAAQ,OAAO,eAAe,KAAK;AACzC,SAAO,UAAU,OAAO,aAAa,UAAU;AACjD;","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 { Agent, fetch as undiciFetch } from "undici";
8
2
  import { lookup as nativeDnsLookup } from "node:dns";
9
3
  import { isIPv6 } from "node:net";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/pin-and-bind-fetch.ts"],"sourcesContent":["/**\n * Pin-and-bind fetch — DNS-rebinding-resistant `fetch` for outbound webhook\n * delivery and other callbacks where the destination is buyer-supplied.\n *\n * The problem: validating a `push_notification_config.url`'s LITERAL hostname\n * against an SSRF deny list does not protect against a DNS-rebinding attack.\n * A buyer can register `https://rebind.attacker.com/`, pass the literal-host\n * check, and then flip the A-record TTL to `169.254.169.254` (cloud metadata)\n * or `127.0.0.1` (loopback) before the webhook fires. Node's `fetch` resolves\n * the host fresh at request time, gets the rebound IP, and posts the\n * signed payload to the attacker-controlled destination.\n *\n * The fix: control DNS resolution and connect-target inside the fetch itself.\n * 1. Resolve the hostname.\n * 2. Validate every resolved IP against the SSRF policy (CIDR deny lists,\n * metadata-host names, scheme rules).\n * 3. Pin the connection to the validated IP — undici opens TCP/TLS to that\n * specific address, but the original hostname is preserved for TLS SNI\n * and the `Host:` header so HTTPS routing still works.\n *\n * Implementation note: undici's `Agent` accepts a `connect.lookup` callback\n * with the same signature as `dns.lookup`. We hook the callback, resolve via\n * `dns.lookup({ all: true })` to see EVERY address the host can reach, run\n * the resolved IPs through {@link enforceSsrfPolicyResolved}, and only return\n * a pinned address when every resolved IP is in an allowed range. This\n * matches the AdCP substitution-observer SSRF contract — a host that\n * resolves to *any* denied IP is treated as suspect and rejected wholesale.\n */\n\nimport { Agent, fetch as undiciFetch, type Dispatcher } from 'undici';\nimport { lookup as nativeDnsLookup, type LookupAddress } from 'node:dns';\nimport { isIPv6 } from 'node:net';\n\nimport { enforceSsrfPolicy, enforceSsrfPolicyResolved } from '../substitution/observer/ssrf';\nimport type { SsrfPolicy } from '../substitution/types';\n\n/**\n * Default SSRF policy for outbound webhook delivery. Stricter than\n * `DEFAULT_SSRF_POLICY` (substitution observer) only in that it allows\n * `host_literal_policy: 'allow'` — webhook URLs MAY use IP literals\n * (e.g. `https://203.0.113.10/cb`) as long as the IP is not in a denied\n * CIDR range. Schemes restricted to https; signed webhooks SHOULD be\n * delivered over TLS.\n *\n * For storyboard / in-process tests where the receiver runs on\n * `http://127.0.0.1:port`, use {@link LOOPBACK_OK_WEBHOOK_SSRF_POLICY}\n * instead. That preset relaxes only the loopback + http rules and keeps\n * every other deny range — adopters get most of the SSRF protection\n * during tests without disabling pin-and-bind entirely.\n */\nexport const WEBHOOK_SSRF_POLICY: SsrfPolicy = Object.freeze({\n schemes_allowed: Object.freeze(['https']),\n schemes_denied: Object.freeze(['http', 'file', 'gopher', 'ftp', 'ftps', 'data', 'javascript', 'about', 'ws', 'wss']),\n hosts_denied_ipv4_cidrs: Object.freeze([\n '0.0.0.0/8',\n '10.0.0.0/8',\n '100.64.0.0/10',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '172.16.0.0/12',\n '192.0.0.0/24',\n '192.168.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n ]),\n hosts_denied_ipv6_cidrs: Object.freeze([\n '::1/128',\n '::/128',\n '::ffff:0:0/96',\n '64:ff9b::/96',\n 'fc00::/7',\n 'fe80::/10',\n 'ff00::/8',\n ]),\n hosts_denied_metadata: Object.freeze([\n 'metadata.google.internal',\n 'metadata',\n 'metadata.packet.net',\n 'fd00:ec2::254',\n ]),\n host_literal_policy: 'allow',\n}) as SsrfPolicy;\n\n/**\n * Pin-and-bind policy that allows http URLs and IPv4/IPv6 loopback so\n * adopters can enable pin-and-bind for production webhook delivery while\n * keeping storyboard / in-process tests working — `createWebhookReceiver`\n * listens on `http://127.0.0.1:port`. Every other private CIDR, metadata\n * host, and link-local range is still denied, so loopback is the only\n * relaxation. Pass to `createPinAndBindFetch({ policy })` from your test\n * fixture or storyboard runner harness; do NOT use in production.\n */\nexport const LOOPBACK_OK_WEBHOOK_SSRF_POLICY: SsrfPolicy = Object.freeze({\n schemes_allowed: Object.freeze(['http', 'https']),\n schemes_denied: Object.freeze(['file', 'gopher', 'ftp', 'ftps', 'data', 'javascript', 'about', 'ws', 'wss']),\n hosts_denied_ipv4_cidrs: Object.freeze([\n '0.0.0.0/8',\n '10.0.0.0/8',\n '100.64.0.0/10',\n // 127.0.0.0/8 omitted — loopback allowed for tests.\n '169.254.0.0/16',\n '172.16.0.0/12',\n '192.0.0.0/24',\n '192.168.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n ]),\n hosts_denied_ipv6_cidrs: Object.freeze([\n // ::1/128 and ::/128 omitted — IPv6 loopback allowed for tests.\n '::ffff:0:0/96',\n '64:ff9b::/96',\n 'fc00::/7',\n 'fe80::/10',\n 'ff00::/8',\n ]),\n hosts_denied_metadata: Object.freeze([\n 'metadata.google.internal',\n 'metadata',\n 'metadata.packet.net',\n 'fd00:ec2::254',\n ]),\n host_literal_policy: 'allow',\n}) as SsrfPolicy;\n\n/**\n * Signature of the lookup callback `dns.lookup` accepts. Re-declared here\n * because the native type from `node:dns` is a complex overload set; the\n * shape we actually need is the all=true variant the Agent expects.\n */\nexport type DnsLookupAll = (\n hostname: string,\n options: { family?: number; hints?: number; all: true; verbatim?: boolean },\n callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void\n) => void;\n\nexport interface PinAndBindFetchOptions {\n /**\n * SSRF policy to enforce against resolved IPs. Defaults to\n * {@link WEBHOOK_SSRF_POLICY} (https-only, all private/loopback/metadata\n * ranges denied, IP literals allowed).\n */\n policy?: SsrfPolicy;\n /**\n * Override the underlying DNS lookup. Default uses `dns.lookup` with\n * `all: true`. Tests inject a stub to simulate rebinding attacks without\n * touching real DNS.\n */\n lookup?: DnsLookupAll;\n /**\n * Forward to `Agent` — connect-attempt timeout, TLS options, etc. Cannot\n * override `lookup`; that is wired by this helper.\n */\n agentOptions?: Omit<Agent.Options, 'connect'> & {\n connect?: Omit<NonNullable<Agent.Options['connect']>, 'lookup'>;\n };\n}\n\nconst DEFAULT_LOOKUP_ALL: DnsLookupAll = (hostname, options, callback) => {\n nativeDnsLookup(hostname, { ...options, all: true }, (err, addresses) => {\n callback(err, addresses as LookupAddress[]);\n });\n};\n\n/**\n * Build a `fetch` that pins outbound connections to the IPs the SSRF policy\n * allows, defeating DNS-rebinding attacks against per-attempt DNS resolution.\n *\n * This is the default `fetch` for `createWebhookEmitter` /\n * `createAdcpServer({ webhooks })`, so production webhook delivery is\n * rebinding-protected without extra wiring. Call it explicitly only to\n * override the policy — e.g. {@link LOOPBACK_OK_WEBHOOK_SSRF_POLICY} for\n * storyboard tests that deliver to a loopback http receiver. See\n * `docs/guides/SIGNING-GUIDE.md` § Webhook SSRF defense.\n *\n * Construct once per emitter and reuse — each call instantiates a fresh\n * `undici.Agent` with its own connection pool.\n *\n * @example\n * ```ts\n * import { createWebhookEmitter, createPinAndBindFetch } from '@adcp/sdk/server';\n *\n * const emitter = createWebhookEmitter({\n * signerKey: webhookKey,\n * fetch: createPinAndBindFetch(),\n * });\n * ```\n */\nexport function createPinAndBindFetch(options: PinAndBindFetchOptions = {}): typeof fetch {\n const policy = options.policy ?? WEBHOOK_SSRF_POLICY;\n const lookupImpl = options.lookup ?? DEFAULT_LOOKUP_ALL;\n\n const guardedLookup = (\n hostname: string,\n opts: { family?: number; hints?: number; all?: boolean; verbatim?: boolean } | undefined,\n callback: (err: NodeJS.ErrnoException | null, addressOrAll?: string | LookupAddress[], family?: number) => void\n ): void => {\n const wantsAll = opts?.all === true;\n lookupImpl(hostname, { ...(opts ?? {}), all: true }, (err, addresses) => {\n if (err) {\n callback(err);\n return;\n }\n if (!Array.isArray(addresses) || addresses.length === 0) {\n callback(\n makeSsrfError(`DNS resolution returned no addresses for ${hostname}`, 'dns_revalidation:no_addresses')\n );\n return;\n }\n\n // The URL passed in here only matters for scheme + hostname checks,\n // both of which were already validated synchronously by undici when\n // the request started. We re-build a placeholder URL to feed the\n // resolved-address rule, which is the load-bearing check for\n // rebinding defense.\n const url = new URL(`https://${bracketIfV6(hostname)}`);\n const ips = addresses.map(a => a.address);\n const result = enforceSsrfPolicyResolved(url, ips, policy);\n if (!result.allowed) {\n callback(makeSsrfError(result.message ?? 'SSRF policy denied resolved address', result.rule ?? 'ssrf'));\n return;\n }\n\n if (wantsAll) {\n callback(null, addresses);\n return;\n }\n // Pin to the first resolved address. enforceSsrfPolicyResolved is\n // all-or-none: if it allowed the resolution, every entry passed.\n const first = addresses[0]!;\n callback(null, first.address, first.family);\n });\n };\n\n const dispatcher = new Agent({\n ...(options.agentOptions ?? {}),\n connect: {\n ...(options.agentOptions?.connect ?? {}),\n // undici's connect type accepts a lookup with the dns.lookup signature.\n lookup: guardedLookup as unknown as Agent.Options['connect'] extends infer T\n ? T extends { lookup?: infer L }\n ? L\n : never\n : never,\n },\n });\n\n const wrapped = async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): Promise<Response> => {\n // Synchronous pre-check for the URL's literal scheme + (if it's an IP)\n // its CIDR membership. undici skips `connect.lookup` for IP-literal\n // hostnames, so the resolved-IP path below would never see them.\n // This pre-check enforces the same SSRF policy on URLs like\n // `https://127.0.0.1/cb` or `https://[::1]/cb`.\n const url = resolveRequestUrl(input);\n if (url) {\n const sync = enforceSsrfPolicy(url, policy);\n if (!sync.allowed) {\n throw makeSsrfError(sync.message ?? 'SSRF policy denied URL', sync.rule ?? 'ssrf');\n }\n }\n return undiciFetch(input as Parameters<typeof undiciFetch>[0], {\n ...(init as Parameters<typeof undiciFetch>[1]),\n dispatcher: dispatcher as unknown as Dispatcher,\n }) as unknown as Response;\n };\n\n return wrapped as typeof fetch;\n}\n\nfunction resolveRequestUrl(input: Parameters<typeof fetch>[0]): URL | null {\n try {\n if (typeof input === 'string') return new URL(input);\n if (input instanceof URL) return input;\n if (\n typeof input === 'object' &&\n input !== null &&\n 'url' in input &&\n typeof (input as { url: unknown }).url === 'string'\n ) {\n return new URL((input as { url: string }).url);\n }\n } catch {\n // Let undici surface the parse error in its own shape.\n return null;\n }\n return null;\n}\n\nfunction bracketIfV6(host: string): string {\n return isIPv6(host) ? `[${host}]` : host;\n}\n\nfunction makeSsrfError(message: string, rule: string): NodeJS.ErrnoException {\n const err = new Error(`pin-and-bind: ${rule}: ${message}`) as NodeJS.ErrnoException;\n err.code = 'EADCP_SSRF_BLOCKED';\n return err;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/server/pin-and-bind-fetch.ts"],"sourcesContent":["/**\n * Pin-and-bind fetch — DNS-rebinding-resistant `fetch` for outbound webhook\n * delivery and other callbacks where the destination is buyer-supplied.\n *\n * The problem: validating a `push_notification_config.url`'s LITERAL hostname\n * against an SSRF deny list does not protect against a DNS-rebinding attack.\n * A buyer can register `https://rebind.attacker.com/`, pass the literal-host\n * check, and then flip the A-record TTL to `169.254.169.254` (cloud metadata)\n * or `127.0.0.1` (loopback) before the webhook fires. Node's `fetch` resolves\n * the host fresh at request time, gets the rebound IP, and posts the\n * signed payload to the attacker-controlled destination.\n *\n * The fix: control DNS resolution and connect-target inside the fetch itself.\n * 1. Resolve the hostname.\n * 2. Validate every resolved IP against the SSRF policy (CIDR deny lists,\n * metadata-host names, scheme rules).\n * 3. Pin the connection to the validated IP — undici opens TCP/TLS to that\n * specific address, but the original hostname is preserved for TLS SNI\n * and the `Host:` header so HTTPS routing still works.\n *\n * Implementation note: undici's `Agent` accepts a `connect.lookup` callback\n * with the same signature as `dns.lookup`. We hook the callback, resolve via\n * `dns.lookup({ all: true })` to see EVERY address the host can reach, run\n * the resolved IPs through {@link enforceSsrfPolicyResolved}, and only return\n * a pinned address when every resolved IP is in an allowed range. This\n * matches the AdCP substitution-observer SSRF contract — a host that\n * resolves to *any* denied IP is treated as suspect and rejected wholesale.\n */\n\nimport { Agent, fetch as undiciFetch, type Dispatcher } from 'undici';\nimport { lookup as nativeDnsLookup, type LookupAddress } from 'node:dns';\nimport { isIPv6 } from 'node:net';\n\nimport { enforceSsrfPolicy, enforceSsrfPolicyResolved } from '../substitution/observer/ssrf';\nimport type { SsrfPolicy } from '../substitution/types';\n\n/**\n * Default SSRF policy for outbound webhook delivery. Stricter than\n * `DEFAULT_SSRF_POLICY` (substitution observer) only in that it allows\n * `host_literal_policy: 'allow'` — webhook URLs MAY use IP literals\n * (e.g. `https://203.0.113.10/cb`) as long as the IP is not in a denied\n * CIDR range. Schemes restricted to https; signed webhooks SHOULD be\n * delivered over TLS.\n *\n * For storyboard / in-process tests where the receiver runs on\n * `http://127.0.0.1:port`, use {@link LOOPBACK_OK_WEBHOOK_SSRF_POLICY}\n * instead. That preset relaxes only the loopback + http rules and keeps\n * every other deny range — adopters get most of the SSRF protection\n * during tests without disabling pin-and-bind entirely.\n */\nexport const WEBHOOK_SSRF_POLICY: SsrfPolicy = Object.freeze({\n schemes_allowed: Object.freeze(['https']),\n schemes_denied: Object.freeze(['http', 'file', 'gopher', 'ftp', 'ftps', 'data', 'javascript', 'about', 'ws', 'wss']),\n hosts_denied_ipv4_cidrs: Object.freeze([\n '0.0.0.0/8',\n '10.0.0.0/8',\n '100.64.0.0/10',\n '127.0.0.0/8',\n '169.254.0.0/16',\n '172.16.0.0/12',\n '192.0.0.0/24',\n '192.168.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n ]),\n hosts_denied_ipv6_cidrs: Object.freeze([\n '::1/128',\n '::/128',\n '::ffff:0:0/96',\n '64:ff9b::/96',\n 'fc00::/7',\n 'fe80::/10',\n 'ff00::/8',\n ]),\n hosts_denied_metadata: Object.freeze([\n 'metadata.google.internal',\n 'metadata',\n 'metadata.packet.net',\n 'fd00:ec2::254',\n ]),\n host_literal_policy: 'allow',\n}) as SsrfPolicy;\n\n/**\n * Pin-and-bind policy that allows http URLs and IPv4/IPv6 loopback so\n * adopters can enable pin-and-bind for production webhook delivery while\n * keeping storyboard / in-process tests working — `createWebhookReceiver`\n * listens on `http://127.0.0.1:port`. Every other private CIDR, metadata\n * host, and link-local range is still denied, so loopback is the only\n * relaxation. Pass to `createPinAndBindFetch({ policy })` from your test\n * fixture or storyboard runner harness; do NOT use in production.\n */\nexport const LOOPBACK_OK_WEBHOOK_SSRF_POLICY: SsrfPolicy = Object.freeze({\n schemes_allowed: Object.freeze(['http', 'https']),\n schemes_denied: Object.freeze(['file', 'gopher', 'ftp', 'ftps', 'data', 'javascript', 'about', 'ws', 'wss']),\n hosts_denied_ipv4_cidrs: Object.freeze([\n '0.0.0.0/8',\n '10.0.0.0/8',\n '100.64.0.0/10',\n // 127.0.0.0/8 omitted — loopback allowed for tests.\n '169.254.0.0/16',\n '172.16.0.0/12',\n '192.0.0.0/24',\n '192.168.0.0/16',\n '224.0.0.0/4',\n '240.0.0.0/4',\n ]),\n hosts_denied_ipv6_cidrs: Object.freeze([\n // ::1/128 and ::/128 omitted — IPv6 loopback allowed for tests.\n '::ffff:0:0/96',\n '64:ff9b::/96',\n 'fc00::/7',\n 'fe80::/10',\n 'ff00::/8',\n ]),\n hosts_denied_metadata: Object.freeze([\n 'metadata.google.internal',\n 'metadata',\n 'metadata.packet.net',\n 'fd00:ec2::254',\n ]),\n host_literal_policy: 'allow',\n}) as SsrfPolicy;\n\n/**\n * Signature of the lookup callback `dns.lookup` accepts. Re-declared here\n * because the native type from `node:dns` is a complex overload set; the\n * shape we actually need is the all=true variant the Agent expects.\n */\nexport type DnsLookupAll = (\n hostname: string,\n options: { family?: number; hints?: number; all: true; verbatim?: boolean },\n callback: (err: NodeJS.ErrnoException | null, addresses: LookupAddress[]) => void\n) => void;\n\nexport interface PinAndBindFetchOptions {\n /**\n * SSRF policy to enforce against resolved IPs. Defaults to\n * {@link WEBHOOK_SSRF_POLICY} (https-only, all private/loopback/metadata\n * ranges denied, IP literals allowed).\n */\n policy?: SsrfPolicy;\n /**\n * Override the underlying DNS lookup. Default uses `dns.lookup` with\n * `all: true`. Tests inject a stub to simulate rebinding attacks without\n * touching real DNS.\n */\n lookup?: DnsLookupAll;\n /**\n * Forward to `Agent` — connect-attempt timeout, TLS options, etc. Cannot\n * override `lookup`; that is wired by this helper.\n */\n agentOptions?: Omit<Agent.Options, 'connect'> & {\n connect?: Omit<NonNullable<Agent.Options['connect']>, 'lookup'>;\n };\n}\n\nconst DEFAULT_LOOKUP_ALL: DnsLookupAll = (hostname, options, callback) => {\n nativeDnsLookup(hostname, { ...options, all: true }, (err, addresses) => {\n callback(err, addresses as LookupAddress[]);\n });\n};\n\n/**\n * Build a `fetch` that pins outbound connections to the IPs the SSRF policy\n * allows, defeating DNS-rebinding attacks against per-attempt DNS resolution.\n *\n * This is the default `fetch` for `createWebhookEmitter` /\n * `createAdcpServer({ webhooks })`, so production webhook delivery is\n * rebinding-protected without extra wiring. Call it explicitly only to\n * override the policy — e.g. {@link LOOPBACK_OK_WEBHOOK_SSRF_POLICY} for\n * storyboard tests that deliver to a loopback http receiver. See\n * `docs/guides/SIGNING-GUIDE.md` § Webhook SSRF defense.\n *\n * Construct once per emitter and reuse — each call instantiates a fresh\n * `undici.Agent` with its own connection pool.\n *\n * @example\n * ```ts\n * import { createWebhookEmitter, createPinAndBindFetch } from '@adcp/sdk/server';\n *\n * const emitter = createWebhookEmitter({\n * signerKey: webhookKey,\n * fetch: createPinAndBindFetch(),\n * });\n * ```\n */\nexport function createPinAndBindFetch(options: PinAndBindFetchOptions = {}): typeof fetch {\n const policy = options.policy ?? WEBHOOK_SSRF_POLICY;\n const lookupImpl = options.lookup ?? DEFAULT_LOOKUP_ALL;\n\n const guardedLookup = (\n hostname: string,\n opts: { family?: number; hints?: number; all?: boolean; verbatim?: boolean } | undefined,\n callback: (err: NodeJS.ErrnoException | null, addressOrAll?: string | LookupAddress[], family?: number) => void\n ): void => {\n const wantsAll = opts?.all === true;\n lookupImpl(hostname, { ...(opts ?? {}), all: true }, (err, addresses) => {\n if (err) {\n callback(err);\n return;\n }\n if (!Array.isArray(addresses) || addresses.length === 0) {\n callback(\n makeSsrfError(`DNS resolution returned no addresses for ${hostname}`, 'dns_revalidation:no_addresses')\n );\n return;\n }\n\n // The URL passed in here only matters for scheme + hostname checks,\n // both of which were already validated synchronously by undici when\n // the request started. We re-build a placeholder URL to feed the\n // resolved-address rule, which is the load-bearing check for\n // rebinding defense.\n const url = new URL(`https://${bracketIfV6(hostname)}`);\n const ips = addresses.map(a => a.address);\n const result = enforceSsrfPolicyResolved(url, ips, policy);\n if (!result.allowed) {\n callback(makeSsrfError(result.message ?? 'SSRF policy denied resolved address', result.rule ?? 'ssrf'));\n return;\n }\n\n if (wantsAll) {\n callback(null, addresses);\n return;\n }\n // Pin to the first resolved address. enforceSsrfPolicyResolved is\n // all-or-none: if it allowed the resolution, every entry passed.\n const first = addresses[0]!;\n callback(null, first.address, first.family);\n });\n };\n\n const dispatcher = new Agent({\n ...(options.agentOptions ?? {}),\n connect: {\n ...(options.agentOptions?.connect ?? {}),\n // undici's connect type accepts a lookup with the dns.lookup signature.\n lookup: guardedLookup as unknown as Agent.Options['connect'] extends infer T\n ? T extends { lookup?: infer L }\n ? L\n : never\n : never,\n },\n });\n\n const wrapped = async (input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): Promise<Response> => {\n // Synchronous pre-check for the URL's literal scheme + (if it's an IP)\n // its CIDR membership. undici skips `connect.lookup` for IP-literal\n // hostnames, so the resolved-IP path below would never see them.\n // This pre-check enforces the same SSRF policy on URLs like\n // `https://127.0.0.1/cb` or `https://[::1]/cb`.\n const url = resolveRequestUrl(input);\n if (url) {\n const sync = enforceSsrfPolicy(url, policy);\n if (!sync.allowed) {\n throw makeSsrfError(sync.message ?? 'SSRF policy denied URL', sync.rule ?? 'ssrf');\n }\n }\n return undiciFetch(input as Parameters<typeof undiciFetch>[0], {\n ...(init as Parameters<typeof undiciFetch>[1]),\n dispatcher: dispatcher as unknown as Dispatcher,\n }) as unknown as Response;\n };\n\n return wrapped as typeof fetch;\n}\n\nfunction resolveRequestUrl(input: Parameters<typeof fetch>[0]): URL | null {\n try {\n if (typeof input === 'string') return new URL(input);\n if (input instanceof URL) return input;\n if (\n typeof input === 'object' &&\n input !== null &&\n 'url' in input &&\n typeof (input as { url: unknown }).url === 'string'\n ) {\n return new URL((input as { url: string }).url);\n }\n } catch {\n // Let undici surface the parse error in its own shape.\n return null;\n }\n return null;\n}\n\nfunction bracketIfV6(host: string): string {\n return isIPv6(host) ? `[${host}]` : host;\n}\n\nfunction makeSsrfError(message: string, rule: string): NodeJS.ErrnoException {\n const err = new Error(`pin-and-bind: ${rule}: ${message}`) as NodeJS.ErrnoException;\n err.code = 'EADCP_SSRF_BLOCKED';\n return err;\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 {
8
2
  DEFAULT_MAX_DOCUMENT_BYTES,
9
3
  createSessionedStore,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/server/postgres-state-store.ts"],"sourcesContent":["/**\n * PostgreSQL-backed state store for distributed AdCP servers.\n *\n * Replaces InMemoryStateStore when running multiple server instances behind\n * a load balancer. Domain objects are stored in a shared JSONB table so any\n * instance can read or write state regardless of which instance handled\n * the original request.\n *\n * @example\n * ```typescript\n * import { Pool } from 'pg';\n * import { PostgresStateStore, createAdcpServer, serve } from '@adcp/sdk/server/legacy/v5';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * const stateStore = new PostgresStateStore(pool);\n *\n * // Run migration once at startup\n * await pool.query(getAdcpStateMigration());\n *\n * serve(() => createAdcpServer({\n * name: 'My Publisher', version: '1.0.0',\n * stateStore,\n * mediaBuy: {\n * createMediaBuy: async (params, ctx) => {\n * const buy = { media_buy_id: 'mb_1', status: 'active', packages: [] };\n * await ctx.store.put('media_buys', buy.media_buy_id, buy);\n * return buy;\n * },\n * },\n * }));\n * ```\n */\n\nimport type { PgQueryable } from './postgres-task-store';\nimport {\n DEFAULT_MAX_DOCUMENT_BYTES,\n createSessionedStore,\n validateCollection,\n validateId,\n validateWrite,\n type AdcpStateStore,\n type ListOptions,\n type ListResult,\n type PutIfMatchResult,\n type VersionedDocument,\n} from './state-store';\n\nexport interface PostgresStateStoreOptions {\n /** Table name. Must contain only lowercase letters, digits, and underscores. Defaults to `\"adcp_state\"`. */\n tableName?: string;\n /** Max bytes per document. Defaults to {@link DEFAULT_MAX_DOCUMENT_BYTES}. */\n maxDocumentBytes?: number;\n}\n\nconst DEFAULT_TABLE = 'adcp_state';\nconst VALID_IDENTIFIER = /^[a-z_][a-z0-9_]*$/;\nconst PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 500;\n\n/**\n * Generate the SQL DDL for the state store table.\n *\n * Idempotent: safe to run on existing tables. The `ADD COLUMN IF NOT EXISTS`\n * clause upgrades databases created by earlier SDK versions (no `version`\n * column) without rewriting data — existing rows start at version 1. A seller's\n * first `putIfMatch` against an existing (pre-migration) row will see\n * `currentVersion: 1` — same as a freshly inserted row. Treat version as opaque.\n *\n * Do not attach triggers that suppress `UPDATE` or return `OLD` for this table —\n * `putIfMatch` relies on affected-row count to detect conflicts, and a trigger\n * that drops the update will be reported as a CAS conflict. RLS policies that\n * silently reject writes have the same problem.\n */\nexport function getAdcpStateMigration(tableName = DEFAULT_TABLE): string {\n if (!VALID_IDENTIFIER.test(tableName)) {\n throw new Error(`Invalid table name: \"${tableName}\". Must match /^[a-z_][a-z0-9_]*$/.`);\n }\n\n return `\n CREATE TABLE IF NOT EXISTS ${tableName} (\n collection TEXT NOT NULL,\n id TEXT NOT NULL,\n data JSONB NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\n PRIMARY KEY (collection, id)\n );\n\n ALTER TABLE ${tableName}\n ADD COLUMN IF NOT EXISTS version INTEGER NOT NULL DEFAULT 1;\n\n CREATE INDEX IF NOT EXISTS idx_${tableName}_collection\n ON ${tableName}(collection);\n\n CREATE INDEX IF NOT EXISTS idx_${tableName}_updated\n ON ${tableName}(updated_at);\n `;\n}\n\n/** The migration SQL as a constant for the default table name. */\nexport const ADCP_STATE_MIGRATION = getAdcpStateMigration();\n\nexport class PostgresStateStore implements AdcpStateStore {\n private readonly db: PgQueryable;\n private readonly table: string;\n private readonly maxDocumentBytes: number;\n\n constructor(db: PgQueryable, options?: PostgresStateStoreOptions) {\n this.db = db;\n this.table = options?.tableName ?? DEFAULT_TABLE;\n this.maxDocumentBytes = options?.maxDocumentBytes ?? DEFAULT_MAX_DOCUMENT_BYTES;\n if (!VALID_IDENTIFIER.test(this.table)) {\n throw new Error(`Invalid table name: \"${this.table}\". Must match /^[a-z_][a-z0-9_]*$/.`);\n }\n }\n\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n validateCollection(collection);\n validateId(id);\n const { rows } = await this.db.query(`SELECT data FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n if (rows.length === 0) return null;\n return rows[0]!.data as T;\n }\n\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n validateCollection(collection);\n validateId(id);\n const { rows } = await this.db.query(`SELECT data, version FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n if (rows.length === 0) return null;\n const row = rows[0]!;\n return { data: row.data as T, version: row.version as number };\n }\n\n async put(collection: string, id: string, data: Record<string, unknown>): Promise<void> {\n const serialized = validateWrite(collection, id, data, this.maxDocumentBytes);\n await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id)\n DO UPDATE SET data = $3, version = ${this.table}.version + 1, updated_at = NOW()`,\n [collection, id, serialized]\n );\n }\n\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n const serialized = validateWrite(collection, id, data, this.maxDocumentBytes);\n\n if (expectedVersion === null) {\n // Insert-only path: succeed iff no row exists. Returns version on success,\n // nothing on conflict (then we re-read to report the current version).\n const { rows } = await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id) DO NOTHING\n RETURNING version`,\n [collection, id, serialized]\n );\n if (rows.length > 0) return { ok: true, version: rows[0]!.version as number };\n const { rows: existing } = await this.db.query(\n `SELECT version FROM ${this.table} WHERE collection = $1 AND id = $2`,\n [collection, id]\n );\n return { ok: false, currentVersion: (existing[0]?.version as number | undefined) ?? null };\n }\n\n const { rows } = await this.db.query(\n `UPDATE ${this.table}\n SET data = $3, version = version + 1, updated_at = NOW()\n WHERE collection = $1 AND id = $2 AND version = $4\n RETURNING version`,\n [collection, id, serialized, expectedVersion]\n );\n if (rows.length > 0) return { ok: true, version: rows[0]!.version as number };\n\n const { rows: existing } = await this.db.query(\n `SELECT version FROM ${this.table} WHERE collection = $1 AND id = $2`,\n [collection, id]\n );\n return { ok: false, currentVersion: (existing[0]?.version as number | undefined) ?? null };\n }\n\n async patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void> {\n const serialized = validateWrite(collection, id, partial, this.maxDocumentBytes);\n await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id)\n DO UPDATE SET data = ${this.table}.data || $3, version = ${this.table}.version + 1, updated_at = NOW()`,\n [collection, id, serialized]\n );\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n validateCollection(collection);\n validateId(id);\n const { rowCount } = await this.db.query(`DELETE FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n return (rowCount ?? 0) > 0;\n }\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n validateCollection(collection);\n const limit = Math.min(options?.limit ?? PAGE_SIZE, MAX_PAGE_SIZE);\n const conditions = ['collection = $1'];\n const values: unknown[] = [collection];\n let paramIndex = 2;\n\n // Filter by JSONB containment\n if (options?.filter && Object.keys(options.filter).length > 0) {\n conditions.push(`data @> $${paramIndex}`);\n values.push(JSON.stringify(options.filter));\n paramIndex++;\n }\n\n // Cursor-based pagination (cursor = \"updated_at|id\")\n if (options?.cursor) {\n const parts = options.cursor.split('|', 2);\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new Error(`Invalid cursor format: expected \"timestamp|id\"`);\n }\n const [cursorTime, cursorId] = parts;\n conditions.push(`(updated_at, id) > ($${paramIndex}::timestamptz, $${paramIndex + 1})`);\n values.push(cursorTime, cursorId);\n paramIndex += 2;\n }\n\n const where = conditions.join(' AND ');\n // Fetch one extra to detect hasMore\n values.push(limit + 1);\n\n const { rows } = await this.db.query(\n `SELECT id, data, updated_at::text AS updated_at_raw\n FROM ${this.table}\n WHERE ${where}\n ORDER BY updated_at, id\n LIMIT $${paramIndex}`,\n values\n );\n\n const hasMore = rows.length > limit;\n const resultRows = hasMore ? rows.slice(0, limit) : rows;\n const items = resultRows.map(r => r.data as T);\n\n let nextCursor: string | undefined;\n if (hasMore && resultRows.length > 0) {\n const last = resultRows[resultRows.length - 1]!;\n nextCursor = `${last.updated_at_raw as string}|${last.id as string}`;\n }\n\n return { items, nextCursor };\n }\n\n /**\n * Delete all documents in a collection.\n */\n async clearCollection(collection: string): Promise<number> {\n const { rowCount } = await this.db.query(`DELETE FROM ${this.table} WHERE collection = $1`, [collection]);\n return rowCount ?? 0;\n }\n\n scoped(sessionKey: string): AdcpStateStore {\n return createSessionedStore(this, sessionKey);\n }\n}\n"],"mappings":"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","names":["rows","existing"]}
1
+ {"version":3,"sources":["../../../src/lib/server/postgres-state-store.ts"],"sourcesContent":["/**\n * PostgreSQL-backed state store for distributed AdCP servers.\n *\n * Replaces InMemoryStateStore when running multiple server instances behind\n * a load balancer. Domain objects are stored in a shared JSONB table so any\n * instance can read or write state regardless of which instance handled\n * the original request.\n *\n * @example\n * ```typescript\n * import { Pool } from 'pg';\n * import { PostgresStateStore, createAdcpServer, serve } from '@adcp/sdk/server/legacy/v5';\n *\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL });\n * const stateStore = new PostgresStateStore(pool);\n *\n * // Run migration once at startup\n * await pool.query(getAdcpStateMigration());\n *\n * serve(() => createAdcpServer({\n * name: 'My Publisher', version: '1.0.0',\n * stateStore,\n * mediaBuy: {\n * createMediaBuy: async (params, ctx) => {\n * const buy = { media_buy_id: 'mb_1', status: 'active', packages: [] };\n * await ctx.store.put('media_buys', buy.media_buy_id, buy);\n * return buy;\n * },\n * },\n * }));\n * ```\n */\n\nimport type { PgQueryable } from './postgres-task-store';\nimport {\n DEFAULT_MAX_DOCUMENT_BYTES,\n createSessionedStore,\n validateCollection,\n validateId,\n validateWrite,\n type AdcpStateStore,\n type ListOptions,\n type ListResult,\n type PutIfMatchResult,\n type VersionedDocument,\n} from './state-store';\n\nexport interface PostgresStateStoreOptions {\n /** Table name. Must contain only lowercase letters, digits, and underscores. Defaults to `\"adcp_state\"`. */\n tableName?: string;\n /** Max bytes per document. Defaults to {@link DEFAULT_MAX_DOCUMENT_BYTES}. */\n maxDocumentBytes?: number;\n}\n\nconst DEFAULT_TABLE = 'adcp_state';\nconst VALID_IDENTIFIER = /^[a-z_][a-z0-9_]*$/;\nconst PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 500;\n\n/**\n * Generate the SQL DDL for the state store table.\n *\n * Idempotent: safe to run on existing tables. The `ADD COLUMN IF NOT EXISTS`\n * clause upgrades databases created by earlier SDK versions (no `version`\n * column) without rewriting data — existing rows start at version 1. A seller's\n * first `putIfMatch` against an existing (pre-migration) row will see\n * `currentVersion: 1` — same as a freshly inserted row. Treat version as opaque.\n *\n * Do not attach triggers that suppress `UPDATE` or return `OLD` for this table —\n * `putIfMatch` relies on affected-row count to detect conflicts, and a trigger\n * that drops the update will be reported as a CAS conflict. RLS policies that\n * silently reject writes have the same problem.\n */\nexport function getAdcpStateMigration(tableName = DEFAULT_TABLE): string {\n if (!VALID_IDENTIFIER.test(tableName)) {\n throw new Error(`Invalid table name: \"${tableName}\". Must match /^[a-z_][a-z0-9_]*$/.`);\n }\n\n return `\n CREATE TABLE IF NOT EXISTS ${tableName} (\n collection TEXT NOT NULL,\n id TEXT NOT NULL,\n data JSONB NOT NULL,\n version INTEGER NOT NULL DEFAULT 1,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n\n PRIMARY KEY (collection, id)\n );\n\n ALTER TABLE ${tableName}\n ADD COLUMN IF NOT EXISTS version INTEGER NOT NULL DEFAULT 1;\n\n CREATE INDEX IF NOT EXISTS idx_${tableName}_collection\n ON ${tableName}(collection);\n\n CREATE INDEX IF NOT EXISTS idx_${tableName}_updated\n ON ${tableName}(updated_at);\n `;\n}\n\n/** The migration SQL as a constant for the default table name. */\nexport const ADCP_STATE_MIGRATION = getAdcpStateMigration();\n\nexport class PostgresStateStore implements AdcpStateStore {\n private readonly db: PgQueryable;\n private readonly table: string;\n private readonly maxDocumentBytes: number;\n\n constructor(db: PgQueryable, options?: PostgresStateStoreOptions) {\n this.db = db;\n this.table = options?.tableName ?? DEFAULT_TABLE;\n this.maxDocumentBytes = options?.maxDocumentBytes ?? DEFAULT_MAX_DOCUMENT_BYTES;\n if (!VALID_IDENTIFIER.test(this.table)) {\n throw new Error(`Invalid table name: \"${this.table}\". Must match /^[a-z_][a-z0-9_]*$/.`);\n }\n }\n\n async get<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<T | null> {\n validateCollection(collection);\n validateId(id);\n const { rows } = await this.db.query(`SELECT data FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n if (rows.length === 0) return null;\n return rows[0]!.data as T;\n }\n\n async getWithVersion<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n id: string\n ): Promise<VersionedDocument<T> | null> {\n validateCollection(collection);\n validateId(id);\n const { rows } = await this.db.query(`SELECT data, version FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n if (rows.length === 0) return null;\n const row = rows[0]!;\n return { data: row.data as T, version: row.version as number };\n }\n\n async put(collection: string, id: string, data: Record<string, unknown>): Promise<void> {\n const serialized = validateWrite(collection, id, data, this.maxDocumentBytes);\n await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id)\n DO UPDATE SET data = $3, version = ${this.table}.version + 1, updated_at = NOW()`,\n [collection, id, serialized]\n );\n }\n\n async putIfMatch(\n collection: string,\n id: string,\n data: Record<string, unknown>,\n expectedVersion: number | null\n ): Promise<PutIfMatchResult> {\n const serialized = validateWrite(collection, id, data, this.maxDocumentBytes);\n\n if (expectedVersion === null) {\n // Insert-only path: succeed iff no row exists. Returns version on success,\n // nothing on conflict (then we re-read to report the current version).\n const { rows } = await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id) DO NOTHING\n RETURNING version`,\n [collection, id, serialized]\n );\n if (rows.length > 0) return { ok: true, version: rows[0]!.version as number };\n const { rows: existing } = await this.db.query(\n `SELECT version FROM ${this.table} WHERE collection = $1 AND id = $2`,\n [collection, id]\n );\n return { ok: false, currentVersion: (existing[0]?.version as number | undefined) ?? null };\n }\n\n const { rows } = await this.db.query(\n `UPDATE ${this.table}\n SET data = $3, version = version + 1, updated_at = NOW()\n WHERE collection = $1 AND id = $2 AND version = $4\n RETURNING version`,\n [collection, id, serialized, expectedVersion]\n );\n if (rows.length > 0) return { ok: true, version: rows[0]!.version as number };\n\n const { rows: existing } = await this.db.query(\n `SELECT version FROM ${this.table} WHERE collection = $1 AND id = $2`,\n [collection, id]\n );\n return { ok: false, currentVersion: (existing[0]?.version as number | undefined) ?? null };\n }\n\n async patch(collection: string, id: string, partial: Record<string, unknown>): Promise<void> {\n const serialized = validateWrite(collection, id, partial, this.maxDocumentBytes);\n await this.db.query(\n `INSERT INTO ${this.table} (collection, id, data, version)\n VALUES ($1, $2, $3, 1)\n ON CONFLICT (collection, id)\n DO UPDATE SET data = ${this.table}.data || $3, version = ${this.table}.version + 1, updated_at = NOW()`,\n [collection, id, serialized]\n );\n }\n\n async delete(collection: string, id: string): Promise<boolean> {\n validateCollection(collection);\n validateId(id);\n const { rowCount } = await this.db.query(`DELETE FROM ${this.table} WHERE collection = $1 AND id = $2`, [\n collection,\n id,\n ]);\n return (rowCount ?? 0) > 0;\n }\n\n async list<T extends Record<string, unknown> = Record<string, unknown>>(\n collection: string,\n options?: ListOptions\n ): Promise<ListResult<T>> {\n validateCollection(collection);\n const limit = Math.min(options?.limit ?? PAGE_SIZE, MAX_PAGE_SIZE);\n const conditions = ['collection = $1'];\n const values: unknown[] = [collection];\n let paramIndex = 2;\n\n // Filter by JSONB containment\n if (options?.filter && Object.keys(options.filter).length > 0) {\n conditions.push(`data @> $${paramIndex}`);\n values.push(JSON.stringify(options.filter));\n paramIndex++;\n }\n\n // Cursor-based pagination (cursor = \"updated_at|id\")\n if (options?.cursor) {\n const parts = options.cursor.split('|', 2);\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\n throw new Error(`Invalid cursor format: expected \"timestamp|id\"`);\n }\n const [cursorTime, cursorId] = parts;\n conditions.push(`(updated_at, id) > ($${paramIndex}::timestamptz, $${paramIndex + 1})`);\n values.push(cursorTime, cursorId);\n paramIndex += 2;\n }\n\n const where = conditions.join(' AND ');\n // Fetch one extra to detect hasMore\n values.push(limit + 1);\n\n const { rows } = await this.db.query(\n `SELECT id, data, updated_at::text AS updated_at_raw\n FROM ${this.table}\n WHERE ${where}\n ORDER BY updated_at, id\n LIMIT $${paramIndex}`,\n values\n );\n\n const hasMore = rows.length > limit;\n const resultRows = hasMore ? rows.slice(0, limit) : rows;\n const items = resultRows.map(r => r.data as T);\n\n let nextCursor: string | undefined;\n if (hasMore && resultRows.length > 0) {\n const last = resultRows[resultRows.length - 1]!;\n nextCursor = `${last.updated_at_raw as string}|${last.id as string}`;\n }\n\n return { items, nextCursor };\n }\n\n /**\n * Delete all documents in a collection.\n */\n async clearCollection(collection: string): Promise<number> {\n const { rowCount } = await this.db.query(`DELETE FROM ${this.table} WHERE collection = $1`, [collection]);\n return rowCount ?? 0;\n }\n\n scoped(sessionKey: string): AdcpStateStore {\n return createSessionedStore(this, sessionKey);\n }\n}\n"],"mappings":"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","names":["rows","existing"]}
@@ -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 "node:crypto";
8
2
  const DEFAULT_TABLE = "adcp_mcp_tasks";
9
3
  const VALID_IDENTIFIER = /^[a-z_][a-z0-9_]*$/;