@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,37 @@
1
+ "use strict";
2
+ /**
3
+ * ProposalManager — primitives for the two-platform composition.
4
+ *
5
+ * Splits proposal assembly (`get_products`, refine, finalize) from media-buy
6
+ * execution (`create_media_buy`, lifecycle), mirroring `adcp-client-python`'s
7
+ * v1.5 ProposalManager. Either side can be mock-backed independently.
8
+ *
9
+ * @public
10
+ * @packageDocumentation
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.maybeHydrateRecipesForMediaBuyId = exports.releaseProposalReservation = exports.finalizeProposalConsumption = exports.maybeReserveProposalForCreateMediaBuy = exports.maybePersistDraftAfterGetProducts = exports.maybeInterceptFinalize = exports.logConsumed = exports.logExpired = exports.logFinalizeSucceeded = exports.logDraftPersisted = exports.setProposalLifecycleLogger = exports.detectFinalizeAction = exports.validateOverlapSubsetOfWire = exports.validateCapabilityOverlap = exports.enforceProposalExpiry = exports.MockProposalManager = exports.InMemoryProposalStore = exports.validateProposalCapabilities = void 0;
14
+ var types_1 = require("./types");
15
+ Object.defineProperty(exports, "validateProposalCapabilities", { enumerable: true, get: function () { return types_1.validateProposalCapabilities; } });
16
+ var store_1 = require("./store");
17
+ Object.defineProperty(exports, "InMemoryProposalStore", { enumerable: true, get: function () { return store_1.InMemoryProposalStore; } });
18
+ var mock_manager_1 = require("./mock-manager");
19
+ Object.defineProperty(exports, "MockProposalManager", { enumerable: true, get: function () { return mock_manager_1.MockProposalManager; } });
20
+ var lifecycle_1 = require("./lifecycle");
21
+ Object.defineProperty(exports, "enforceProposalExpiry", { enumerable: true, get: function () { return lifecycle_1.enforceProposalExpiry; } });
22
+ Object.defineProperty(exports, "validateCapabilityOverlap", { enumerable: true, get: function () { return lifecycle_1.validateCapabilityOverlap; } });
23
+ Object.defineProperty(exports, "validateOverlapSubsetOfWire", { enumerable: true, get: function () { return lifecycle_1.validateOverlapSubsetOfWire; } });
24
+ Object.defineProperty(exports, "detectFinalizeAction", { enumerable: true, get: function () { return lifecycle_1.detectFinalizeAction; } });
25
+ Object.defineProperty(exports, "setProposalLifecycleLogger", { enumerable: true, get: function () { return lifecycle_1.setProposalLifecycleLogger; } });
26
+ Object.defineProperty(exports, "logDraftPersisted", { enumerable: true, get: function () { return lifecycle_1.logDraftPersisted; } });
27
+ Object.defineProperty(exports, "logFinalizeSucceeded", { enumerable: true, get: function () { return lifecycle_1.logFinalizeSucceeded; } });
28
+ Object.defineProperty(exports, "logExpired", { enumerable: true, get: function () { return lifecycle_1.logExpired; } });
29
+ Object.defineProperty(exports, "logConsumed", { enumerable: true, get: function () { return lifecycle_1.logConsumed; } });
30
+ var dispatch_1 = require("./dispatch");
31
+ Object.defineProperty(exports, "maybeInterceptFinalize", { enumerable: true, get: function () { return dispatch_1.maybeInterceptFinalize; } });
32
+ Object.defineProperty(exports, "maybePersistDraftAfterGetProducts", { enumerable: true, get: function () { return dispatch_1.maybePersistDraftAfterGetProducts; } });
33
+ Object.defineProperty(exports, "maybeReserveProposalForCreateMediaBuy", { enumerable: true, get: function () { return dispatch_1.maybeReserveProposalForCreateMediaBuy; } });
34
+ Object.defineProperty(exports, "finalizeProposalConsumption", { enumerable: true, get: function () { return dispatch_1.finalizeProposalConsumption; } });
35
+ Object.defineProperty(exports, "releaseProposalReservation", { enumerable: true, get: function () { return dispatch_1.releaseProposalReservation; } });
36
+ Object.defineProperty(exports, "maybeHydrateRecipesForMediaBuyId", { enumerable: true, get: function () { return dispatch_1.maybeHydrateRecipesForMediaBuyId; } });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAYH,iCAAuD;AAA9C,qHAAA,4BAA4B,OAAA;AAIrC,iCAAgD;AAAvC,8GAAA,qBAAqB,OAAA;AAE9B,+CAAqD;AAA5C,mHAAA,mBAAmB,OAAA;AAG5B,yCAUqB;AATnB,kHAAA,qBAAqB,OAAA;AACrB,sHAAA,yBAAyB,OAAA;AACzB,wHAAA,2BAA2B,OAAA;AAC3B,iHAAA,oBAAoB,OAAA;AACpB,uHAAA,0BAA0B,OAAA;AAC1B,8GAAA,iBAAiB,OAAA;AACjB,iHAAA,oBAAoB,OAAA;AACpB,uGAAA,UAAU,OAAA;AACV,wGAAA,WAAW,OAAA;AAIb,uCAOoB;AANlB,kHAAA,sBAAsB,OAAA;AACtB,6HAAA,iCAAiC,OAAA;AACjC,iIAAA,qCAAqC,OAAA;AACrC,uHAAA,2BAA2B,OAAA;AAC3B,sHAAA,0BAA0B,OAAA;AAC1B,4HAAA,gCAAgC,OAAA"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Proposal-lifecycle framework helpers — the v1.5 intercept seam.
3
+ *
4
+ * Sits parallel to existing dispatch helpers in `runtime/from-platform.ts`.
5
+ * Framework intercepts at a seam, does its work, dispatches.
6
+ *
7
+ * Public surface (the dispatch path imports these):
8
+ *
9
+ * - {@link enforceProposalExpiry} — D7. Look up the committed proposal,
10
+ * validate `state === 'committed'` and `now <= expires_at + grace`,
11
+ * return the record.
12
+ * - {@link validateCapabilityOverlap} — D4. Walk a buyer's
13
+ * `create_media_buy` / `update_media_buy` request packages against
14
+ * each recipe's `capability_overlap` and reject mismatches with
15
+ * `INVALID_REQUEST`.
16
+ * - {@link validateOverlapSubsetOfWire} — D4 round-4. Validate at
17
+ * `putDraft` time that each recipe's `capability_overlap` axis is a
18
+ * subset of the corresponding wire-declared product capabilities.
19
+ * Mismatches throw `INTERNAL_ERROR` (adopter bug, not buyer bug).
20
+ * - {@link detectFinalizeAction} — pull out the first finalize-action
21
+ * refine entry from a `GetProductsRequest`.
22
+ * - structured-log helpers per § Observability.
23
+ *
24
+ * Ports `adcp-client-python.src/adcp/decisioning/proposal_lifecycle.py`.
25
+ *
26
+ * @public
27
+ * @packageDocumentation
28
+ */
29
+ import type { GetProductsRequest, Product } from '../../../types/tools.generated';
30
+ import type { ProposalRecord, ProposalStore } from './store';
31
+ import type { Recipe } from './types';
32
+ /**
33
+ * Validate a proposal is committed and within its hold window.
34
+ *
35
+ * Three failure modes mapped to spec error codes:
36
+ *
37
+ * - Record not found OR cross-tenant → `PROPOSAL_NOT_FOUND` (terminal).
38
+ * Cross-tenant probes return the same error as missing IDs (no
39
+ * principal-enumeration via id probing).
40
+ * - State !== `'committed'` → `PROPOSAL_NOT_COMMITTED` (correctable).
41
+ * The buyer needs to call `getProducts({ buying_mode: 'refine',
42
+ * refine: [{ action: 'finalize' }] })` first.
43
+ * - Committed but `now > expires_at + grace` → `PROPOSAL_EXPIRED`
44
+ * (correctable per AdCP 3.0.6 — the buyer re-discovers via
45
+ * `get_products` to obtain a fresh proposal).
46
+ *
47
+ * @public
48
+ */
49
+ export declare function enforceProposalExpiry<TRecipe extends Recipe>(proposalId: string, args: {
50
+ proposalStore: ProposalStore<TRecipe>;
51
+ expectedAccountId: string;
52
+ graceSeconds?: number;
53
+ now?: Date;
54
+ }): Promise<ProposalRecord<TRecipe>>;
55
+ interface PackageLike {
56
+ product_id?: string;
57
+ pricing_option_id?: string;
58
+ pricing_model?: string;
59
+ delivery_type?: string;
60
+ signal_type?: string;
61
+ targeting_overlay?: Record<string, unknown>;
62
+ /**
63
+ * Adopter-resolved pricing model — the validation reads this when
64
+ * present. Set by the framework when it has resolved
65
+ * `pricing_option_id` against the product's pricing options.
66
+ */
67
+ _resolved_pricing_model?: string;
68
+ _resolved_delivery_type?: string;
69
+ [k: string]: unknown;
70
+ }
71
+ /**
72
+ * Pre-adapter validation seam: walk buyer's packages against each recipe's
73
+ * `capability_overlap` and reject mismatches.
74
+ *
75
+ * Called from the framework's `create_media_buy` and `update_media_buy`
76
+ * dispatch paths after recipes are hydrated from the {@link ProposalStore}.
77
+ * Per D4, the framework owns this gate so every adopter doesn't write the
78
+ * same intersection logic.
79
+ *
80
+ * Validation axes (per {@link CapabilityOverlap}):
81
+ *
82
+ * - `pricingModels` — checked against `package._resolved_pricing_model`
83
+ * or `package.pricing_model`.
84
+ * - `targetingDimensions` — checked against `package.targeting_overlay` keys.
85
+ * - `deliveryTypes` — checked against `package._resolved_delivery_type`
86
+ * or `package.delivery_type`.
87
+ * - `signalTypes` — checked against `package.signal_type`.
88
+ *
89
+ * Per the design's undefined-vs-empty-set semantics: `undefined` skips the
90
+ * gate; an explicit `Set` (including the empty set) is enforced.
91
+ *
92
+ * @public
93
+ */
94
+ export declare function validateCapabilityOverlap<TRecipe extends Recipe>(args: {
95
+ packages: readonly PackageLike[];
96
+ recipes: ReadonlyMap<string, TRecipe>;
97
+ fieldPathPrefix?: string;
98
+ }): void;
99
+ /**
100
+ * Validate `recipe.capability_overlap` is a subset of the matching product's
101
+ * wire-declared capabilities.
102
+ *
103
+ * Called at `putDraft` time. Mismatches throw `INTERNAL_ERROR` — this is
104
+ * an adopter bug (the manager declared an overlap claiming capabilities the
105
+ * wire shape doesn't advertise), not a buyer bug.
106
+ *
107
+ * @public
108
+ */
109
+ export declare function validateOverlapSubsetOfWire<TRecipe extends Recipe>(args: {
110
+ recipes: ReadonlyMap<string, TRecipe>;
111
+ products: readonly Product[];
112
+ }): void;
113
+ /**
114
+ * Result of {@link detectFinalizeAction}: the index, proposal_id, and
115
+ * optional ask of the first finalize-action refine entry.
116
+ *
117
+ * @public
118
+ */
119
+ export interface FinalizeActionRef {
120
+ index: number;
121
+ proposalId: string;
122
+ ask?: string;
123
+ }
124
+ /**
125
+ * Return the first finalize-action refine entry from a
126
+ * `GetProductsRequest`, or `null` if no finalize entry exists.
127
+ *
128
+ * The index points at the entry's position in `refine[]` so the framework
129
+ * can produce indexed wire field paths (`refine[3].proposal_id`) on
130
+ * rejection — buyers parsing the error get a precise pointer.
131
+ *
132
+ * Per the spec, `buying_mode: 'refine'` carries a `refine[]` array of
133
+ * entries. Each entry has a `scope` (`request` / `product` / `proposal`)
134
+ * and an optional `action` (`include` / `omit` / `finalize`). v1.5 only
135
+ * intercepts `proposal`-scoped entries with `action: 'finalize'`.
136
+ *
137
+ * The framework processes ONE finalize entry per request; if the buyer
138
+ * sends multiple finalize entries, only the first is processed (rest fall
139
+ * through to the standard refine path).
140
+ *
141
+ * @public
142
+ */
143
+ export declare function detectFinalizeAction(req: GetProductsRequest): FinalizeActionRef | null;
144
+ /**
145
+ * Logger-shaped sink for structured proposal-lifecycle events. Defaults to
146
+ * `console.info`-style emission; the dispatch path can pass a typed logger
147
+ * to route through the rest of the framework's logging.
148
+ *
149
+ * @public
150
+ */
151
+ export interface ProposalLifecycleLogger {
152
+ info(message: string, fields?: Record<string, unknown>): void;
153
+ }
154
+ /**
155
+ * Replace the module-level logger that proposal-lifecycle structured
156
+ * events (`proposal.draft_persisted`, `proposal.finalized`, `proposal.expired`,
157
+ * `proposal.consumed`) emit through. Adopters wire this to their existing
158
+ * logger (pino, bunyan, etc.) so lifecycle events route through the same
159
+ * pipeline as the rest of their server logs. Tests use it to capture
160
+ * structured emissions for assertion.
161
+ *
162
+ * @public
163
+ */
164
+ export declare function setProposalLifecycleLogger(next: ProposalLifecycleLogger): void;
165
+ /** `proposal.draft_persisted` event. */
166
+ export declare function logDraftPersisted(args: {
167
+ proposalId: string;
168
+ accountId: string;
169
+ recipesCount: number;
170
+ }): void;
171
+ /**
172
+ * `proposal.finalized` event. `path` is `'inline'` or `'handoff'`.
173
+ */
174
+ export declare function logFinalizeSucceeded(args: {
175
+ proposalId: string;
176
+ accountId: string;
177
+ expiresAt: Date;
178
+ path: 'inline' | 'handoff';
179
+ }): void;
180
+ /** `proposal.expired` event. */
181
+ export declare function logExpired(args: {
182
+ proposalId: string;
183
+ accountId: string;
184
+ now: Date;
185
+ expiresAt: Date;
186
+ graceSeconds: number;
187
+ }): void;
188
+ /** `proposal.consumed` event. */
189
+ export declare function logConsumed(args: {
190
+ proposalId: string;
191
+ accountId: string;
192
+ mediaBuyId: string;
193
+ }): void;
194
+ export {};
195
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+ /**
3
+ * Proposal-lifecycle framework helpers — the v1.5 intercept seam.
4
+ *
5
+ * Sits parallel to existing dispatch helpers in `runtime/from-platform.ts`.
6
+ * Framework intercepts at a seam, does its work, dispatches.
7
+ *
8
+ * Public surface (the dispatch path imports these):
9
+ *
10
+ * - {@link enforceProposalExpiry} — D7. Look up the committed proposal,
11
+ * validate `state === 'committed'` and `now <= expires_at + grace`,
12
+ * return the record.
13
+ * - {@link validateCapabilityOverlap} — D4. Walk a buyer's
14
+ * `create_media_buy` / `update_media_buy` request packages against
15
+ * each recipe's `capability_overlap` and reject mismatches with
16
+ * `INVALID_REQUEST`.
17
+ * - {@link validateOverlapSubsetOfWire} — D4 round-4. Validate at
18
+ * `putDraft` time that each recipe's `capability_overlap` axis is a
19
+ * subset of the corresponding wire-declared product capabilities.
20
+ * Mismatches throw `INTERNAL_ERROR` (adopter bug, not buyer bug).
21
+ * - {@link detectFinalizeAction} — pull out the first finalize-action
22
+ * refine entry from a `GetProductsRequest`.
23
+ * - structured-log helpers per § Observability.
24
+ *
25
+ * Ports `adcp-client-python.src/adcp/decisioning/proposal_lifecycle.py`.
26
+ *
27
+ * @public
28
+ * @packageDocumentation
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.enforceProposalExpiry = enforceProposalExpiry;
32
+ exports.validateCapabilityOverlap = validateCapabilityOverlap;
33
+ exports.validateOverlapSubsetOfWire = validateOverlapSubsetOfWire;
34
+ exports.detectFinalizeAction = detectFinalizeAction;
35
+ exports.setProposalLifecycleLogger = setProposalLifecycleLogger;
36
+ exports.logDraftPersisted = logDraftPersisted;
37
+ exports.logFinalizeSucceeded = logFinalizeSucceeded;
38
+ exports.logExpired = logExpired;
39
+ exports.logConsumed = logConsumed;
40
+ const async_outcome_1 = require("../async-outcome");
41
+ // ---------------------------------------------------------------------------
42
+ // D7 — expires_at enforcement
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Validate a proposal is committed and within its hold window.
46
+ *
47
+ * Three failure modes mapped to spec error codes:
48
+ *
49
+ * - Record not found OR cross-tenant → `PROPOSAL_NOT_FOUND` (terminal).
50
+ * Cross-tenant probes return the same error as missing IDs (no
51
+ * principal-enumeration via id probing).
52
+ * - State !== `'committed'` → `PROPOSAL_NOT_COMMITTED` (correctable).
53
+ * The buyer needs to call `getProducts({ buying_mode: 'refine',
54
+ * refine: [{ action: 'finalize' }] })` first.
55
+ * - Committed but `now > expires_at + grace` → `PROPOSAL_EXPIRED`
56
+ * (correctable per AdCP 3.0.6 — the buyer re-discovers via
57
+ * `get_products` to obtain a fresh proposal).
58
+ *
59
+ * @public
60
+ */
61
+ async function enforceProposalExpiry(proposalId, args) {
62
+ const { proposalStore, expectedAccountId, graceSeconds = 0, now } = args;
63
+ const record = await proposalStore.get(proposalId, { expectedAccountId });
64
+ if (!record) {
65
+ throw new async_outcome_1.AdcpError('PROPOSAL_NOT_FOUND', {
66
+ recovery: 'terminal',
67
+ message: `Proposal ${JSON.stringify(proposalId)} not found. The buyer must call get_products ` +
68
+ `with buying_mode='refine' and refine=[{action:'finalize',...}] to obtain a ` +
69
+ `committed proposal_id before referencing it on create_media_buy.`,
70
+ field: 'proposal_id',
71
+ });
72
+ }
73
+ if (record.state !== 'committed') {
74
+ throw new async_outcome_1.AdcpError('PROPOSAL_NOT_COMMITTED', {
75
+ recovery: 'correctable',
76
+ message: `Proposal ${JSON.stringify(proposalId)} is in state ${JSON.stringify(record.state)}; ` +
77
+ `only committed proposals can be accepted via create_media_buy. Call get_products ` +
78
+ `with buying_mode='refine' and action='finalize' first.`,
79
+ field: 'proposal_id',
80
+ });
81
+ }
82
+ if (record.expiresAt) {
83
+ const current = now ?? new Date();
84
+ const deadline = record.expiresAt.getTime() + graceSeconds * 1000;
85
+ if (current.getTime() > deadline) {
86
+ logExpired({
87
+ proposalId,
88
+ accountId: record.accountId,
89
+ now: current,
90
+ expiresAt: record.expiresAt,
91
+ graceSeconds,
92
+ });
93
+ throw new async_outcome_1.AdcpError('PROPOSAL_EXPIRED', {
94
+ // Per AdCP 3.0.6 schemas/cache/3.0.6/enums/error-code.json,
95
+ // PROPOSAL_EXPIRED is `correctable` — the buyer re-discovers
96
+ // via `get_products` to obtain a fresh proposal (the hold
97
+ // window has lapsed but the buyer can re-request).
98
+ recovery: 'correctable',
99
+ message: `Proposal ${JSON.stringify(proposalId)} expired at ${record.expiresAt.toISOString()}; ` +
100
+ `create_media_buy must be called within the inventory hold window. Call get_products ` +
101
+ `with buying_mode='refine' and action='finalize' to request a fresh hold.`,
102
+ field: 'proposal_id',
103
+ });
104
+ }
105
+ }
106
+ return record;
107
+ }
108
+ /**
109
+ * Pre-adapter validation seam: walk buyer's packages against each recipe's
110
+ * `capability_overlap` and reject mismatches.
111
+ *
112
+ * Called from the framework's `create_media_buy` and `update_media_buy`
113
+ * dispatch paths after recipes are hydrated from the {@link ProposalStore}.
114
+ * Per D4, the framework owns this gate so every adopter doesn't write the
115
+ * same intersection logic.
116
+ *
117
+ * Validation axes (per {@link CapabilityOverlap}):
118
+ *
119
+ * - `pricingModels` — checked against `package._resolved_pricing_model`
120
+ * or `package.pricing_model`.
121
+ * - `targetingDimensions` — checked against `package.targeting_overlay` keys.
122
+ * - `deliveryTypes` — checked against `package._resolved_delivery_type`
123
+ * or `package.delivery_type`.
124
+ * - `signalTypes` — checked against `package.signal_type`.
125
+ *
126
+ * Per the design's undefined-vs-empty-set semantics: `undefined` skips the
127
+ * gate; an explicit `Set` (including the empty set) is enforced.
128
+ *
129
+ * @public
130
+ */
131
+ function validateCapabilityOverlap(args) {
132
+ const { packages, recipes, fieldPathPrefix = 'packages' } = args;
133
+ for (let i = 0; i < packages.length; i++) {
134
+ const pkg = packages[i];
135
+ const productId = pkg.product_id;
136
+ if (!productId)
137
+ continue;
138
+ const recipe = recipes.get(productId);
139
+ if (!recipe || !recipe.capability_overlap)
140
+ continue;
141
+ const overlap = recipe.capability_overlap;
142
+ if (overlap.pricingModels) {
143
+ const requested = pkg._resolved_pricing_model ?? pkg.pricing_model;
144
+ if (requested !== undefined && !overlap.pricingModels.has(String(requested))) {
145
+ throw new async_outcome_1.AdcpError('INVALID_REQUEST', {
146
+ recovery: 'terminal',
147
+ message: `Buyer requested pricing_model=${JSON.stringify(requested)} on package ` +
148
+ `${JSON.stringify(productId)}, but this product's recipe declares ` +
149
+ `capability_overlap.pricingModels=${JSON.stringify([...overlap.pricingModels].sort())}. ` +
150
+ `The seller did not enable that pricing model for this product.`,
151
+ field: `${fieldPathPrefix}[${i}].pricing_option_id`,
152
+ });
153
+ }
154
+ }
155
+ if (overlap.targetingDimensions) {
156
+ const overlay = pkg.targeting_overlay;
157
+ const keys = overlay && typeof overlay === 'object' ? Object.keys(overlay) : [];
158
+ const disallowed = keys.filter(k => !overlap.targetingDimensions.has(k));
159
+ if (disallowed.length > 0) {
160
+ throw new async_outcome_1.AdcpError('INVALID_REQUEST', {
161
+ recovery: 'terminal',
162
+ message: `Buyer requested targeting dimensions ${JSON.stringify(disallowed.sort())} on ` +
163
+ `package ${JSON.stringify(productId)}, but this product's recipe declares ` +
164
+ `capability_overlap.targetingDimensions=` +
165
+ `${JSON.stringify([...overlap.targetingDimensions].sort())}. The seller did not ` +
166
+ `enable those targeting dimensions for this product.`,
167
+ field: `${fieldPathPrefix}[${i}].targeting_overlay`,
168
+ });
169
+ }
170
+ }
171
+ if (overlap.deliveryTypes) {
172
+ const delivery = pkg._resolved_delivery_type ?? pkg.delivery_type;
173
+ if (delivery !== undefined && !overlap.deliveryTypes.has(String(delivery))) {
174
+ throw new async_outcome_1.AdcpError('INVALID_REQUEST', {
175
+ recovery: 'terminal',
176
+ message: `Buyer requested delivery_type=${JSON.stringify(delivery)} on package ` +
177
+ `${JSON.stringify(productId)}, but this product's recipe declares ` +
178
+ `capability_overlap.deliveryTypes=${JSON.stringify([...overlap.deliveryTypes].sort())}.`,
179
+ field: `${fieldPathPrefix}[${i}].delivery_type`,
180
+ });
181
+ }
182
+ }
183
+ if (overlap.signalTypes) {
184
+ const signalType = pkg.signal_type;
185
+ if (signalType !== undefined && !overlap.signalTypes.has(String(signalType))) {
186
+ throw new async_outcome_1.AdcpError('INVALID_REQUEST', {
187
+ recovery: 'terminal',
188
+ message: `Buyer requested signal_type=${JSON.stringify(signalType)} on package ` +
189
+ `${JSON.stringify(productId)}, but this product's recipe declares ` +
190
+ `capability_overlap.signalTypes=${JSON.stringify([...overlap.signalTypes].sort())}.`,
191
+ field: `${fieldPathPrefix}[${i}].signal_type`,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ }
197
+ /**
198
+ * Validate `recipe.capability_overlap` is a subset of the matching product's
199
+ * wire-declared capabilities.
200
+ *
201
+ * Called at `putDraft` time. Mismatches throw `INTERNAL_ERROR` — this is
202
+ * an adopter bug (the manager declared an overlap claiming capabilities the
203
+ * wire shape doesn't advertise), not a buyer bug.
204
+ *
205
+ * @public
206
+ */
207
+ function validateOverlapSubsetOfWire(args) {
208
+ const productsById = new Map();
209
+ for (const p of args.products) {
210
+ if (p.product_id)
211
+ productsById.set(p.product_id, p);
212
+ }
213
+ for (const [productId, recipe] of args.recipes) {
214
+ if (!recipe.capability_overlap)
215
+ continue;
216
+ const product = productsById.get(productId);
217
+ if (!product)
218
+ continue; // missing-product is caught elsewhere
219
+ const overlap = recipe.capability_overlap;
220
+ if (overlap.pricingModels) {
221
+ const wirePricing = wirePricingModels(product);
222
+ const extras = [...overlap.pricingModels].filter(p => !wirePricing.has(p));
223
+ if (extras.length > 0) {
224
+ throw new async_outcome_1.AdcpError('INTERNAL_ERROR', {
225
+ recovery: 'terminal',
226
+ message: `Recipe for product ${JSON.stringify(productId)} declares ` +
227
+ `capability_overlap.pricingModels=${JSON.stringify([...overlap.pricingModels].sort())} ` +
228
+ `including ${JSON.stringify(extras.sort())}, but the wire product only advertises ` +
229
+ `${JSON.stringify([...wirePricing].sort())}. The recipe's overlap must be a subset ` +
230
+ `of the wire-declared capabilities; adopter declaration is inconsistent with the ` +
231
+ `product shape.`,
232
+ });
233
+ }
234
+ }
235
+ if (overlap.deliveryTypes) {
236
+ const wireDelivery = wireDeliveryTypes(product);
237
+ const extras = [...overlap.deliveryTypes].filter(p => !wireDelivery.has(p));
238
+ // Only enforce when the wire declares something — products lacking a
239
+ // delivery_type field shouldn't trip the gate.
240
+ if (extras.length > 0 && wireDelivery.size > 0) {
241
+ throw new async_outcome_1.AdcpError('INTERNAL_ERROR', {
242
+ recovery: 'terminal',
243
+ message: `Recipe for product ${JSON.stringify(productId)} declares ` +
244
+ `capability_overlap.deliveryTypes=${JSON.stringify([...overlap.deliveryTypes].sort())} ` +
245
+ `including ${JSON.stringify(extras.sort())}, but the wire product only advertises ` +
246
+ `${JSON.stringify([...wireDelivery].sort())}.`,
247
+ });
248
+ }
249
+ }
250
+ }
251
+ }
252
+ function wirePricingModels(product) {
253
+ const out = new Set();
254
+ const pricing = product.pricing_options;
255
+ if (!pricing)
256
+ return out;
257
+ for (const opt of pricing) {
258
+ if (opt.pricing_model)
259
+ out.add(String(opt.pricing_model));
260
+ }
261
+ return out;
262
+ }
263
+ function wireDeliveryTypes(product) {
264
+ const dt = product.delivery_type;
265
+ return dt ? new Set([String(dt)]) : new Set();
266
+ }
267
+ /**
268
+ * Return the first finalize-action refine entry from a
269
+ * `GetProductsRequest`, or `null` if no finalize entry exists.
270
+ *
271
+ * The index points at the entry's position in `refine[]` so the framework
272
+ * can produce indexed wire field paths (`refine[3].proposal_id`) on
273
+ * rejection — buyers parsing the error get a precise pointer.
274
+ *
275
+ * Per the spec, `buying_mode: 'refine'` carries a `refine[]` array of
276
+ * entries. Each entry has a `scope` (`request` / `product` / `proposal`)
277
+ * and an optional `action` (`include` / `omit` / `finalize`). v1.5 only
278
+ * intercepts `proposal`-scoped entries with `action: 'finalize'`.
279
+ *
280
+ * The framework processes ONE finalize entry per request; if the buyer
281
+ * sends multiple finalize entries, only the first is processed (rest fall
282
+ * through to the standard refine path).
283
+ *
284
+ * @public
285
+ */
286
+ function detectFinalizeAction(req) {
287
+ const refine = req.refine;
288
+ if (!refine || refine.length === 0)
289
+ return null;
290
+ for (let index = 0; index < refine.length; index++) {
291
+ const entry = refine[index];
292
+ if (entry.scope === 'proposal' && entry.action === 'finalize') {
293
+ const proposalId = entry.proposal_id;
294
+ if (typeof proposalId === 'string' && proposalId.length > 0) {
295
+ const ask = typeof entry.ask === 'string' ? entry.ask : undefined;
296
+ return ask !== undefined ? { index, proposalId, ask } : { index, proposalId };
297
+ }
298
+ }
299
+ }
300
+ return null;
301
+ }
302
+ let logger = {
303
+ info: (message, fields) => {
304
+ if (fields) {
305
+ console.log(JSON.stringify({ message, ...fields }));
306
+ }
307
+ else {
308
+ console.log(message);
309
+ }
310
+ },
311
+ };
312
+ /**
313
+ * Replace the module-level logger that proposal-lifecycle structured
314
+ * events (`proposal.draft_persisted`, `proposal.finalized`, `proposal.expired`,
315
+ * `proposal.consumed`) emit through. Adopters wire this to their existing
316
+ * logger (pino, bunyan, etc.) so lifecycle events route through the same
317
+ * pipeline as the rest of their server logs. Tests use it to capture
318
+ * structured emissions for assertion.
319
+ *
320
+ * @public
321
+ */
322
+ function setProposalLifecycleLogger(next) {
323
+ logger = next;
324
+ }
325
+ /** `proposal.draft_persisted` event. */
326
+ function logDraftPersisted(args) {
327
+ logger.info('proposal.draft_persisted', {
328
+ event: 'proposal.draft_persisted',
329
+ proposal_id: args.proposalId,
330
+ account_id: args.accountId,
331
+ recipes_count: args.recipesCount,
332
+ });
333
+ }
334
+ /**
335
+ * `proposal.finalized` event. `path` is `'inline'` or `'handoff'`.
336
+ */
337
+ function logFinalizeSucceeded(args) {
338
+ logger.info('proposal.finalized', {
339
+ event: 'proposal.finalized',
340
+ proposal_id: args.proposalId,
341
+ account_id: args.accountId,
342
+ expires_at: args.expiresAt.toISOString(),
343
+ path: args.path,
344
+ });
345
+ }
346
+ /** `proposal.expired` event. */
347
+ function logExpired(args) {
348
+ logger.info('proposal.expired', {
349
+ event: 'proposal.expired',
350
+ proposal_id: args.proposalId,
351
+ account_id: args.accountId,
352
+ now: args.now.toISOString(),
353
+ expires_at: args.expiresAt.toISOString(),
354
+ grace_seconds: args.graceSeconds,
355
+ });
356
+ }
357
+ /** `proposal.consumed` event. */
358
+ function logConsumed(args) {
359
+ logger.info('proposal.consumed', {
360
+ event: 'proposal.consumed',
361
+ proposal_id: args.proposalId,
362
+ account_id: args.accountId,
363
+ media_buy_id: args.mediaBuyId,
364
+ });
365
+ }
366
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../../../src/lib/server/decisioning/proposal/lifecycle.ts"],"names":[],"mappings":"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"}