@adcp/sdk 5.25.0 → 6.0.0

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 (298) hide show
  1. package/README.md +45 -7
  2. package/dist/lib/compliance-fixtures/index.d.ts +1 -1
  3. package/dist/lib/compliance-fixtures/index.js +1 -1
  4. package/dist/lib/conformance/runners.d.ts.map +1 -1
  5. package/dist/lib/conformance/runners.js +13 -1
  6. package/dist/lib/conformance/runners.js.map +1 -1
  7. package/dist/lib/core/AgentClient.d.ts.map +1 -1
  8. package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
  9. package/dist/lib/core/SingleAgentClient.js +15 -0
  10. package/dist/lib/core/SingleAgentClient.js.map +1 -1
  11. package/dist/lib/core/TaskExecutor.d.ts +7 -0
  12. package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
  13. package/dist/lib/core/TaskExecutor.js +9 -2
  14. package/dist/lib/core/TaskExecutor.js.map +1 -1
  15. package/dist/lib/index.d.ts +1 -1
  16. package/dist/lib/index.d.ts.map +1 -1
  17. package/dist/lib/index.js +7 -8
  18. package/dist/lib/index.js.map +1 -1
  19. package/dist/lib/protocols/index.d.ts +3 -1
  20. package/dist/lib/protocols/index.d.ts.map +1 -1
  21. package/dist/lib/protocols/index.js +23 -14
  22. package/dist/lib/protocols/index.js.map +1 -1
  23. package/dist/lib/schemas/index.d.ts +1 -1
  24. package/dist/lib/schemas/index.js +1 -1
  25. package/dist/lib/server/create-adcp-server.d.ts +142 -11
  26. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  27. package/dist/lib/server/create-adcp-server.js +211 -2
  28. package/dist/lib/server/create-adcp-server.js.map +1 -1
  29. package/dist/lib/server/ctx-metadata/backends/memory.d.ts +27 -0
  30. package/dist/lib/server/ctx-metadata/backends/memory.d.ts.map +1 -0
  31. package/dist/lib/server/ctx-metadata/backends/memory.js +72 -0
  32. package/dist/lib/server/ctx-metadata/backends/memory.js.map +1 -0
  33. package/dist/lib/server/ctx-metadata/backends/pg.d.ts +62 -0
  34. package/dist/lib/server/ctx-metadata/backends/pg.d.ts.map +1 -0
  35. package/dist/lib/server/ctx-metadata/backends/pg.js +145 -0
  36. package/dist/lib/server/ctx-metadata/backends/pg.js.map +1 -0
  37. package/dist/lib/server/ctx-metadata/index.d.ts +15 -0
  38. package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -0
  39. package/dist/lib/server/ctx-metadata/index.js +28 -0
  40. package/dist/lib/server/ctx-metadata/index.js.map +1 -0
  41. package/dist/lib/server/ctx-metadata/store.d.ts +177 -0
  42. package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -0
  43. package/dist/lib/server/ctx-metadata/store.js +327 -0
  44. package/dist/lib/server/ctx-metadata/store.js.map +1 -0
  45. package/dist/lib/server/ctx-metadata/wire-shape.d.ts +55 -0
  46. package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -0
  47. package/dist/lib/server/ctx-metadata/wire-shape.js +121 -0
  48. package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -0
  49. package/dist/lib/server/decisioning/account.d.ts +309 -0
  50. package/dist/lib/server/decisioning/account.d.ts.map +1 -0
  51. package/dist/lib/server/decisioning/account.js +102 -0
  52. package/dist/lib/server/decisioning/account.js.map +1 -0
  53. package/dist/lib/server/decisioning/admin-router.d.ts +75 -0
  54. package/dist/lib/server/decisioning/admin-router.d.ts.map +1 -0
  55. package/dist/lib/server/decisioning/admin-router.js +120 -0
  56. package/dist/lib/server/decisioning/admin-router.js.map +1 -0
  57. package/dist/lib/server/decisioning/assembly-helpers.d.ts +204 -0
  58. package/dist/lib/server/decisioning/assembly-helpers.d.ts.map +1 -0
  59. package/dist/lib/server/decisioning/assembly-helpers.js +173 -0
  60. package/dist/lib/server/decisioning/assembly-helpers.js.map +1 -0
  61. package/dist/lib/server/decisioning/async-outcome.d.ts +154 -0
  62. package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -0
  63. package/dist/lib/server/decisioning/async-outcome.js +239 -0
  64. package/dist/lib/server/decisioning/async-outcome.js.map +1 -0
  65. package/dist/lib/server/decisioning/capabilities.d.ts +251 -0
  66. package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -0
  67. package/dist/lib/server/decisioning/capabilities.js +16 -0
  68. package/dist/lib/server/decisioning/capabilities.js.map +1 -0
  69. package/dist/lib/server/decisioning/context.d.ts +212 -0
  70. package/dist/lib/server/decisioning/context.d.ts.map +1 -0
  71. package/dist/lib/server/decisioning/context.js +26 -0
  72. package/dist/lib/server/decisioning/context.js.map +1 -0
  73. package/dist/lib/server/decisioning/errors-typed.d.ts +104 -0
  74. package/dist/lib/server/decisioning/errors-typed.d.ts.map +1 -0
  75. package/dist/lib/server/decisioning/errors-typed.js +304 -0
  76. package/dist/lib/server/decisioning/errors-typed.js.map +1 -0
  77. package/dist/lib/server/decisioning/helpers.d.ts +131 -0
  78. package/dist/lib/server/decisioning/helpers.d.ts.map +1 -0
  79. package/dist/lib/server/decisioning/helpers.js +134 -0
  80. package/dist/lib/server/decisioning/helpers.js.map +1 -0
  81. package/dist/lib/server/decisioning/index.d.ts +46 -0
  82. package/dist/lib/server/decisioning/index.d.ts.map +1 -0
  83. package/dist/lib/server/decisioning/index.js +120 -0
  84. package/dist/lib/server/decisioning/index.js.map +1 -0
  85. package/dist/lib/server/decisioning/list-helpers.d.ts +53 -0
  86. package/dist/lib/server/decisioning/list-helpers.d.ts.map +1 -0
  87. package/dist/lib/server/decisioning/list-helpers.js +96 -0
  88. package/dist/lib/server/decisioning/list-helpers.js.map +1 -0
  89. package/dist/lib/server/decisioning/manifest-helpers.d.ts +56 -0
  90. package/dist/lib/server/decisioning/manifest-helpers.d.ts.map +1 -0
  91. package/dist/lib/server/decisioning/manifest-helpers.js +78 -0
  92. package/dist/lib/server/decisioning/manifest-helpers.js.map +1 -0
  93. package/dist/lib/server/decisioning/pagination.d.ts +21 -0
  94. package/dist/lib/server/decisioning/pagination.d.ts.map +1 -0
  95. package/dist/lib/server/decisioning/pagination.js +12 -0
  96. package/dist/lib/server/decisioning/pagination.js.map +1 -0
  97. package/dist/lib/server/decisioning/platform.d.ts +188 -0
  98. package/dist/lib/server/decisioning/platform.d.ts.map +1 -0
  99. package/dist/lib/server/decisioning/platform.js +19 -0
  100. package/dist/lib/server/decisioning/platform.js.map +1 -0
  101. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +510 -0
  102. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -0
  103. package/dist/lib/server/decisioning/runtime/from-platform.js +2196 -0
  104. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -0
  105. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +114 -0
  106. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -0
  107. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +247 -0
  108. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -0
  109. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts +32 -0
  110. package/dist/lib/server/decisioning/runtime/protocol-for-tool.d.ts.map +1 -0
  111. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +127 -0
  112. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -0
  113. package/dist/lib/server/decisioning/runtime/task-registry.d.ts +105 -0
  114. package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -0
  115. package/dist/lib/server/decisioning/runtime/task-registry.js +96 -0
  116. package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -0
  117. package/dist/lib/server/decisioning/runtime/to-context.d.ts +54 -0
  118. package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -0
  119. package/dist/lib/server/decisioning/runtime/to-context.js +166 -0
  120. package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -0
  121. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +20 -0
  122. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -0
  123. package/dist/lib/server/decisioning/runtime/validate-platform.js +93 -0
  124. package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -0
  125. package/dist/lib/server/decisioning/specialisms/audiences.d.ts +72 -0
  126. package/dist/lib/server/decisioning/specialisms/audiences.d.ts.map +1 -0
  127. package/dist/lib/server/decisioning/specialisms/audiences.js +15 -0
  128. package/dist/lib/server/decisioning/specialisms/audiences.js.map +1 -0
  129. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts +92 -0
  130. package/dist/lib/server/decisioning/specialisms/brand-rights.d.ts.map +1 -0
  131. package/dist/lib/server/decisioning/specialisms/brand-rights.js +28 -0
  132. package/dist/lib/server/decisioning/specialisms/brand-rights.js.map +1 -0
  133. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts +67 -0
  134. package/dist/lib/server/decisioning/specialisms/campaign-governance.d.ts.map +1 -0
  135. package/dist/lib/server/decisioning/specialisms/campaign-governance.js +31 -0
  136. package/dist/lib/server/decisioning/specialisms/campaign-governance.js.map +1 -0
  137. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts +78 -0
  138. package/dist/lib/server/decisioning/specialisms/content-standards.d.ts.map +1 -0
  139. package/dist/lib/server/decisioning/specialisms/content-standards.js +35 -0
  140. package/dist/lib/server/decisioning/specialisms/content-standards.js.map +1 -0
  141. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +81 -0
  142. package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -0
  143. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js +28 -0
  144. package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -0
  145. package/dist/lib/server/decisioning/specialisms/creative.d.ts +144 -0
  146. package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -0
  147. package/dist/lib/server/decisioning/specialisms/creative.js +19 -0
  148. package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -0
  149. package/dist/lib/server/decisioning/specialisms/lists.d.ts +61 -0
  150. package/dist/lib/server/decisioning/specialisms/lists.d.ts.map +1 -0
  151. package/dist/lib/server/decisioning/specialisms/lists.js +30 -0
  152. package/dist/lib/server/decisioning/specialisms/lists.js.map +1 -0
  153. package/dist/lib/server/decisioning/specialisms/sales.d.ts +163 -0
  154. package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -0
  155. package/dist/lib/server/decisioning/specialisms/sales.js +64 -0
  156. package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -0
  157. package/dist/lib/server/decisioning/specialisms/signals.d.ts +64 -0
  158. package/dist/lib/server/decisioning/specialisms/signals.d.ts.map +1 -0
  159. package/dist/lib/server/decisioning/specialisms/signals.js +28 -0
  160. package/dist/lib/server/decisioning/specialisms/signals.js.map +1 -0
  161. package/dist/lib/server/decisioning/start-time.d.ts +76 -0
  162. package/dist/lib/server/decisioning/start-time.d.ts.map +1 -0
  163. package/dist/lib/server/decisioning/start-time.js +81 -0
  164. package/dist/lib/server/decisioning/start-time.js.map +1 -0
  165. package/dist/lib/server/decisioning/status-changes.d.ts +165 -0
  166. package/dist/lib/server/decisioning/status-changes.d.ts.map +1 -0
  167. package/dist/lib/server/decisioning/status-changes.js +131 -0
  168. package/dist/lib/server/decisioning/status-changes.js.map +1 -0
  169. package/dist/lib/server/decisioning/status-mappers.d.ts +46 -0
  170. package/dist/lib/server/decisioning/status-mappers.d.ts.map +1 -0
  171. package/dist/lib/server/decisioning/status-mappers.js +46 -0
  172. package/dist/lib/server/decisioning/status-mappers.js.map +1 -0
  173. package/dist/lib/server/decisioning/tenant-registry.d.ts +289 -0
  174. package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -0
  175. package/dist/lib/server/decisioning/tenant-registry.js +503 -0
  176. package/dist/lib/server/decisioning/tenant-registry.js.map +1 -0
  177. package/dist/lib/server/express-adapter.d.ts +1 -1
  178. package/dist/lib/server/express-adapter.js +1 -1
  179. package/dist/lib/server/governance.d.ts +1 -1
  180. package/dist/lib/server/governance.js +1 -1
  181. package/dist/lib/server/idempotency/store.d.ts +1 -1
  182. package/dist/lib/server/idempotency/store.js +1 -1
  183. package/dist/lib/server/index.d.ts +9 -2
  184. package/dist/lib/server/index.d.ts.map +1 -1
  185. package/dist/lib/server/index.js +79 -4
  186. package/dist/lib/server/index.js.map +1 -1
  187. package/dist/lib/server/legacy/v5/index.d.ts +38 -0
  188. package/dist/lib/server/legacy/v5/index.d.ts.map +1 -0
  189. package/dist/lib/server/legacy/v5/index.js +60 -0
  190. package/dist/lib/server/legacy/v5/index.js.map +1 -0
  191. package/dist/lib/server/normalize-errors.d.ts +88 -0
  192. package/dist/lib/server/normalize-errors.d.ts.map +1 -0
  193. package/dist/lib/server/normalize-errors.js +146 -0
  194. package/dist/lib/server/normalize-errors.js.map +1 -0
  195. package/dist/lib/server/pick-safe-details.d.ts +90 -0
  196. package/dist/lib/server/pick-safe-details.d.ts.map +1 -0
  197. package/dist/lib/server/pick-safe-details.js +148 -0
  198. package/dist/lib/server/pick-safe-details.js.map +1 -0
  199. package/dist/lib/server/postgres-state-store.d.ts +1 -1
  200. package/dist/lib/server/postgres-state-store.js +1 -1
  201. package/dist/lib/server/responses.d.ts +38 -0
  202. package/dist/lib/server/responses.d.ts.map +1 -1
  203. package/dist/lib/server/responses.js +38 -0
  204. package/dist/lib/server/responses.js.map +1 -1
  205. package/dist/lib/server/state-store.d.ts +1 -1
  206. package/dist/lib/server/state-store.js +1 -1
  207. package/dist/lib/server/test-controller.d.ts +10 -3
  208. package/dist/lib/server/test-controller.d.ts.map +1 -1
  209. package/dist/lib/server/test-controller.js +10 -3
  210. package/dist/lib/server/test-controller.js.map +1 -1
  211. package/dist/lib/testing/comply-controller.d.ts +47 -1
  212. package/dist/lib/testing/comply-controller.d.ts.map +1 -1
  213. package/dist/lib/testing/comply-controller.js +11 -4
  214. package/dist/lib/testing/comply-controller.js.map +1 -1
  215. package/dist/lib/testing/index.d.ts +1 -1
  216. package/dist/lib/testing/index.d.ts.map +1 -1
  217. package/dist/lib/testing/index.js.map +1 -1
  218. package/dist/lib/testing/personas/index.d.ts +143 -0
  219. package/dist/lib/testing/personas/index.d.ts.map +1 -0
  220. package/dist/lib/testing/personas/index.js +190 -0
  221. package/dist/lib/testing/personas/index.js.map +1 -0
  222. package/dist/lib/testing/storyboard/index.d.ts +1 -1
  223. package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
  224. package/dist/lib/testing/storyboard/index.js +3 -2
  225. package/dist/lib/testing/storyboard/index.js.map +1 -1
  226. package/dist/lib/testing/storyboard/runner.d.ts +13 -0
  227. package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
  228. package/dist/lib/testing/storyboard/runner.js +179 -7
  229. package/dist/lib/testing/storyboard/runner.js.map +1 -1
  230. package/dist/lib/types/adcp.d.ts.map +1 -1
  231. package/dist/lib/types/adcp.js +1 -0
  232. package/dist/lib/types/adcp.js.map +1 -1
  233. package/dist/lib/types/asset-instances.d.ts +1 -0
  234. package/dist/lib/types/asset-instances.d.ts.map +1 -1
  235. package/dist/lib/types/core.generated.d.ts +203 -98
  236. package/dist/lib/types/core.generated.d.ts.map +1 -1
  237. package/dist/lib/types/core.generated.js +1 -1
  238. package/dist/lib/types/index.d.ts +1 -0
  239. package/dist/lib/types/index.d.ts.map +1 -1
  240. package/dist/lib/types/index.js.map +1 -1
  241. package/dist/lib/types/schemas.generated.d.ts +599 -159
  242. package/dist/lib/types/schemas.generated.d.ts.map +1 -1
  243. package/dist/lib/types/schemas.generated.js +175 -94
  244. package/dist/lib/types/schemas.generated.js.map +1 -1
  245. package/dist/lib/types/tools.generated.d.ts +315 -46
  246. package/dist/lib/types/tools.generated.d.ts.map +1 -1
  247. package/dist/lib/utils/capabilities.d.ts +1 -1
  248. package/dist/lib/utils/capabilities.d.ts.map +1 -1
  249. package/dist/lib/utils/capabilities.js +6 -0
  250. package/dist/lib/utils/capabilities.js.map +1 -1
  251. package/dist/lib/validation/schema-validator.d.ts +13 -0
  252. package/dist/lib/validation/schema-validator.d.ts.map +1 -1
  253. package/dist/lib/validation/schema-validator.js +240 -3
  254. package/dist/lib/validation/schema-validator.js.map +1 -1
  255. package/dist/lib/version.d.ts +3 -3
  256. package/dist/lib/version.d.ts.map +1 -1
  257. package/dist/lib/version.js +3 -3
  258. package/dist/lib/version.js.map +1 -1
  259. package/docs/guides/BUILD-AN-AGENT.md +30 -5
  260. package/docs/llms.txt +28 -17
  261. package/examples/README.md +3 -1
  262. package/examples/decisioning-platform-broadcast-tv.ts +300 -0
  263. package/examples/decisioning-platform-identity-graph.ts +214 -0
  264. package/examples/decisioning-platform-mock-seller.ts +332 -0
  265. package/examples/decisioning-platform-multi-tenant.ts +128 -0
  266. package/examples/decisioning-platform-programmatic.ts +254 -0
  267. package/examples/signals-agent.ts +1 -1
  268. package/package.json +13 -2
  269. package/skills/build-brand-rights-agent/SKILL.md +10 -3
  270. package/skills/build-creative-agent/SKILL.md +94 -64
  271. package/skills/build-decisioning-creative-template/SKILL.md +554 -0
  272. package/skills/build-decisioning-platform/SKILL.md +304 -0
  273. package/skills/build-decisioning-platform/advanced/BRAND-RIGHTS.md +25 -0
  274. package/skills/build-decisioning-platform/advanced/COMPLIANCE.md +23 -0
  275. package/skills/build-decisioning-platform/advanced/GOVERNANCE.md +24 -0
  276. package/skills/build-decisioning-platform/advanced/HITL.md +34 -0
  277. package/skills/build-decisioning-platform/advanced/IDEMPOTENCY.md +52 -0
  278. package/skills/build-decisioning-platform/advanced/MULTI-TENANT.md +47 -0
  279. package/skills/build-decisioning-platform/advanced/OAUTH.md +22 -0
  280. package/skills/build-decisioning-platform/advanced/REFERENCE.md +991 -0
  281. package/skills/build-decisioning-platform/advanced/SANDBOX.md +24 -0
  282. package/skills/build-decisioning-platform/advanced/STATE-MACHINE.md +52 -0
  283. package/skills/build-decisioning-signal-marketplace/SKILL.md +269 -0
  284. package/skills/build-generative-seller-agent/SKILL.md +89 -53
  285. package/skills/build-governance-agent/SKILL.md +76 -45
  286. package/skills/build-retail-media-agent/SKILL.md +87 -62
  287. package/skills/build-seller-agent/SKILL.md +384 -255
  288. package/skills/build-seller-agent/deployment.md +5 -3
  289. package/skills/build-seller-agent/specialisms/audience-sync.md +0 -2
  290. package/skills/build-seller-agent/specialisms/sales-broadcast-tv.md +0 -2
  291. package/skills/build-seller-agent/specialisms/sales-guaranteed.md +0 -2
  292. package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +0 -2
  293. package/skills/build-seller-agent/specialisms/sales-proposal-mode.md +0 -2
  294. package/skills/build-seller-agent/specialisms/sales-social.md +0 -2
  295. package/skills/build-seller-agent/specialisms/signed-requests.md +0 -2
  296. package/skills/build-si-agent/SKILL.md +40 -32
  297. package/skills/build-signals-agent/SKILL.md +139 -92
  298. package/skills/call-adcp-agent.previous/SKILL.md +5 -0
@@ -0,0 +1,24 @@
1
+ # Sandbox routing
2
+
3
+ When a buyer sends `account: { id: '...', sandbox: true }`, route the call to your platform's test/staging environment instead of production. The buyer wants to validate against your real surface without touching prod.
4
+
5
+ ```ts
6
+ accounts: {
7
+ resolve: async (ref) => {
8
+ if (ref?.sandbox === true) {
9
+ return { id: ref.id, operator: 'mypub-sandbox', ctx_metadata: { env: 'staging' } };
10
+ }
11
+ return { id: ref?.id ?? 'pub_main', operator: 'mypub', ctx_metadata: { env: 'production' } };
12
+ },
13
+ ...
14
+ }
15
+
16
+ createMediaBuy: async (req, ctx) => {
17
+ const target = ctx.account.ctx_metadata.env === 'staging' ? this.gamSandbox : this.gam;
18
+ return await target.createOrder(req);
19
+ }
20
+ ```
21
+
22
+ There is no separate "dry-run" mode — sandbox subsumes "validate against real platform without writing to production." Tool-specific `dry_run` flags on `sync_catalogs` / `sync_creatives` are wire fields you receive and honor; they are NOT a framework-level mode.
23
+
24
+ See `REFERENCE.md` for the full sandbox section.
@@ -0,0 +1,52 @@
1
+ # Media buy state machine
2
+
3
+ The wire spec defines a closed status enum; transitions are constrained. Sales agents that get state wrong fail compliance.
4
+
5
+ ## States and transitions
6
+
7
+ ```
8
+ pending_creatives → buyer hasn't pushed creatives yet
9
+
10
+ pending_start → creatives synced + approved; awaiting campaign start_time
11
+
12
+ active → delivering
13
+
14
+ paused → buyer or operator paused (resumable)
15
+
16
+ completed → end_time passed naturally
17
+
18
+ canceled → terminated before end_time
19
+
20
+ rejected → never accepted (compliance / governance fail at create time)
21
+ ```
22
+
23
+ ## Rules
24
+
25
+ 1. **`createMediaBuy` returns `pending_creatives`** unless creatives were synced in the same request batch (rare). Returning `active` immediately is wrong — the buyer hasn't synced anything yet.
26
+ 2. **`syncCreatives` doesn't change media-buy status itself.** Operator approval flow / start_time tick advances it. Use `publishStatusChange(...)` to emit the transition.
27
+ 3. **Transition events are spec-aligned**: `pending_creatives` → `pending_start` happens when ALL packages have at least one approved creative. `pending_start` → `active` happens when `start_time` is reached.
28
+ 4. **`paused` and `active` are reversible.** `canceled`, `completed`, `rejected` are terminal.
29
+ 5. **Illegal transitions throw `InvalidStateError`.** Buyer trying to update a `completed` buy → throw, don't silently accept.
30
+
31
+ ## Pattern: emit transitions via the bus
32
+
33
+ ```ts
34
+ import { publishStatusChange } from '@adcp/sdk/server';
35
+
36
+ // When all packages have approved creatives:
37
+ publishStatusChange({
38
+ account_id: ctx.account.id,
39
+ resource_type: 'media_buy',
40
+ resource_id: mediaBuyId,
41
+ status: 'pending_start',
42
+ occurred_at: new Date().toISOString(),
43
+ });
44
+ ```
45
+
46
+ Buyers subscribed via push_notification_config or MCP Resources see the transition.
47
+
48
+ ## Where to track state
49
+
50
+ If your platform has the source of truth (GAM order status), read it on every `getMediaBuyDelivery` / `getMediaBuy` and project via `StatusMappers`. If your SDK is the source, use `ctx.ctxMetadata` to stash the current state per buy and update on every mutation.
51
+
52
+ See `REFERENCE.md` for the full status mapper section.
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: build-decisioning-signal-marketplace
3
+ description: Build an AdCP v6.0 (preview) signal-marketplace OR signal-owned decisioning platform — a data provider serving audience signals to buyers. Use ONLY when the user explicitly wants the v6.0 DecisioningPlatform shape; for v5.x handler-style signals agents, use `build-signals-agent` instead.
4
+ ---
5
+
6
+ # Build a Signals Decisioning Platform (v6.0 preview)
7
+
8
+ You're building a **signals data provider** that fits one of two AdCP specialisms:
9
+
10
+ - `signal-marketplace` — third-party data brokers serving curated signals (LiveRamp, Oracle Data Cloud, third-party DMPs)
11
+ - `signal-owned` — first-party data providers serving their own signals (publisher first-party data, retailer customer-graph)
12
+
13
+ Both share the same `SignalsPlatform` interface. Pick the specialism that matches your relationship to the data; the implementation shape is identical.
14
+
15
+ ## When this skill applies
16
+
17
+ - User wants a signals platform on the **v6.0 DecisioningPlatform** surface (preview, pre-GA)
18
+ - Specialism: `signal-marketplace` OR `signal-owned`
19
+ - SDK package: `@adcp/sdk` v5.18+ with the `decisioning` preview surface
20
+
21
+ **Wrong skill if:**
22
+
23
+ - User wants v5.x handler-style API → `skills/build-signals-agent/`
24
+ - User wants creative transforms → `skills/build-decisioning-creative-template/`
25
+ - User wants to sell media inventory → `skills/build-seller-agent/`
26
+
27
+ ## The whole shape (read this first)
28
+
29
+ A v6.0 signals platform implements two methods:
30
+
31
+ - **`getSignals(req, ctx) → Promise<GetSignalsResponse>`** — sync catalog discovery. Buyer sends filters; you return the matching signals. No async envelope.
32
+ - **`activateSignal(req, ctx) → Promise<ActivateSignalSuccess>`** — sync ack with async lifecycle. Provision the signal onto destination platforms (Snap, Meta, TikTok, etc.); return immediately with `deployments[]` rows in current state (`pending` is valid). Each deployment's eventual `activating` / `deployed` / `failed` flows via `publishStatusChange({ resource_type: 'signal', ... })`.
33
+
34
+ Both throw `AdcpError` for buyer-fixable rejection.
35
+
36
+ ### Minimal worked example — DataMatrix marketplace
37
+
38
+ ```ts
39
+ import {
40
+ AdcpError,
41
+ createAdcpServerFromPlatform,
42
+ publishStatusChange,
43
+ type DecisioningPlatform,
44
+ type SignalsPlatform,
45
+ type AccountStore,
46
+ } from '@adcp/sdk/server';
47
+ import type {
48
+ GetSignalsRequest,
49
+ GetSignalsResponse,
50
+ ActivateSignalRequest,
51
+ ActivateSignalSuccess,
52
+ AccountReference,
53
+ } from '@adcp/sdk/types';
54
+ import { serve } from '@adcp/sdk/server';
55
+
56
+ interface DataMatrixConfig {
57
+ /** Match-rate floor — signals below this rate to a destination are filtered out. */
58
+ minMatchRate: number;
59
+ }
60
+ interface DataMatrixMeta {
61
+ workspace_id: string;
62
+ }
63
+
64
+ class DataMatrixPlatform implements DecisioningPlatform<DataMatrixConfig, DataMatrixMeta> {
65
+ capabilities = {
66
+ specialisms: ['signal-marketplace'] as const,
67
+ creative_agents: [],
68
+ channels: [] as const,
69
+ pricingModels: ['cpm'] as const,
70
+ config: { minMatchRate: 0.15 } satisfies DataMatrixConfig,
71
+ };
72
+
73
+ accounts: AccountStore<DataMatrixMeta> = {
74
+ resolve: async (ref: AccountReference) => {
75
+ const id = 'account_id' in ref ? ref.account_id : 'dm_default';
76
+ return {
77
+ id,
78
+ name: 'DataMatrix default',
79
+ status: 'active',
80
+ operator: 'datamatrix.example.com',
81
+ metadata: { workspace_id: `ws_${id}` },
82
+ authInfo: { kind: 'api_key' },
83
+ };
84
+ },
85
+ };
86
+
87
+ signals: SignalsPlatform<DataMatrixMeta> = {
88
+ getSignals: async (_req: GetSignalsRequest): Promise<GetSignalsResponse> => {
89
+ return {
90
+ signals: [
91
+ {
92
+ signal_id: { source: 'agent', agent_url: 'https://datamatrix.example/signals', id: 'in_market_auto' },
93
+ signal_agent_segment_id: 'dm_seg_auto_001',
94
+ name: 'In-Market: Auto Buyers',
95
+ description: 'Active automotive shoppers within 90-day purchase window',
96
+ value_type: 'binary',
97
+ signal_type: 'marketplace',
98
+ data_provider: 'DataMatrix',
99
+ coverage_percentage: 18.5,
100
+ deployments: [],
101
+ pricing_options: [{ pricing_option_id: 'po_cpm_4', model: 'cpm', cpm: 4.0, currency: 'USD' }],
102
+ },
103
+ ],
104
+ };
105
+ },
106
+
107
+ activateSignal: async (req: ActivateSignalRequest): Promise<ActivateSignalSuccess> => {
108
+ if (!req.destinations.length) {
109
+ throw new AdcpError('INVALID_REQUEST', {
110
+ recovery: 'correctable',
111
+ message: 'destinations must be non-empty',
112
+ field: 'destinations',
113
+ });
114
+ }
115
+ // Sync ack: return deployments in `pending` state. Identity-graph
116
+ // match runs in background; publishStatusChange fires when each
117
+ // destination reaches activating / deployed / failed.
118
+ const deployments = req.destinations.map(d => ({
119
+ type: 'platform' as const,
120
+ platform: 'platform' in d ? d.platform : 'unknown',
121
+ account_id: 'account_id' in d ? d.account_id : undefined,
122
+ is_live: false,
123
+ }));
124
+
125
+ // Schedule background activation for each destination
126
+ const accountId = req.account && 'account_id' in req.account ? req.account.account_id : 'dm_default';
127
+ for (const dep of deployments) {
128
+ setTimeout(() => {
129
+ publishStatusChange({
130
+ account_id: accountId,
131
+ resource_type: 'signal',
132
+ resource_id: req.signal_agent_segment_id,
133
+ payload: { platform: dep.platform, status: 'deployed', is_live: true },
134
+ });
135
+ }, 100).unref?.();
136
+ }
137
+
138
+ return { deployments };
139
+ },
140
+ };
141
+ }
142
+
143
+ const platform = new DataMatrixPlatform();
144
+ const server = createAdcpServerFromPlatform(platform, {
145
+ name: 'datamatrix',
146
+ version: '1.0.0',
147
+ validation: { requests: 'strict', responses: 'strict' },
148
+ });
149
+ serve(() => server, { publicUrl: 'https://datamatrix.example.com' });
150
+ ```
151
+
152
+ ## Sync ack with async lifecycle
153
+
154
+ `activateSignal` is **always sync at the wire level** — `ActivateSignalResponse` has no `Submitted` arm. For platforms with slow identity-graph matches (5-30 min) or destination provisioning (hours), the canonical pattern is:
155
+
156
+ 1. Return `ActivateSignalSuccess` immediately with each deployment row in `pending` state
157
+ 2. Run the activation pipeline in background
158
+ 3. Emit `publishStatusChange({ resource_type: 'signal', ... })` for each deployment as it reaches `activating` / `deployed` / `failed`
159
+
160
+ Buyers subscribe via the resource-update channel to track activation progress.
161
+
162
+ ## Errors — `throw new AdcpError(...)`
163
+
164
+ Common codes for signals:
165
+
166
+ | Code | When |
167
+ | ---------------------- | --------------------------------------------------------------------------------------------- |
168
+ | `'SIGNAL_NOT_FOUND'` | unknown `signal_agent_segment_id` |
169
+ | `'POLICY_VIOLATION'` | buyer lacks rights to activate this data |
170
+ | `'INVALID_REQUEST'` | missing destinations, unrecognized destination shape, missing pricing_option_id when required |
171
+ | `'AUDIENCE_TOO_SMALL'` | activated audience falls below match-rate floor |
172
+ | `'RATE_LIMITED'` | upstream identity-graph throttled |
173
+
174
+ ```ts
175
+ activateSignal: async req => {
176
+ if (!signalCatalog.has(req.signal_agent_segment_id)) {
177
+ throw new AdcpError('SIGNAL_NOT_FOUND', {
178
+ recovery: 'terminal',
179
+ message: `Unknown signal: ${req.signal_agent_segment_id}`,
180
+ field: 'signal_agent_segment_id',
181
+ });
182
+ }
183
+ // ... happy path
184
+ };
185
+ ```
186
+
187
+ ## Idempotency — the framework dedupes; you thread the key downstream
188
+
189
+ Same pattern as creative-template — see [`build-decisioning-creative-template/SKILL.md`](../build-decisioning-creative-template/SKILL.md) § Idempotency. Pass `req.idempotency_key` into your upstream identity-graph / destination-provisioning API so dedup is end-to-end.
190
+
191
+ ## Capabilities
192
+
193
+ ```ts
194
+ capabilities = {
195
+ specialisms: ['signal-marketplace'] as const, // or 'signal-owned'
196
+ creative_agents: [], // not used by signals
197
+ channels: [] as const, // not used by signals
198
+ pricingModels: ['cpm'] as const, // signals are typically CPM uplift
199
+ config: {
200
+ /* your platform-specific config */
201
+ } satisfies YourConfig,
202
+ };
203
+ ```
204
+
205
+ ## Testing your platform
206
+
207
+ ```ts
208
+ import { createAdcpServerFromPlatform } from '@adcp/sdk/server';
209
+
210
+ const platform = new DataMatrixPlatform();
211
+ const server = createAdcpServerFromPlatform(platform, {
212
+ name: 'dm-test',
213
+ version: '0.0.1',
214
+ validation: { requests: 'off', responses: 'off' },
215
+ });
216
+
217
+ const result = await server.dispatchTestRequest({
218
+ method: 'tools/call',
219
+ params: {
220
+ name: 'get_signals',
221
+ arguments: {
222
+ filters: { catalog_types: ['third_party'], industries: ['automotive'] },
223
+ account: { account_id: 'test_acc' },
224
+ },
225
+ },
226
+ });
227
+ console.log(result.structuredContent);
228
+ ```
229
+
230
+ ## What NOT to do
231
+
232
+ ❌ **Don't import from `@adcp/sdk/server` for the platform shape.** Use `@adcp/sdk/server` for v6.0.
233
+
234
+ ❌ **Don't try to make activateSignal HITL.** The wire response has no `Submitted` arm. Sync ack + `publishStatusChange` is the correct pattern.
235
+
236
+ ❌ **Don't return error envelopes manually.** Throw `AdcpError`; the framework projects to wire shape.
237
+
238
+ ❌ **Don't write `as any` / `as never` in adopter code.** The wire types are typed; discriminators on `SignalID` (`source: 'catalog' | 'agent'`) and `Destination` (`type: 'platform' | ...`) narrow without casts.
239
+
240
+ ## Reference: imports cheat sheet
241
+
242
+ ```ts
243
+ // From @adcp/sdk/server
244
+ import {
245
+ AdcpError,
246
+ AccountNotFoundError,
247
+ createAdcpServerFromPlatform,
248
+ publishStatusChange,
249
+ type DecisioningPlatform,
250
+ type AccountStore,
251
+ type Account,
252
+ type SignalsPlatform,
253
+ type RequestContext,
254
+ type ErrorCode,
255
+ type AdcpStructuredError,
256
+ } from '@adcp/sdk/server';
257
+
258
+ // From @adcp/sdk/types — wire schemas (auto-generated)
259
+ import type {
260
+ GetSignalsRequest,
261
+ GetSignalsResponse,
262
+ ActivateSignalRequest,
263
+ ActivateSignalSuccess,
264
+ AccountReference,
265
+ } from '@adcp/sdk/types';
266
+
267
+ // From @adcp/sdk/server — HTTP serving
268
+ import { serve } from '@adcp/sdk/server';
269
+ ```
@@ -37,7 +37,7 @@ A generative seller inherits every sales specialism it supports (usually `sales-
37
37
 
38
38
  Every production seller — generative or otherwise — must wire these regardless of specialism. See `skills/build-seller-agent/SKILL.md` for the full treatment; minimum viable pointers:
39
39
 
40
- - **`idempotency_key`** on every mutating request (`create_media_buy`, `sync_creatives`, `build_creative`, `sync_catalogs`). Wire `createIdempotencyStore({ backend, ttlSeconds })` into `createAdcpServer({ idempotency })` — framework handles replay.
40
+ - **`idempotency_key`** on every mutating request (`create_media_buy`, `sync_creatives`, `build_creative`, `sync_catalogs`). Pass `createIdempotencyStore({ backend, ttlSeconds })` to `createAdcpServerFromPlatform(platform, { idempotency })` — framework handles replay.
41
41
  - **Authentication** (`serve({ authenticate: verifyApiKey(...)/verifyBearer(...) })`). A non-authenticated agent fails the `security_baseline` universal storyboard.
42
42
  - **Signature-header transparency**: even if you don't claim `signed-requests`, don't reject requests that carry `Signature-Input`/`Signature` headers.
43
43
 
@@ -82,7 +82,7 @@ Brands should be registered dynamically through `sync_accounts` — when a buyer
82
82
  >
83
83
  > **Cross-cutting pitfalls matrix runs keep catching:**
84
84
  >
85
- > - **Declare `capabilities: { specialisms: ['creative-generative'] }` on `createAdcpServer`.** The value is `string[]` of enum ids (not `[{id, version}]`). Agents that don't declare their specialism fail the grader with "No applicable tracks found" even if every tool works — tracks are gated on the specialism claim.
85
+ > - **Declare `capabilities.specialisms: ['creative-generative'] as const` on the `DecisioningPlatform` you pass to `createAdcpServerFromPlatform`.** The value is `string[]` of enum ids (not `[{id, version}]`). Agents that don't declare their specialism fail the grader with "No applicable tracks found" even if every tool works — tracks are gated on the specialism claim.
86
86
  > - `build_creative` response is `{ creative_manifest: { format_id, assets } }` — NOT `{ creative_id, status, quality, preview_url }`. Those are `sync_creatives` fields; don't leak them in.
87
87
  > - Each asset in `creative_manifest.assets` requires an `asset_type` discriminator — use the typed factories (`imageAsset({...})`, `videoAsset({...})`, `htmlAsset({...})`, `urlAsset({...})`) instead of writing the literal; discriminator is injected for you.
88
88
  > - `preview_creative` renders have the same pattern: use `urlRender({...})` / `htmlRender({...})` / `bothRender({...})` — they inject `output_format` and enforce the matching `preview_url` / `preview_html` at the type level.
@@ -94,7 +94,7 @@ Brands should be registered dynamically through `sync_accounts` — when a buyer
94
94
 
95
95
  Everything from the standard seller skill applies. The delta is in `list_creative_formats` and `sync_creatives`.
96
96
 
97
- **`get_adcp_capabilities`** — auto-generated by `createAdcpServer` from registered handlers. Do not implement manually.
97
+ **`get_adcp_capabilities`** — auto-generated by `createAdcpServerFromPlatform` from the typed `DecisioningPlatform` you provide. Do not implement manually.
98
98
 
99
99
  **`sync_accounts`** — `SyncAccountsRequestSchema.shape`
100
100
 
@@ -314,7 +314,7 @@ deliveryResponse({
314
314
 
315
315
  ### Context and Ext Passthrough
316
316
 
317
- `createAdcpServer` auto-echoes the request's `context` into every response — **do not set `context` yourself in your handler return values.** The framework injects it post-handler only when the field isn't already present.
317
+ The framework auto-echoes the request's `context` into every response — **do not set `context` yourself in your handler return values.** It's injected post-handler only when the field isn't already present.
318
318
 
319
319
  **Crucial:** `context` is schema-typed as an object. If your handler hand-sets a string or narrative description, validation fails with `/context: must be object` and the framework does not overwrite. Leave the field out entirely.
320
320
 
@@ -351,8 +351,9 @@ Validate with: `adcp storyboard run <agent> deterministic_testing --json`
351
351
 
352
352
  | SDK piece | Usage |
353
353
  | --------------------------------------- | ----------------------------------------------------------------------- |
354
- | `createAdcpServer(config)` | Create server with domain-grouped handlers, auto-generated capabilities |
355
- | `serve(() => createAdcpServer(config))` | Start HTTP server on `:3001/mcp` |
354
+ | `createAdcpServerFromPlatform(platform, opts)` | Create server from a typed `DecisioningPlatform` — compile-time specialism enforcement, auto-generated capabilities, ctx_metadata round-trip |
355
+ | `createAdcpServer(config)` *(legacy)* | v5 handler-bag entry. Mid-migration / escape-hatch only; reach via `@adcp/sdk/server/legacy/v5` |
356
+ | `serve(() => createAdcpServerFromPlatform(platform, opts))` | Start HTTP server on `:3001/mcp` |
356
357
  | `ctx.store` | State persistence — `get/put/patch/delete/list` domain objects |
357
358
  | `adcpError(code, { message })` | Structured error |
358
359
  | `registerTestController(server, store)` | Add `comply_test_controller` for deterministic testing |
@@ -361,7 +362,7 @@ Response builders (`productsResponse`, `mediaBuyResponse`, `syncCreativesRespons
361
362
 
362
363
  `get_adcp_capabilities` is auto-generated from registered handlers. Do not register it manually.
363
364
 
364
- Import: `import { createAdcpServer, serve, adcpError } from '@adcp/sdk';`
365
+ Import: `import { createAdcpServerFromPlatform, serve, adcpError } from '@adcp/sdk/server';`
365
366
 
366
367
  ## Setup
367
368
 
@@ -391,7 +392,7 @@ Minimal `tsconfig.json`:
391
392
  ## Implementation
392
393
 
393
394
  1. Single `.ts` file — all tools in one file
394
- 2. Use `createAdcpServer` with `mediaBuy` and `creative` domain groups
395
+ 2. Use `createAdcpServerFromPlatform` with `sales` and `creative` typed sub-platforms on a `DecisioningPlatform` class
395
396
  3. Handlers return raw data objects — the framework auto-applies response builders
396
397
  4. `get_adcp_capabilities` is auto-generated from registered handlers — do not register it manually
397
398
  5. Use `ctx.store` for state persistence (accounts, media buys, creatives)
@@ -401,8 +402,17 @@ Creative tools (`listCreativeFormats`, `syncCreatives`, `buildCreative`, `listCr
401
402
 
402
403
  ```typescript
403
404
  import { randomUUID } from 'node:crypto';
404
- import { createAdcpServer, serve, adcpError } from '@adcp/sdk';
405
- import { createIdempotencyStore, memoryBackend } from '@adcp/sdk/server';
405
+ import {
406
+ createAdcpServerFromPlatform,
407
+ serve,
408
+ adcpError,
409
+ createIdempotencyStore,
410
+ memoryBackend,
411
+ type DecisioningPlatform,
412
+ type SalesPlatform,
413
+ type CreativeBuilderPlatform,
414
+ type AccountStore,
415
+ } from '@adcp/sdk/server';
406
416
 
407
417
  // Idempotency — required for v3. Generative creation is expensive and
408
418
  // non-deterministic, so caching successful responses per key is critical:
@@ -412,51 +422,76 @@ const idempotency = createIdempotencyStore({
412
422
  ttlSeconds: 86400, // 24 hours (spec bounds: 1h–7d)
413
423
  });
414
424
 
425
+ class MyGenerativeSeller implements DecisioningPlatform {
426
+ capabilities = {
427
+ specialisms: ['sales-non-guaranteed', 'creative-generative'] as const,
428
+ creative_agents: [{ agent_url: 'https://example.com/creative/mcp' }],
429
+ pricingModels: ['cpm'] as const,
430
+ channels: ['display'] as const,
431
+ config: {},
432
+ };
433
+
434
+ accounts: AccountStore = {
435
+ resolve: async ref => ({
436
+ id: 'account_id' in ref ? ref.account_id : 'gen_acc_1',
437
+ operator: 'me',
438
+ ctx_metadata: {},
439
+ }),
440
+ upsert: async () => ({ ok: true, items: [] }),
441
+ list: async () => ({ items: [], nextCursor: null }),
442
+ };
443
+
444
+ sales: SalesPlatform = {
445
+ getProducts: async (req, ctx) => ({ products: PRODUCTS, sandbox: true }),
446
+ createMediaBuy: async (req, ctx) => {
447
+ const buy = {
448
+ media_buy_id: `mb_${randomUUID()}`,
449
+ status: 'pending_creatives' as const,
450
+ packages:
451
+ req.packages?.map(p => ({
452
+ package_id: `pkg_${randomUUID()}`,
453
+ product_id: p.product_id,
454
+ pricing_option_id: p.pricing_option_id,
455
+ budget: p.budget,
456
+ })) ?? [],
457
+ };
458
+ await ctx.store.put('media_buys', buy.media_buy_id, buy);
459
+ return buy;
460
+ },
461
+ updateMediaBuy: async (id, patch, ctx) => ({ media_buy_id: id, status: 'active' }),
462
+ getMediaBuys: async () => ({ media_buys: [] }),
463
+ getMediaBuyDelivery: async () => ({ deliveries: [] }),
464
+ listCreativeFormats: async () => ({ formats: FORMATS }),
465
+ // syncCreatives: generative formats take a `brief`; standard formats
466
+ // carry assets. Check format_id to decide processing. Framework
467
+ // idempotency ensures a retry of the same (key, payload) replays the
468
+ // prior response instead of re-running generation.
469
+ syncCreatives: async (creatives, ctx) =>
470
+ creatives.map(c => ({
471
+ creative_id: (c as { creative_id?: string }).creative_id ?? `cr_${randomUUID()}`,
472
+ action: 'created' as const,
473
+ })),
474
+ };
475
+
476
+ creative: CreativeBuilderPlatform = {
477
+ buildCreative: async (req, ctx) => {
478
+ // Generative path — read brief, call your model, return assets.
479
+ // Framework auto-stores the build for refine/lookup via ctx_metadata.
480
+ return { creative_manifest: { /* generated assets */ } };
481
+ },
482
+ previewCreative: async (req, ctx) => {
483
+ return { preview_url: '...' };
484
+ },
485
+ };
486
+ }
487
+
488
+ const platform = new MyGenerativeSeller();
489
+
415
490
  serve(() =>
416
- createAdcpServer({
491
+ createAdcpServerFromPlatform(platform, {
417
492
  name: 'My Generative Seller',
418
493
  version: '1.0.0',
419
494
  idempotency,
420
-
421
- // Principal scoping. MUST never return undefined — or every mutating
422
- // request rejects as SERVICE_UNAVAILABLE.
423
- resolveSessionKey: () => 'default-principal',
424
-
425
- mediaBuy: {
426
- getProducts: async (params, ctx) => ({ products: PRODUCTS, sandbox: true }),
427
- createMediaBuy: async (params, ctx) => {
428
- const buy = {
429
- media_buy_id: `mb_${randomUUID()}`,
430
- status: 'pending_creatives' as const,
431
- packages:
432
- params.packages?.map(p => ({
433
- package_id: `pkg_${randomUUID()}`,
434
- product_id: p.product_id,
435
- pricing_option_id: p.pricing_option_id,
436
- budget: p.budget,
437
- })) ?? [],
438
- };
439
- await ctx.store.put('media_buys', buy.media_buy_id, buy);
440
- return buy;
441
- },
442
- // ... updateMediaBuy, getMediaBuys, getMediaBuyDelivery
443
- },
444
-
445
- creative: {
446
- listCreativeFormats: async () => ({ formats: FORMATS }),
447
- syncCreatives: async (params, ctx) => {
448
- // Generative formats take a `brief`; standard formats carry assets.
449
- // Check the format_id to decide processing. Framework idempotency
450
- // ensures a retry of the same (key, payload) replays the prior
451
- // response instead of re-running generation.
452
- const results = params.creatives.map(c => ({
453
- creative_id: c.creative_id ?? `cr_${randomUUID()}`,
454
- action: 'created' as const,
455
- }));
456
- return { creatives: results };
457
- },
458
- // ... buildCreative, listCreatives, getCreativeDelivery
459
- },
460
495
  })
461
496
  );
462
497
  ```
@@ -564,8 +599,9 @@ Common failure decoder:
564
599
  | Ignore brand domain on brief sync | Validate brand, reject if unresolvable |
565
600
  | Same handler for brief and standard creatives | Check format_id to decide processing path |
566
601
  | format_ids in products don't match list_creative_formats | Buyers echo format_ids from products into sync_creatives — if your validation rejects your own format_ids, the buyer can't fulfill creative requirements |
567
- | Manually registering `get_adcp_capabilities` | Auto-generated by `createAdcpServer` — do not register it |
568
- | Using `server.tool()` instead of domain groups | Use `createAdcpServer({ mediaBuy: {...}, creative: {...} })` |
602
+ | Manually registering `get_adcp_capabilities` | Auto-generated by `createAdcpServerFromPlatform` from your typed `DecisioningPlatform` — do not register it |
603
+ | Using `server.tool()` instead of typed sub-platforms | Implement `sales: SalesPlatform` + `creative: CreativeBuilderPlatform` on a `DecisioningPlatform` class |
604
+ | Calling `createAdcpServer` directly in new code | Reach for `createAdcpServerFromPlatform`; `createAdcpServer` lives at `@adcp/sdk/server/legacy/v5` for mid-migration / escape-hatch only |
569
605
  | `sandbox: false` on mock data | Buyers may treat mock data as real |
570
606
  | Dropping `context` from responses | Echo `args.context` back unchanged in every response — buyers use it for correlation |
571
607