@adcp/sdk 6.7.0 → 6.8.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 (166) hide show
  1. package/bin/adcp.js +15 -3
  2. package/dist/lib/adapters/derived-account-store.d.ts +152 -0
  3. package/dist/lib/adapters/derived-account-store.d.ts.map +1 -0
  4. package/dist/lib/adapters/derived-account-store.js +135 -0
  5. package/dist/lib/adapters/derived-account-store.js.map +1 -0
  6. package/dist/lib/adapters/implicit-account-store.d.ts +3 -1
  7. package/dist/lib/adapters/implicit-account-store.d.ts.map +1 -1
  8. package/dist/lib/adapters/implicit-account-store.js +3 -1
  9. package/dist/lib/adapters/implicit-account-store.js.map +1 -1
  10. package/dist/lib/adapters/index.d.ts +1 -0
  11. package/dist/lib/adapters/index.d.ts.map +1 -1
  12. package/dist/lib/adapters/index.js +7 -1
  13. package/dist/lib/adapters/index.js.map +1 -1
  14. package/dist/lib/adapters/oauth-passthrough-resolver.d.ts +3 -1
  15. package/dist/lib/adapters/oauth-passthrough-resolver.d.ts.map +1 -1
  16. package/dist/lib/adapters/oauth-passthrough-resolver.js +3 -1
  17. package/dist/lib/adapters/oauth-passthrough-resolver.js.map +1 -1
  18. package/dist/lib/adapters/roster-account-store.d.ts +85 -24
  19. package/dist/lib/adapters/roster-account-store.d.ts.map +1 -1
  20. package/dist/lib/adapters/roster-account-store.js +52 -30
  21. package/dist/lib/adapters/roster-account-store.js.map +1 -1
  22. package/dist/lib/index.d.ts +3 -3
  23. package/dist/lib/index.d.ts.map +1 -1
  24. package/dist/lib/index.js +13 -8
  25. package/dist/lib/index.js.map +1 -1
  26. package/dist/lib/mock-server/creative-ad-server/seed-data.d.ts +81 -0
  27. package/dist/lib/mock-server/creative-ad-server/seed-data.d.ts.map +1 -0
  28. package/dist/lib/mock-server/creative-ad-server/seed-data.js +200 -0
  29. package/dist/lib/mock-server/creative-ad-server/seed-data.js.map +1 -0
  30. package/dist/lib/mock-server/creative-ad-server/server.d.ts +39 -0
  31. package/dist/lib/mock-server/creative-ad-server/server.d.ts.map +1 -0
  32. package/dist/lib/mock-server/creative-ad-server/server.js +618 -0
  33. package/dist/lib/mock-server/creative-ad-server/server.js.map +1 -0
  34. package/dist/lib/mock-server/index.d.ts.map +1 -1
  35. package/dist/lib/mock-server/index.js +180 -24
  36. package/dist/lib/mock-server/index.js.map +1 -1
  37. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.d.ts +66 -0
  38. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.d.ts.map +1 -0
  39. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.js +193 -0
  40. package/dist/lib/mock-server/sales-non-guaranteed/seed-data.js.map +1 -0
  41. package/dist/lib/mock-server/sales-non-guaranteed/server.d.ts +33 -0
  42. package/dist/lib/mock-server/sales-non-guaranteed/server.d.ts.map +1 -0
  43. package/dist/lib/mock-server/sales-non-guaranteed/server.js +782 -0
  44. package/dist/lib/mock-server/sales-non-guaranteed/server.js.map +1 -0
  45. package/dist/lib/mock-server/sponsored-intelligence/seed-data.d.ts +50 -0
  46. package/dist/lib/mock-server/sponsored-intelligence/seed-data.d.ts.map +1 -0
  47. package/dist/lib/mock-server/sponsored-intelligence/seed-data.js +133 -0
  48. package/dist/lib/mock-server/sponsored-intelligence/seed-data.js.map +1 -0
  49. package/dist/lib/mock-server/sponsored-intelligence/server.d.ts +13 -0
  50. package/dist/lib/mock-server/sponsored-intelligence/server.d.ts.map +1 -0
  51. package/dist/lib/mock-server/sponsored-intelligence/server.js +609 -0
  52. package/dist/lib/mock-server/sponsored-intelligence/server.js.map +1 -0
  53. package/dist/lib/protocols/mcp.d.ts.map +1 -1
  54. package/dist/lib/protocols/mcp.js +1 -41
  55. package/dist/lib/protocols/mcp.js.map +1 -1
  56. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  57. package/dist/lib/server/account-mode.d.ts +113 -0
  58. package/dist/lib/server/account-mode.d.ts.map +1 -0
  59. package/dist/lib/server/account-mode.js +125 -0
  60. package/dist/lib/server/account-mode.js.map +1 -0
  61. package/dist/lib/server/adcp-server.js +41 -0
  62. package/dist/lib/server/adcp-server.js.map +1 -1
  63. package/dist/lib/server/auth.d.ts +35 -0
  64. package/dist/lib/server/auth.d.ts.map +1 -1
  65. package/dist/lib/server/auth.js.map +1 -1
  66. package/dist/lib/server/create-adcp-server.d.ts +26 -9
  67. package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
  68. package/dist/lib/server/create-adcp-server.js +46 -20
  69. package/dist/lib/server/create-adcp-server.js.map +1 -1
  70. package/dist/lib/server/ctx-metadata/store.d.ts +1 -1
  71. package/dist/lib/server/ctx-metadata/store.d.ts.map +1 -1
  72. package/dist/lib/server/ctx-metadata/store.js +1 -0
  73. package/dist/lib/server/ctx-metadata/store.js.map +1 -1
  74. package/dist/lib/server/decisioning/account.d.ts +5 -0
  75. package/dist/lib/server/decisioning/account.d.ts.map +1 -1
  76. package/dist/lib/server/decisioning/account.js.map +1 -1
  77. package/dist/lib/server/decisioning/buyer-agent.d.ts +37 -4
  78. package/dist/lib/server/decisioning/buyer-agent.d.ts.map +1 -1
  79. package/dist/lib/server/decisioning/buyer-agent.js +12 -2
  80. package/dist/lib/server/decisioning/buyer-agent.js.map +1 -1
  81. package/dist/lib/server/decisioning/compose.d.ts +33 -2
  82. package/dist/lib/server/decisioning/compose.d.ts.map +1 -1
  83. package/dist/lib/server/decisioning/compose.js +13 -46
  84. package/dist/lib/server/decisioning/compose.js.map +1 -1
  85. package/dist/lib/server/decisioning/index.d.ts +2 -1
  86. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  87. package/dist/lib/server/decisioning/index.js +2 -1
  88. package/dist/lib/server/decisioning/index.js.map +1 -1
  89. package/dist/lib/server/decisioning/platform-helpers.d.ts +18 -0
  90. package/dist/lib/server/decisioning/platform-helpers.d.ts.map +1 -1
  91. package/dist/lib/server/decisioning/platform-helpers.js +20 -0
  92. package/dist/lib/server/decisioning/platform-helpers.js.map +1 -1
  93. package/dist/lib/server/decisioning/platform.d.ts +19 -21
  94. package/dist/lib/server/decisioning/platform.d.ts.map +1 -1
  95. package/dist/lib/server/decisioning/platform.js.map +1 -1
  96. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  97. package/dist/lib/server/decisioning/runtime/from-platform.js +334 -44
  98. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  99. package/dist/lib/server/decisioning/runtime/observed-modes.d.ts +40 -0
  100. package/dist/lib/server/decisioning/runtime/observed-modes.d.ts.map +1 -0
  101. package/dist/lib/server/decisioning/runtime/observed-modes.js +82 -0
  102. package/dist/lib/server/decisioning/runtime/observed-modes.js.map +1 -0
  103. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +2 -2
  104. package/dist/lib/server/decisioning/runtime/protocol-for-tool.js.map +1 -1
  105. package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -1
  106. package/dist/lib/server/decisioning/runtime/validate-platform.js +9 -1
  107. package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -1
  108. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.d.ts +125 -0
  109. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.d.ts.map +1 -0
  110. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.js +52 -0
  111. package/dist/lib/server/decisioning/specialisms/sponsored-intelligence.js.map +1 -0
  112. package/dist/lib/server/decisioning/tenant-registry.d.ts +16 -0
  113. package/dist/lib/server/decisioning/tenant-registry.d.ts.map +1 -1
  114. package/dist/lib/server/decisioning/tenant-registry.js.map +1 -1
  115. package/dist/lib/server/index.d.ts +4 -1
  116. package/dist/lib/server/index.d.ts.map +1 -1
  117. package/dist/lib/server/index.js +9 -3
  118. package/dist/lib/server/index.js.map +1 -1
  119. package/dist/lib/server/serve.js +20 -2
  120. package/dist/lib/server/serve.js.map +1 -1
  121. package/dist/lib/server/test-controller.d.ts +3 -0
  122. package/dist/lib/server/test-controller.d.ts.map +1 -1
  123. package/dist/lib/server/test-controller.js +23 -20
  124. package/dist/lib/server/test-controller.js.map +1 -1
  125. package/dist/lib/testing/comply-controller.d.ts +23 -2
  126. package/dist/lib/testing/comply-controller.d.ts.map +1 -1
  127. package/dist/lib/testing/comply-controller.js +19 -2
  128. package/dist/lib/testing/comply-controller.js.map +1 -1
  129. package/dist/lib/testing/index.d.ts +1 -1
  130. package/dist/lib/testing/index.d.ts.map +1 -1
  131. package/dist/lib/testing/index.js.map +1 -1
  132. package/dist/lib/testing/storyboard/validations.d.ts.map +1 -1
  133. package/dist/lib/testing/storyboard/validations.js +36 -54
  134. package/dist/lib/testing/storyboard/validations.js.map +1 -1
  135. package/dist/lib/testing/test-controller.d.ts +10 -4
  136. package/dist/lib/testing/test-controller.d.ts.map +1 -1
  137. package/dist/lib/testing/test-controller.js +9 -3
  138. package/dist/lib/testing/test-controller.js.map +1 -1
  139. package/dist/lib/types/index.d.ts +3 -2
  140. package/dist/lib/types/index.d.ts.map +1 -1
  141. package/dist/lib/types/index.js +3 -0
  142. package/dist/lib/types/index.js.map +1 -1
  143. package/dist/lib/utils/glob.d.ts +4 -2
  144. package/dist/lib/utils/glob.d.ts.map +1 -1
  145. package/dist/lib/utils/glob.js +4 -2
  146. package/dist/lib/utils/glob.js.map +1 -1
  147. package/dist/lib/version.d.ts +3 -3
  148. package/dist/lib/version.js +3 -3
  149. package/docs/llms.txt +2 -2
  150. package/examples/README.md +29 -13
  151. package/examples/hello-cluster.ts +62 -23
  152. package/examples/hello_creative_adapter_ad_server.ts +790 -0
  153. package/examples/hello_seller_adapter_guaranteed.ts +80 -22
  154. package/examples/hello_seller_adapter_non_guaranteed.ts +1020 -0
  155. package/examples/hello_si_adapter_brand.ts +572 -0
  156. package/package.json +3 -2
  157. package/skills/build-creative-agent/SKILL.md +103 -183
  158. package/skills/build-generative-seller-agent/SKILL.md +15 -9
  159. package/skills/build-governance-agent/SKILL.md +20 -11
  160. package/skills/build-retail-media-agent/SKILL.md +10 -8
  161. package/skills/build-seller-agent/SKILL.md +15 -13
  162. package/skills/build-seller-agent/specialisms/sales-non-guaranteed.md +9 -31
  163. package/skills/build-si-agent/SKILL.md +251 -196
  164. package/skills/build-signals-agent/SKILL.md +2 -0
  165. package/skills/call-adcp-agent/SKILL.md +7 -1
  166. package/skills/call-adcp-agent.previous/SKILL.md +0 -261
@@ -55,6 +55,8 @@ import {
55
55
  createUpstreamHttpClient,
56
56
  memoryBackend,
57
57
  AdcpError,
58
+ getAccountMode,
59
+ assertMediaBuyTransition,
58
60
  type DecisioningPlatform,
59
61
  type SalesCorePlatform,
60
62
  type SalesIngestionPlatform,
@@ -502,10 +504,15 @@ class SalesGuaranteedAdapter implements DecisioningPlatform<Record<string, never
502
504
  // sandbox tenant their IO desk owns; either way, this in-example
503
505
  // synthesis isn't appropriate for prod traffic.
504
506
  //
505
- // Gate is `ADCP_SANDBOX === '1'` exclusively single-source so
506
- // accidentally setting `ADCP_SANDBOX` in any non-sandbox environment
507
- // is the only way this branch fires.
508
- if (ref.sandbox === true && process.env['ADCP_SANDBOX'] === '1') {
507
+ // Gate is `ref.sandbox === true` from the wire `AccountReference`
508
+ // (per `core/account-ref.json`). Stamping `mode: 'sandbox'` on the
509
+ // returned `Account` is what admits the framework's
510
+ // `comply_test_controller` gate see
511
+ // `src/lib/server/decisioning/runtime/from-platform.ts` and
512
+ // `docs/proposals/lifecycle-state-and-sandbox-authority.md`. No env
513
+ // var is consulted; production traffic that doesn't set
514
+ // `sandbox: true` on the wire never hits this branch.
515
+ if (ref.sandbox === true) {
509
516
  const sandboxDomain = 'acmeoutdoor.example';
510
517
  const network = await upstream.lookupNetwork(sandboxDomain);
511
518
  if (!network) return null;
@@ -513,6 +520,7 @@ class SalesGuaranteedAdapter implements DecisioningPlatform<Record<string, never
513
520
  id: `${SANDBOX_ID_PREFIX}${network.network_code}`,
514
521
  name: `Sandbox: ${network.display_name}`,
515
522
  status: 'active',
523
+ mode: 'sandbox',
516
524
  ...(ref.operator !== undefined && { operator: ref.operator }),
517
525
  brand: { domain: ref.brand.domain ?? sandboxDomain },
518
526
  ctx_metadata: {
@@ -789,6 +797,9 @@ class SalesGuaranteedAdapter implements DecisioningPlatform<Record<string, never
789
797
  // but no creatives have been assigned. Buyers transition to
790
798
  // `active` after `sync_creatives` lands, which the framework
791
799
  // surfaces via `publishStatusChange` on `resource_type: 'media_buy'`.
800
+ // Stamp the buy's lifecycle entry so update_media_buy can enforce
801
+ // the spec's MediaBuyStatus state machine on subsequent patches.
802
+ localBuyStatus.set(order.order_id, 'pending_creatives');
792
803
  return {
793
804
  media_buy_id: order.order_id,
794
805
  status: 'pending_creatives',
@@ -805,13 +816,15 @@ class SalesGuaranteedAdapter implements DecisioningPlatform<Record<string, never
805
816
  // BASE `sales_guaranteed` storyboard tests the IO-signing async
806
817
  // path. Production sellers route every buy through the same path —
807
818
  // either always-HITL or always-sync, never both based on a runtime
808
- // flag. Belt-and-suspenders env re-check below: if the env flag
809
- // isn't set even though the id flowed in marked sandbox, fall
810
- // through to the production HITL path. Defends against an
811
- // upstream-resolved account that somehow carries the sandbox prefix
812
- // without the env being sandbox-mode.
813
- const isSandbox = ctx.account.id.startsWith(SANDBOX_ID_PREFIX) && process.env['ADCP_SANDBOX'] === '1';
814
- if (isSandbox) {
819
+ // flag.
820
+ //
821
+ // Trust signal is the resolver-stamped `mode: 'sandbox'` on the
822
+ // resolved account (per `Account.mode`, AdCP 6.7+). The synthesis
823
+ // branch in `accounts.resolve` is the only path that stamps it, so
824
+ // a production account whose id happens to share the sandbox prefix
825
+ // would still flow through the HITL path because its mode would be
826
+ // unset (defaults to `'live'`).
827
+ if (getAccountMode(ctx.account) === 'sandbox') {
815
828
  return completeIoAndCreateLineItems();
816
829
  }
817
830
  // ─── /TEST-ONLY ──────────────────────────────────────────────────
@@ -849,12 +862,36 @@ class SalesGuaranteedAdapter implements DecisioningPlatform<Record<string, never
849
862
  }
850
863
  }
851
864
  }
865
+
866
+ // State-machine enforcement. Lifecycle states the upstream mock doesn't
867
+ // track (`canceled`, `paused`) live in the local tracker; everything else
868
+ // reads from the upstream order.status mapping. Production sellers swap
869
+ // this for a single durable lookup against their order DB.
870
+ //
871
+ // The spec's `core/state-machine.yaml` declares `canceled` as a sink and
872
+ // a re-cancel as illegal — `assertMediaBuyTransition` throws
873
+ // `NOT_CANCELLABLE` on `canceled → canceled`, which is the
874
+ // `media_buy_seller/invalid_transitions` storyboard's contract.
875
+ const localStatus = localBuyStatus.get(buyId);
876
+ const currentStatus: MediaBuyStatus =
877
+ localStatus === 'canceled' || localStatus === 'paused' ? localStatus : mapMediaBuyStatus(order.status);
878
+ let nextStatus: MediaBuyStatus = currentStatus;
879
+ if ((patch as { canceled?: boolean }).canceled === true) {
880
+ assertMediaBuyTransition(currentStatus, 'canceled');
881
+ nextStatus = 'canceled';
882
+ localBuyStatus.set(buyId, nextStatus);
883
+ } else if ((patch as { paused?: boolean }).paused === true && currentStatus === 'active') {
884
+ assertMediaBuyTransition(currentStatus, 'paused');
885
+ nextStatus = 'paused';
886
+ localBuyStatus.set(buyId, nextStatus);
887
+ }
888
+
852
889
  // Mock doesn't model partial updates; production wires each patch
853
890
  // field onto the upstream's OrderService update endpoint. The
854
- // worked example just echoes success.
891
+ // worked example just echoes success with the post-transition status.
855
892
  return {
856
893
  media_buy_id: buyId,
857
- status: mapMediaBuyStatus(order.status),
894
+ status: nextStatus,
858
895
  };
859
896
  },
860
897
 
@@ -997,6 +1034,26 @@ const simulatedDelivery = new Map<
997
1034
  >();
998
1035
  // ─── /TEST-ONLY ──────────────────────────────────────────────────────────
999
1036
 
1037
+ // Local per-buy status tracker for state-machine enforcement on
1038
+ // `update_media_buy`. The mock-server doesn't model lifecycle transitions
1039
+ // (POST /v1/orders/{id} doesn't exist; cancellation is purely an adapter
1040
+ // concern in this worked example). Production sellers track buy state in
1041
+ // their order DB and check `MEDIA_BUY_TRANSITIONS` against the current
1042
+ // status before applying a patch — this Map stands in for that.
1043
+ //
1044
+ // SWAP: replace with a query against your order/lifecycle service. The
1045
+ // `media_buy_seller/invalid_transitions` storyboard exercises NOT_CANCELLABLE
1046
+ // on re-cancel (canceled → canceled is illegal per `core/state-machine.yaml`).
1047
+ type MediaBuyStatus =
1048
+ | 'pending_creatives'
1049
+ | 'pending_start'
1050
+ | 'active'
1051
+ | 'paused'
1052
+ | 'completed'
1053
+ | 'rejected'
1054
+ | 'canceled';
1055
+ const localBuyStatus = new Map<string, MediaBuyStatus>();
1056
+
1000
1057
  // Persist `packages[].targeting_overlay` from create_media_buy and echo it
1001
1058
  // on get_media_buys. The seller spec MANDATES this echo for any seller
1002
1059
  // claiming property-lists / collection-lists, and SHOULD echo any persisted
@@ -1024,17 +1081,18 @@ serve(
1024
1081
  // state transitions deterministically across cascade scenarios.
1025
1082
  // Production sellers don't need this surface — and shouldn't ship
1026
1083
  // it. Per `examples/comply-controller-seller.ts`, the recommended
1027
- // production posture is "don't register the controller at all";
1028
- // a seller running their own sandbox tenant gates registration on
1029
- // an env flag controlled by the deploy pipeline (`ADCP_SANDBOX=1`).
1084
+ // production posture is "don't register the controller at all".
1030
1085
  //
1031
- // SECURITY: gate is `ADCP_SANDBOX === '1'` exclusivelysingle env
1032
- // var. Don't add an `|| NODE_ENV === 'test'` clause staging boxes
1033
- // commonly run with `NODE_ENV=test` and the controller would open
1034
- // there too. The gate test (`test/examples/hello-seller-adapter-
1035
- // guaranteed.test.js`) sets `ADCP_SANDBOX=1` in `extraEnv`.
1086
+ // No `sandboxGate` herethe framework gate inside
1087
+ // `createAdcpServerFromPlatform` resolves the calling principal
1088
+ // through `accounts.resolve` and admits only when the resolved
1089
+ // account's `mode` is `'sandbox'` or `'mock'` (per `Account.mode`
1090
+ // in AdCP 6.7+). The synthesis branch in `accounts.resolve` above
1091
+ // stamps `mode: 'sandbox'` on cascade-scenario refs; production
1092
+ // refs flow through the live path with the field unset (default
1093
+ // `'live'`), so the framework gate refuses dispatch for them.
1094
+ // See `docs/proposals/lifecycle-state-and-sandbox-authority.md`.
1036
1095
  complyTest: {
1037
- sandboxGate: () => process.env['ADCP_SANDBOX'] === '1',
1038
1096
  seed: {
1039
1097
  media_buy: ({ media_buy_id, fixture }) => {
1040
1098
  const existing = seededMediaBuys.get(media_buy_id);