@adcp/sdk 6.10.0 → 6.12.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 (116) hide show
  1. package/bin/adcp-config.js +7 -1
  2. package/bin/adcp.js +191 -4
  3. package/dist/lib/adapters/index.d.ts +0 -2
  4. package/dist/lib/adapters/index.d.ts.map +1 -1
  5. package/dist/lib/adapters/index.js +1 -8
  6. package/dist/lib/adapters/index.js.map +1 -1
  7. package/dist/lib/index.d.ts +1 -1
  8. package/dist/lib/index.d.ts.map +1 -1
  9. package/dist/lib/index.js +2 -7
  10. package/dist/lib/index.js.map +1 -1
  11. package/dist/lib/mock-server/index.d.ts +2 -0
  12. package/dist/lib/mock-server/index.d.ts.map +1 -1
  13. package/dist/lib/mock-server/index.js +17 -0
  14. package/dist/lib/mock-server/index.js.map +1 -1
  15. package/dist/lib/mock-server/sales-guaranteed/recipe.d.ts +155 -0
  16. package/dist/lib/mock-server/sales-guaranteed/recipe.d.ts.map +1 -0
  17. package/dist/lib/mock-server/sales-guaranteed/recipe.js +107 -0
  18. package/dist/lib/mock-server/sales-guaranteed/recipe.js.map +1 -0
  19. package/dist/lib/mock-server/sales-guaranteed/server.d.ts.map +1 -1
  20. package/dist/lib/mock-server/sales-guaranteed/server.js +212 -0
  21. package/dist/lib/mock-server/sales-guaranteed/server.js.map +1 -1
  22. package/dist/lib/mock-server/sales-non-guaranteed/recipe.d.ts +123 -0
  23. package/dist/lib/mock-server/sales-non-guaranteed/recipe.d.ts.map +1 -0
  24. package/dist/lib/mock-server/sales-non-guaranteed/recipe.js +81 -0
  25. package/dist/lib/mock-server/sales-non-guaranteed/recipe.js.map +1 -0
  26. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  27. package/dist/lib/server/ctx-metadata/index.d.ts +1 -1
  28. package/dist/lib/server/ctx-metadata/index.d.ts.map +1 -1
  29. package/dist/lib/server/ctx-metadata/index.js +3 -1
  30. package/dist/lib/server/ctx-metadata/index.js.map +1 -1
  31. package/dist/lib/server/ctx-metadata/wire-shape.d.ts +21 -0
  32. package/dist/lib/server/ctx-metadata/wire-shape.d.ts.map +1 -1
  33. package/dist/lib/server/ctx-metadata/wire-shape.js +111 -0
  34. package/dist/lib/server/ctx-metadata/wire-shape.js.map +1 -1
  35. package/dist/lib/server/decisioning/async-outcome.d.ts +17 -0
  36. package/dist/lib/server/decisioning/async-outcome.d.ts.map +1 -1
  37. package/dist/lib/server/decisioning/async-outcome.js +23 -18
  38. package/dist/lib/server/decisioning/async-outcome.js.map +1 -1
  39. package/dist/lib/server/decisioning/context.d.ts +27 -2
  40. package/dist/lib/server/decisioning/context.d.ts.map +1 -1
  41. package/dist/lib/server/decisioning/index.d.ts +4 -0
  42. package/dist/lib/server/decisioning/index.d.ts.map +1 -1
  43. package/dist/lib/server/decisioning/index.js +16 -1
  44. package/dist/lib/server/decisioning/index.js.map +1 -1
  45. package/dist/lib/server/decisioning/platform.d.ts +17 -0
  46. package/dist/lib/server/decisioning/platform.d.ts.map +1 -1
  47. package/dist/lib/server/decisioning/platform.js.map +1 -1
  48. package/dist/lib/server/decisioning/proposal/dispatch.d.ts +203 -0
  49. package/dist/lib/server/decisioning/proposal/dispatch.d.ts.map +1 -0
  50. package/dist/lib/server/decisioning/proposal/dispatch.js +395 -0
  51. package/dist/lib/server/decisioning/proposal/dispatch.js.map +1 -0
  52. package/dist/lib/server/decisioning/proposal/index.d.ts +21 -0
  53. package/dist/lib/server/decisioning/proposal/index.d.ts.map +1 -0
  54. package/dist/lib/server/decisioning/proposal/index.js +37 -0
  55. package/dist/lib/server/decisioning/proposal/index.js.map +1 -0
  56. package/dist/lib/server/decisioning/proposal/lifecycle.d.ts +195 -0
  57. package/dist/lib/server/decisioning/proposal/lifecycle.d.ts.map +1 -0
  58. package/dist/lib/server/decisioning/proposal/lifecycle.js +366 -0
  59. package/dist/lib/server/decisioning/proposal/lifecycle.js.map +1 -0
  60. package/dist/lib/server/decisioning/proposal/mock-manager.d.ts +93 -0
  61. package/dist/lib/server/decisioning/proposal/mock-manager.d.ts.map +1 -0
  62. package/dist/lib/server/decisioning/proposal/mock-manager.js +109 -0
  63. package/dist/lib/server/decisioning/proposal/mock-manager.js.map +1 -0
  64. package/dist/lib/server/decisioning/proposal/store.d.ts +279 -0
  65. package/dist/lib/server/decisioning/proposal/store.d.ts.map +1 -0
  66. package/dist/lib/server/decisioning/proposal/store.js +291 -0
  67. package/dist/lib/server/decisioning/proposal/store.js.map +1 -0
  68. package/dist/lib/server/decisioning/proposal/types.d.ts +394 -0
  69. package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -0
  70. package/dist/lib/server/decisioning/proposal/types.js +58 -0
  71. package/dist/lib/server/decisioning/proposal/types.js.map +1 -0
  72. package/dist/lib/server/decisioning/runtime/from-platform.d.ts +25 -0
  73. package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
  74. package/dist/lib/server/decisioning/runtime/from-platform.js +204 -19
  75. package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
  76. package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
  77. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +5 -2
  78. package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
  79. package/dist/lib/server/decisioning/runtime/task-registry.d.ts +5 -0
  80. package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
  81. package/dist/lib/server/decisioning/runtime/task-registry.js +4 -1
  82. package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
  83. package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
  84. package/dist/lib/server/decisioning/runtime/to-context.js +10 -2
  85. package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
  86. package/dist/lib/server/index.d.ts +1 -1
  87. package/dist/lib/server/index.d.ts.map +1 -1
  88. package/dist/lib/server/index.js +3 -1
  89. package/dist/lib/server/index.js.map +1 -1
  90. package/dist/lib/server/test-controller.d.ts +2 -0
  91. package/dist/lib/server/test-controller.d.ts.map +1 -1
  92. package/dist/lib/server/test-controller.js +6 -11
  93. package/dist/lib/server/test-controller.js.map +1 -1
  94. package/dist/lib/testing/client.d.ts.map +1 -1
  95. package/dist/lib/testing/client.js +7 -1
  96. package/dist/lib/testing/client.js.map +1 -1
  97. package/dist/lib/testing/comply-controller.d.ts +2 -0
  98. package/dist/lib/testing/comply-controller.d.ts.map +1 -1
  99. package/dist/lib/testing/comply-controller.js.map +1 -1
  100. package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
  101. package/dist/lib/testing/storyboard/task-map.js +1 -0
  102. package/dist/lib/testing/storyboard/task-map.js.map +1 -1
  103. package/dist/lib/testing/storyboard/test-kit.d.ts.map +1 -1
  104. package/dist/lib/testing/storyboard/test-kit.js +4 -0
  105. package/dist/lib/testing/storyboard/test-kit.js.map +1 -1
  106. package/dist/lib/testing/types.d.ts +10 -0
  107. package/dist/lib/testing/types.d.ts.map +1 -1
  108. package/dist/lib/version.d.ts +3 -3
  109. package/dist/lib/version.js +3 -3
  110. package/examples/hello_seller_adapter_guaranteed.ts +29 -2
  111. package/examples/hello_seller_adapter_proposal_mode.ts +575 -0
  112. package/package.json +1 -1
  113. package/dist/lib/adapters/proposal-manager.d.ts +0 -142
  114. package/dist/lib/adapters/proposal-manager.d.ts.map +0 -1
  115. package/dist/lib/adapters/proposal-manager.js +0 -184
  116. package/dist/lib/adapters/proposal-manager.js.map +0 -1
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Proposal-dispatch — the v1.5 framework intercept seams.
3
+ *
4
+ * Pure functions that the runtime calls from the wire-handler shims
5
+ * (`getProducts`, `createMediaBuy`, `updateMediaBuy`,
6
+ * `getMediaBuyDelivery`). Each helper short-circuits when no manager /
7
+ * store is wired for the request, so the v1 path is preserved
8
+ * byte-for-byte.
9
+ *
10
+ * Five integration points (parity with `adcp-client-python.src/adcp/decisioning/proposal_dispatch.py`):
11
+ *
12
+ * - {@link maybeInterceptFinalize} — `getProducts` shim. Detects
13
+ * `refine[i].action: 'finalize'`, calls the manager's
14
+ * `finalizeProposal`, commits the proposal, returns the wire
15
+ * response. Returns `null` when no finalize entry / no
16
+ * finalize-capable manager.
17
+ * - {@link maybePersistDraftAfterGetProducts} — `getProducts` shim
18
+ * (post-call). Walks the response's `proposals[]`, validates
19
+ * `overlap ⊆ wire`, persists each as a draft.
20
+ * - {@link maybeReserveProposalForCreateMediaBuy} — `createMediaBuy`
21
+ * shim. When `proposal_id` is set, validates expiry + capability
22
+ * overlap, reserves the proposal (`COMMITTED → CONSUMING`), returns
23
+ * the recipes map for `ctx.recipes` hydration.
24
+ * - {@link finalizeProposalConsumption} — `createMediaBuy` shim
25
+ * (post-success). Promotes `CONSUMING → CONSUMED` and records the
26
+ * `mediaBuyId` back-reference.
27
+ * - {@link releaseProposalReservation} — `createMediaBuy` shim
28
+ * (failure rollback). Restores `CONSUMING → COMMITTED`.
29
+ * - {@link maybeHydrateRecipesForMediaBuyId} —
30
+ * `updateMediaBuy` / `getMediaBuyDelivery` shims. Reverse-index
31
+ * hydration via `getByMediaBuyId`. Re-runs capability-overlap
32
+ * validation per Resolutions §5.
33
+ *
34
+ * @public
35
+ * @packageDocumentation
36
+ */
37
+ import { type TaskHandoff } from '../async-outcome';
38
+ import type { GetProductsRequest, GetProductsResponse } from '../../../types/tools.generated';
39
+ import type { ProposalRecord, ProposalStore } from './store';
40
+ import type { FinalizeProposalSuccess, ProposalManager, Recipe } from './types';
41
+ /**
42
+ * Result of {@link maybeInterceptFinalize}.
43
+ *
44
+ * - `kind: 'intercepted'` — adopter's `finalizeProposal` was called.
45
+ * Caller threads `result` and `project` through the framework's
46
+ * standard `routeIfHandoff` so the projection callback fires
47
+ * synchronously for sync `FinalizeProposalSuccess` returns AND
48
+ * inside the background task for `TaskHandoff<FinalizeProposalSuccess>`
49
+ * returns. The projection commits the proposal store, emits the
50
+ * `proposal.finalized` log, and shapes the wire response.
51
+ * - `kind: 'pass'` — no finalize entry / no finalize-capable manager;
52
+ * caller continues with the standard `getProducts` dispatch.
53
+ *
54
+ * No special-case handling: finalize HITL inherits the framework's
55
+ * task-lifecycle posture (cancellation, restart-via-durable-store,
56
+ * deadline, webhook delivery) from `routeIfHandoff`, the same machinery
57
+ * that drives `createMediaBuy` HITL and `syncCreatives` HITL.
58
+ *
59
+ * @public
60
+ */
61
+ export type FinalizeInterceptResult<TRecipe extends Recipe = Recipe> = {
62
+ kind: 'intercepted';
63
+ result: FinalizeProposalSuccess<TRecipe> | TaskHandoff<FinalizeProposalSuccess<TRecipe>>;
64
+ project: (success: FinalizeProposalSuccess<TRecipe>) => Promise<GetProductsResponse>;
65
+ } | {
66
+ kind: 'pass';
67
+ };
68
+ /**
69
+ * Intercept `buying_mode: 'refine'` requests carrying a
70
+ * `refine[i].action: 'finalize'` entry. Hydrates the draft, calls the
71
+ * manager's `finalizeProposal`, and returns the raw adopter result + a
72
+ * projection callback. The runtime threads them through the framework's
73
+ * standard `routeIfHandoff` so:
74
+ *
75
+ * - Sync `FinalizeProposalSuccess` returns: projection runs inline,
76
+ * buyer sees the committed proposal in the response.
77
+ * - HITL `TaskHandoff<FinalizeProposalSuccess>` returns: framework
78
+ * returns the Submitted envelope to the buyer, runs the adopter's
79
+ * handoff fn in background; projection runs when the handoff
80
+ * resolves, commits the proposal, projects the terminal task
81
+ * artifact.
82
+ *
83
+ * Same machinery as `createMediaBuy` HITL — finalize inherits whatever
84
+ * cancellation, restart-via-durable-store, deadline, and webhook
85
+ * delivery semantics the framework's task lifecycle provides for every
86
+ * other unified-hybrid tool. No special-case wrapper.
87
+ *
88
+ * @public
89
+ */
90
+ export declare function maybeInterceptFinalize<TRecipe extends Recipe, TCtxMeta>(args: {
91
+ request: GetProductsRequest;
92
+ manager: ProposalManager<TRecipe, TCtxMeta> | undefined;
93
+ store: ProposalStore<TRecipe> | undefined;
94
+ ctx: {
95
+ account: {
96
+ id: string;
97
+ };
98
+ } & Record<string, unknown>;
99
+ }): Promise<FinalizeInterceptResult<TRecipe>>;
100
+ /**
101
+ * Persist proposals returned by `getProducts` / `refineProducts` as
102
+ * drafts in the wired {@link ProposalStore}. Validates `overlap ⊆ wire`
103
+ * for any returned recipes before persisting.
104
+ *
105
+ * Quietly returns when no store is wired, no `proposals[]` in the
106
+ * response, or no typed recipes attached to products.
107
+ *
108
+ * @public
109
+ */
110
+ export declare function maybePersistDraftAfterGetProducts<TRecipe extends Recipe>(args: {
111
+ response: GetProductsResponse;
112
+ store: ProposalStore<TRecipe> | undefined;
113
+ ctx: {
114
+ account: {
115
+ id: string;
116
+ };
117
+ };
118
+ }): Promise<void>;
119
+ /**
120
+ * Result of {@link maybeReserveProposalForCreateMediaBuy}.
121
+ *
122
+ * - `record` — the reserved {@link ProposalRecord}. Caller threads
123
+ * `recipes` onto `ctx.recipes` and calls
124
+ * {@link finalizeProposalConsumption} on adapter success or
125
+ * {@link releaseProposalReservation} on failure.
126
+ * - `null` — request has no `proposal_id`, no store wired, or the
127
+ * framework didn't intercept (v1 path).
128
+ *
129
+ * @public
130
+ */
131
+ export type ReservedProposal<TRecipe extends Recipe> = ProposalRecord<TRecipe>;
132
+ /**
133
+ * Reserve the proposal for consumption and hydrate `ctx.recipes`.
134
+ *
135
+ * Atomic CAS via {@link ProposalStore.tryReserveConsumption} — the
136
+ * proposal transitions `COMMITTED → CONSUMING` before the adapter runs.
137
+ * Two parallel `createMediaBuy(proposal_id=X)` calls cannot both
138
+ * reserve; the loser raises `PROPOSAL_NOT_COMMITTED`.
139
+ *
140
+ * Validates per § D7 (expiry) BEFORE reserving — an expired proposal
141
+ * surfaces `PROPOSAL_EXPIRED` without flipping the state.
142
+ *
143
+ * @public
144
+ */
145
+ export declare function maybeReserveProposalForCreateMediaBuy<TRecipe extends Recipe, TCtxMeta>(args: {
146
+ request: {
147
+ proposal_id?: string;
148
+ packages?: ReadonlyArray<unknown>;
149
+ } & Record<string, unknown>;
150
+ manager: ProposalManager<TRecipe, TCtxMeta> | undefined;
151
+ store: ProposalStore<TRecipe> | undefined;
152
+ ctx: {
153
+ account: {
154
+ id: string;
155
+ };
156
+ };
157
+ now?: Date;
158
+ }): Promise<ReservedProposal<TRecipe> | null>;
159
+ /**
160
+ * Promote `CONSUMING → CONSUMED` after the adapter's `createMediaBuy`
161
+ * succeeded.
162
+ *
163
+ * @public
164
+ */
165
+ export declare function finalizeProposalConsumption<TRecipe extends Recipe>(args: {
166
+ store: ProposalStore<TRecipe> | undefined;
167
+ record: ReservedProposal<TRecipe>;
168
+ mediaBuyId: string;
169
+ }): Promise<void>;
170
+ /**
171
+ * Roll back the reservation: `CONSUMING → COMMITTED`. Best-effort.
172
+ *
173
+ * @public
174
+ */
175
+ export declare function releaseProposalReservation<TRecipe extends Recipe>(args: {
176
+ store: ProposalStore<TRecipe> | undefined;
177
+ record: ReservedProposal<TRecipe>;
178
+ logger?: {
179
+ warn(message: string): void;
180
+ };
181
+ }): Promise<void>;
182
+ /**
183
+ * Hydrate `ctx.recipes` for post-acceptance buy operations via the
184
+ * `getByMediaBuyId` reverse-index. Returns the record (so the caller
185
+ * can re-validate overlap if a packages-shaped patch is provided);
186
+ * returns `null` when no proposal backs this buy.
187
+ *
188
+ * Per Resolutions §5: re-validates capability overlap on every call
189
+ * with packages.
190
+ *
191
+ * @public
192
+ */
193
+ export declare function maybeHydrateRecipesForMediaBuyId<TRecipe extends Recipe>(args: {
194
+ mediaBuyId: string | undefined;
195
+ store: ProposalStore<TRecipe> | undefined;
196
+ ctx: {
197
+ account: {
198
+ id: string;
199
+ };
200
+ };
201
+ packages?: ReadonlyArray<unknown>;
202
+ }): Promise<ProposalRecord<TRecipe> | null>;
203
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,395 @@
1
+ "use strict";
2
+ /**
3
+ * Proposal-dispatch — the v1.5 framework intercept seams.
4
+ *
5
+ * Pure functions that the runtime calls from the wire-handler shims
6
+ * (`getProducts`, `createMediaBuy`, `updateMediaBuy`,
7
+ * `getMediaBuyDelivery`). Each helper short-circuits when no manager /
8
+ * store is wired for the request, so the v1 path is preserved
9
+ * byte-for-byte.
10
+ *
11
+ * Five integration points (parity with `adcp-client-python.src/adcp/decisioning/proposal_dispatch.py`):
12
+ *
13
+ * - {@link maybeInterceptFinalize} — `getProducts` shim. Detects
14
+ * `refine[i].action: 'finalize'`, calls the manager's
15
+ * `finalizeProposal`, commits the proposal, returns the wire
16
+ * response. Returns `null` when no finalize entry / no
17
+ * finalize-capable manager.
18
+ * - {@link maybePersistDraftAfterGetProducts} — `getProducts` shim
19
+ * (post-call). Walks the response's `proposals[]`, validates
20
+ * `overlap ⊆ wire`, persists each as a draft.
21
+ * - {@link maybeReserveProposalForCreateMediaBuy} — `createMediaBuy`
22
+ * shim. When `proposal_id` is set, validates expiry + capability
23
+ * overlap, reserves the proposal (`COMMITTED → CONSUMING`), returns
24
+ * the recipes map for `ctx.recipes` hydration.
25
+ * - {@link finalizeProposalConsumption} — `createMediaBuy` shim
26
+ * (post-success). Promotes `CONSUMING → CONSUMED` and records the
27
+ * `mediaBuyId` back-reference.
28
+ * - {@link releaseProposalReservation} — `createMediaBuy` shim
29
+ * (failure rollback). Restores `CONSUMING → COMMITTED`.
30
+ * - {@link maybeHydrateRecipesForMediaBuyId} —
31
+ * `updateMediaBuy` / `getMediaBuyDelivery` shims. Reverse-index
32
+ * hydration via `getByMediaBuyId`. Re-runs capability-overlap
33
+ * validation per Resolutions §5.
34
+ *
35
+ * @public
36
+ * @packageDocumentation
37
+ */
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.maybeInterceptFinalize = maybeInterceptFinalize;
40
+ exports.maybePersistDraftAfterGetProducts = maybePersistDraftAfterGetProducts;
41
+ exports.maybeReserveProposalForCreateMediaBuy = maybeReserveProposalForCreateMediaBuy;
42
+ exports.finalizeProposalConsumption = finalizeProposalConsumption;
43
+ exports.releaseProposalReservation = releaseProposalReservation;
44
+ exports.maybeHydrateRecipesForMediaBuyId = maybeHydrateRecipesForMediaBuyId;
45
+ const async_outcome_1 = require("../async-outcome");
46
+ const lifecycle_1 = require("./lifecycle");
47
+ // ---------------------------------------------------------------------------
48
+ // Capability detection
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Per Resolutions §7: framework detects finalize via method-presence +
52
+ * `capabilities.finalize` flag. Adopters opt in by both implementing
53
+ * AND declaring; flipping only one half is an adopter bug.
54
+ */
55
+ function hasFinalizeCapability(manager) {
56
+ if (!manager)
57
+ return false;
58
+ if (!manager.capabilities.finalize)
59
+ return false;
60
+ return typeof manager.finalizeProposal === 'function';
61
+ }
62
+ /**
63
+ * Intercept `buying_mode: 'refine'` requests carrying a
64
+ * `refine[i].action: 'finalize'` entry. Hydrates the draft, calls the
65
+ * manager's `finalizeProposal`, and returns the raw adopter result + a
66
+ * projection callback. The runtime threads them through the framework's
67
+ * standard `routeIfHandoff` so:
68
+ *
69
+ * - Sync `FinalizeProposalSuccess` returns: projection runs inline,
70
+ * buyer sees the committed proposal in the response.
71
+ * - HITL `TaskHandoff<FinalizeProposalSuccess>` returns: framework
72
+ * returns the Submitted envelope to the buyer, runs the adopter's
73
+ * handoff fn in background; projection runs when the handoff
74
+ * resolves, commits the proposal, projects the terminal task
75
+ * artifact.
76
+ *
77
+ * Same machinery as `createMediaBuy` HITL — finalize inherits whatever
78
+ * cancellation, restart-via-durable-store, deadline, and webhook
79
+ * delivery semantics the framework's task lifecycle provides for every
80
+ * other unified-hybrid tool. No special-case wrapper.
81
+ *
82
+ * @public
83
+ */
84
+ async function maybeInterceptFinalize(args) {
85
+ const { request, manager, store, ctx } = args;
86
+ const finalizeEntry = (0, lifecycle_1.detectFinalizeAction)(request);
87
+ if (!finalizeEntry)
88
+ return { kind: 'pass' };
89
+ if (!hasFinalizeCapability(manager) || !store)
90
+ return { kind: 'pass' };
91
+ const fieldPath = `refine[${finalizeEntry.index}].proposal_id`;
92
+ const accountId = ctx.account.id;
93
+ const record = await store.get(finalizeEntry.proposalId, { expectedAccountId: accountId });
94
+ if (!record) {
95
+ throw new async_outcome_1.AdcpError('PROPOSAL_NOT_FOUND', {
96
+ recovery: 'terminal',
97
+ message: `Proposal ${JSON.stringify(finalizeEntry.proposalId)} not found. The buyer must call ` +
98
+ `get_products with buying_mode='brief' or 'refine' to obtain a draft proposal_id ` +
99
+ `before finalizing it.`,
100
+ field: fieldPath,
101
+ });
102
+ }
103
+ if (record.state !== 'draft') {
104
+ throw new async_outcome_1.AdcpError('PROPOSAL_NOT_COMMITTED', {
105
+ recovery: 'correctable',
106
+ message: `Proposal ${JSON.stringify(finalizeEntry.proposalId)} is in state ` +
107
+ `${JSON.stringify(record.state)}; only draft proposals can be finalized. ` +
108
+ `Already-committed proposals should be accepted via create_media_buy(proposal_id=...) ` +
109
+ `directly.`,
110
+ field: fieldPath,
111
+ });
112
+ }
113
+ const finalizeReq = {
114
+ proposalId: finalizeEntry.proposalId,
115
+ recipes: record.recipes,
116
+ proposalPayload: record.proposalPayload,
117
+ parentRequest: request,
118
+ ...(finalizeEntry.ask !== undefined && { ask: finalizeEntry.ask }),
119
+ };
120
+ // manager + finalizeProposal are non-undefined per hasFinalizeCapability.
121
+ const result = await manager.finalizeProposal(finalizeReq, ctx);
122
+ // Pre-determine the path label by checking whether the adopter
123
+ // returned a TaskHandoff up-front. `routeIfHandoff` runs `project`
124
+ // synchronously for the sync arm and inside the background task for
125
+ // the handoff arm; either way, we want the log to reflect which arm
126
+ // the adopter chose.
127
+ const path = (0, async_outcome_1.isTaskHandoff)(result) ? 'handoff' : 'inline';
128
+ const finalizeProposalId = finalizeEntry.proposalId;
129
+ const project = async (success) => {
130
+ if (!isFinalizeSuccess(success)) {
131
+ throw new async_outcome_1.AdcpError('INTERNAL_ERROR', {
132
+ recovery: 'terminal',
133
+ message: `finalizeProposal resolved to an unexpected shape; expected FinalizeProposalSuccess ` +
134
+ `with 'proposal' and 'expiresAt' fields.`,
135
+ });
136
+ }
137
+ await store.commit(finalizeProposalId, {
138
+ expiresAt: success.expiresAt,
139
+ proposalPayload: success.proposal,
140
+ });
141
+ (0, lifecycle_1.logFinalizeSucceeded)({
142
+ proposalId: finalizeProposalId,
143
+ accountId,
144
+ expiresAt: success.expiresAt,
145
+ path,
146
+ });
147
+ return projectFinalizeResponse({
148
+ request,
149
+ committedProposal: success.proposal,
150
+ finalizeProposalId,
151
+ });
152
+ };
153
+ return { kind: 'intercepted', result, project };
154
+ }
155
+ function isFinalizeSuccess(v) {
156
+ if (!v || typeof v !== 'object')
157
+ return false;
158
+ const r = v;
159
+ return r.proposal != null && r.expiresAt instanceof Date;
160
+ }
161
+ function projectFinalizeResponse(args) {
162
+ const refineEntries = args.request.refine;
163
+ const refinementApplied = [];
164
+ if (refineEntries) {
165
+ for (const entry of refineEntries) {
166
+ const scope = entry.scope;
167
+ if (scope === 'proposal') {
168
+ refinementApplied.push({
169
+ scope: 'proposal',
170
+ proposal_id: typeof entry.proposal_id === 'string' ? entry.proposal_id : args.finalizeProposalId,
171
+ status: 'applied',
172
+ });
173
+ }
174
+ else if (scope === 'product') {
175
+ refinementApplied.push({
176
+ scope: 'product',
177
+ product_id: typeof entry.product_id === 'string' ? entry.product_id : '',
178
+ status: 'applied',
179
+ });
180
+ }
181
+ else {
182
+ refinementApplied.push({ scope: 'request', status: 'applied' });
183
+ }
184
+ }
185
+ }
186
+ // **Decision: `products: []` on the finalize response by design.** The
187
+ // committed proposal carries `allocations[]` keyed by `product_id`;
188
+ // the buyer either has the products from the prior `brief_with_proposals`
189
+ // step (the natural flow) or fetches by id. Echoing the products here
190
+ // would require the framework to either re-emit from the persisted
191
+ // draft (extra wire bytes the buyer already has) or call back into the
192
+ // adopter (extra round-trip to upstream). Buyers who explicitly want
193
+ // products on the finalize response can fetch them via a follow-up
194
+ // `get_products({ product_ids: [...] })` keyed off
195
+ // `proposals[0].allocations[].product_id`.
196
+ return {
197
+ products: [],
198
+ proposals: [args.committedProposal],
199
+ refinement_applied: refinementApplied,
200
+ };
201
+ }
202
+ // ---------------------------------------------------------------------------
203
+ // getProducts / refineProducts — post-call draft persistence
204
+ // ---------------------------------------------------------------------------
205
+ /**
206
+ * Persist proposals returned by `getProducts` / `refineProducts` as
207
+ * drafts in the wired {@link ProposalStore}. Validates `overlap ⊆ wire`
208
+ * for any returned recipes before persisting.
209
+ *
210
+ * Quietly returns when no store is wired, no `proposals[]` in the
211
+ * response, or no typed recipes attached to products.
212
+ *
213
+ * @public
214
+ */
215
+ async function maybePersistDraftAfterGetProducts(args) {
216
+ const { response, store, ctx } = args;
217
+ if (!store)
218
+ return;
219
+ const proposals = response.proposals;
220
+ if (!proposals || proposals.length === 0)
221
+ return;
222
+ const products = response.products ?? [];
223
+ for (const proposal of proposals) {
224
+ const proposalId = proposal.proposal_id;
225
+ if (!proposalId)
226
+ continue;
227
+ const proposalPayload = toPlainObject(proposal);
228
+ const recipes = collectRecipesFromProducts(products, proposalPayload);
229
+ if (recipes.size > 0) {
230
+ (0, lifecycle_1.validateOverlapSubsetOfWire)({ recipes, products });
231
+ }
232
+ await store.putDraft({
233
+ proposalId,
234
+ accountId: ctx.account.id,
235
+ recipes,
236
+ proposalPayload,
237
+ });
238
+ (0, lifecycle_1.logDraftPersisted)({
239
+ proposalId,
240
+ accountId: ctx.account.id,
241
+ recipesCount: recipes.size,
242
+ });
243
+ }
244
+ }
245
+ function collectRecipesFromProducts(products, proposalPayload) {
246
+ // Filter to products referenced by the proposal's allocations[] (per
247
+ // spec) or legacy products[] string array when present.
248
+ let referenced = null;
249
+ const allocations = proposalPayload.allocations;
250
+ if (Array.isArray(allocations)) {
251
+ referenced = new Set(allocations
252
+ .map((a) => a.product_id)
253
+ .filter((id) => typeof id === 'string'));
254
+ }
255
+ else if (Array.isArray(proposalPayload.products)) {
256
+ referenced = new Set(proposalPayload.products.filter((p) => typeof p === 'string'));
257
+ }
258
+ const recipes = new Map();
259
+ for (const product of products) {
260
+ const productId = product.product_id;
261
+ if (!productId)
262
+ continue;
263
+ if (referenced && !referenced.has(productId))
264
+ continue;
265
+ const implConfig = product.implementation_config;
266
+ if (isRecipe(implConfig)) {
267
+ recipes.set(productId, implConfig);
268
+ }
269
+ }
270
+ return recipes;
271
+ }
272
+ function isRecipe(v) {
273
+ return v != null && typeof v === 'object' && typeof v.recipe_kind === 'string';
274
+ }
275
+ function toPlainObject(v) {
276
+ if (v == null || typeof v !== 'object')
277
+ return {};
278
+ // Deep clone via JSON to drop class-instance prototypes — the stored
279
+ // payload must round-trip through a durable backing.
280
+ return JSON.parse(JSON.stringify(v));
281
+ }
282
+ /**
283
+ * Reserve the proposal for consumption and hydrate `ctx.recipes`.
284
+ *
285
+ * Atomic CAS via {@link ProposalStore.tryReserveConsumption} — the
286
+ * proposal transitions `COMMITTED → CONSUMING` before the adapter runs.
287
+ * Two parallel `createMediaBuy(proposal_id=X)` calls cannot both
288
+ * reserve; the loser raises `PROPOSAL_NOT_COMMITTED`.
289
+ *
290
+ * Validates per § D7 (expiry) BEFORE reserving — an expired proposal
291
+ * surfaces `PROPOSAL_EXPIRED` without flipping the state.
292
+ *
293
+ * @public
294
+ */
295
+ async function maybeReserveProposalForCreateMediaBuy(args) {
296
+ const { request, manager, store, ctx, now } = args;
297
+ const proposalId = request.proposal_id;
298
+ if (!proposalId || !store)
299
+ return null;
300
+ const graceSeconds = manager?.capabilities.expiresAtGraceSeconds ?? 0;
301
+ // Expiry check BEFORE reserving — keep the buyer's slot uncommitted
302
+ // when telling them they're expired.
303
+ await (0, lifecycle_1.enforceProposalExpiry)(proposalId, {
304
+ proposalStore: store,
305
+ expectedAccountId: ctx.account.id,
306
+ graceSeconds,
307
+ ...(now && { now }),
308
+ });
309
+ const reserved = await store.tryReserveConsumption(proposalId, {
310
+ expectedAccountId: ctx.account.id,
311
+ });
312
+ // Capability-overlap gate per D4. Buyer's packages may be empty when
313
+ // proposal_id is set (the spec allows the seller to derive packages
314
+ // from allocations); skip the gate in that case.
315
+ const packages = request.packages;
316
+ if (packages && Array.isArray(packages) && packages.length > 0) {
317
+ (0, lifecycle_1.validateCapabilityOverlap)({
318
+ packages: packages,
319
+ recipes: reserved.recipes,
320
+ });
321
+ }
322
+ return reserved;
323
+ }
324
+ /**
325
+ * Promote `CONSUMING → CONSUMED` after the adapter's `createMediaBuy`
326
+ * succeeded.
327
+ *
328
+ * @public
329
+ */
330
+ async function finalizeProposalConsumption(args) {
331
+ const { store, record, mediaBuyId } = args;
332
+ if (!store)
333
+ return;
334
+ await store.finalizeConsumption(record.proposalId, {
335
+ mediaBuyId,
336
+ expectedAccountId: record.accountId,
337
+ });
338
+ (0, lifecycle_1.logConsumed)({
339
+ proposalId: record.proposalId,
340
+ accountId: record.accountId,
341
+ mediaBuyId,
342
+ });
343
+ }
344
+ /**
345
+ * Roll back the reservation: `CONSUMING → COMMITTED`. Best-effort.
346
+ *
347
+ * @public
348
+ */
349
+ async function releaseProposalReservation(args) {
350
+ const { store, record, logger } = args;
351
+ if (!store)
352
+ return;
353
+ try {
354
+ await store.releaseConsumption(record.proposalId, {
355
+ expectedAccountId: record.accountId,
356
+ });
357
+ }
358
+ catch (err) {
359
+ const message = err instanceof Error ? err.message : String(err);
360
+ logger?.warn(`[adcp/decisioning] failed to release consumption reservation for proposal ` +
361
+ `${record.proposalId}: ${message}. The record may stay in CONSUMING until eviction.`);
362
+ }
363
+ }
364
+ // ---------------------------------------------------------------------------
365
+ // updateMediaBuy / getMediaBuyDelivery — reverse-index recipe hydration
366
+ // ---------------------------------------------------------------------------
367
+ /**
368
+ * Hydrate `ctx.recipes` for post-acceptance buy operations via the
369
+ * `getByMediaBuyId` reverse-index. Returns the record (so the caller
370
+ * can re-validate overlap if a packages-shaped patch is provided);
371
+ * returns `null` when no proposal backs this buy.
372
+ *
373
+ * Per Resolutions §5: re-validates capability overlap on every call
374
+ * with packages.
375
+ *
376
+ * @public
377
+ */
378
+ async function maybeHydrateRecipesForMediaBuyId(args) {
379
+ const { mediaBuyId, store, ctx, packages } = args;
380
+ if (!mediaBuyId || !store)
381
+ return null;
382
+ const record = await store.getByMediaBuyId(mediaBuyId, {
383
+ expectedAccountId: ctx.account.id,
384
+ });
385
+ if (!record)
386
+ return null;
387
+ if (packages && Array.isArray(packages) && packages.length > 0) {
388
+ (0, lifecycle_1.validateCapabilityOverlap)({
389
+ packages: packages,
390
+ recipes: record.recipes,
391
+ });
392
+ }
393
+ return record;
394
+ }
395
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ProposalManager — primitives for the two-platform composition.
3
+ *
4
+ * Splits proposal assembly (`get_products`, refine, finalize) from media-buy
5
+ * execution (`create_media_buy`, lifecycle), mirroring `adcp-client-python`'s
6
+ * v1.5 ProposalManager. Either side can be mock-backed independently.
7
+ *
8
+ * @public
9
+ * @packageDocumentation
10
+ */
11
+ export type { ProposalManager, ProposalCapabilities, ProposalSalesSpecialism, Recipe, CapabilityOverlap, FinalizeProposalRequest, FinalizeProposalSuccess, } from './types';
12
+ export { validateProposalCapabilities } from './types';
13
+ export type { ProposalState, ProposalRecord, ProposalStore, InMemoryProposalStoreOptions } from './store';
14
+ export { InMemoryProposalStore } from './store';
15
+ export { MockProposalManager } from './mock-manager';
16
+ export type { MockProposalManagerOptions } from './mock-manager';
17
+ export { enforceProposalExpiry, validateCapabilityOverlap, validateOverlapSubsetOfWire, detectFinalizeAction, setProposalLifecycleLogger, logDraftPersisted, logFinalizeSucceeded, logExpired, logConsumed, } from './lifecycle';
18
+ export type { FinalizeActionRef, ProposalLifecycleLogger } from './lifecycle';
19
+ export { maybeInterceptFinalize, maybePersistDraftAfterGetProducts, maybeReserveProposalForCreateMediaBuy, finalizeProposalConsumption, releaseProposalReservation, maybeHydrateRecipesForMediaBuyId, } from './dispatch';
20
+ export type { FinalizeInterceptResult, ReservedProposal } from './dispatch';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,uBAAuB,EACvB,MAAM,EACN,iBAAiB,EACjB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAE1G,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,YAAY,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,oBAAoB,EACpB,0BAA0B,EAC1B,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EACL,sBAAsB,EACtB,iCAAiC,EACjC,qCAAqC,EACrC,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}