@openlup/platform 0.27.0 → 0.28.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 (115) hide show
  1. package/CHANGELOG.md +167 -109
  2. package/README.md +111 -8
  3. package/dist/account-support/accountReadFacade.d.ts +8 -0
  4. package/dist/account-support/accountReadFacade.js +10 -0
  5. package/dist/account-support/accountReadModels.d.ts +69 -0
  6. package/dist/account-support/accountReadModels.js +272 -0
  7. package/dist/account-support/bindings.d.ts +23 -0
  8. package/dist/account-support/bindings.js +16 -0
  9. package/dist/account-support/contracts/account.d.ts +281 -0
  10. package/dist/account-support/contracts/account.js +1 -0
  11. package/dist/account-support/contracts/capabilities.d.ts +44 -0
  12. package/dist/account-support/contracts/capabilities.js +1 -0
  13. package/dist/account-support/contracts/commands.d.ts +307 -0
  14. package/dist/account-support/contracts/commands.js +1 -0
  15. package/dist/account-support/contracts/customer360.d.ts +154 -0
  16. package/dist/account-support/contracts/customer360.js +1 -0
  17. package/dist/account-support/contracts/index.d.ts +10 -0
  18. package/dist/account-support/contracts/index.js +1 -0
  19. package/dist/account-support/contracts/invoice.d.ts +79 -0
  20. package/dist/account-support/contracts/invoice.js +1 -0
  21. package/dist/account-support/contracts/operator.d.ts +289 -0
  22. package/dist/account-support/contracts/operator.js +1 -0
  23. package/dist/account-support/contribution.d.ts +24 -0
  24. package/dist/account-support/contribution.js +22 -0
  25. package/dist/account-support/customer360.d.ts +106 -0
  26. package/dist/account-support/customer360.js +163 -0
  27. package/dist/account-support/customerAccountReadDiagnostics.d.ts +11 -0
  28. package/dist/account-support/customerAccountReadDiagnostics.js +71 -0
  29. package/dist/account-support/index.d.ts +26 -0
  30. package/dist/account-support/index.js +15 -0
  31. package/dist/account-support/invoiceAccess.d.ts +57 -0
  32. package/dist/account-support/invoiceAccess.js +40 -0
  33. package/dist/account-support/migrations.d.ts +14 -0
  34. package/dist/account-support/migrations.js +7 -0
  35. package/dist/account-support/operatorAuthority.d.ts +67 -0
  36. package/dist/account-support/operatorAuthority.js +379 -0
  37. package/dist/account-support/operatorRecovery.d.ts +66 -0
  38. package/dist/account-support/operatorRecovery.js +129 -0
  39. package/dist/account-support/orderHistory.d.ts +50 -0
  40. package/dist/account-support/orderHistory.js +188 -0
  41. package/dist/account-support/paymentMethodComposition.d.ts +5 -0
  42. package/dist/account-support/paymentMethodComposition.js +4 -0
  43. package/dist/account-support/postgresOperatorAuthority.d.ts +16 -0
  44. package/dist/account-support/postgresOperatorAuthority.js +93 -0
  45. package/dist/account-support/selfService.d.ts +6 -0
  46. package/dist/account-support/selfService.js +81 -0
  47. package/dist/account-support/subscriptionCommandCodec.d.ts +10 -0
  48. package/dist/account-support/subscriptionCommandCodec.js +38 -0
  49. package/dist/catalog/draftSchemas.d.ts +1 -1
  50. package/dist/catalog/foundationSchemas.d.ts +3 -3
  51. package/dist/catalog/resolvedSkuProjection.d.ts +2 -2
  52. package/dist/catalog/sellableSchemas.d.ts +2 -2
  53. package/dist/commerce/checkoutCommandSchemas.d.ts +2 -2
  54. package/dist/commerce/checkoutResumeSchemas.d.ts +6 -6
  55. package/dist/commerce/checkoutSchemas.d.ts +12 -12
  56. package/dist/commerce/commerceReturnsPort.d.ts +2 -2
  57. package/dist/commerce/configuratorIntentSchemas.d.ts +2 -2
  58. package/dist/commerce/contractPrimitives.d.ts +8 -8
  59. package/dist/commerce/customerDefaultsSnapshotSchemas.d.ts +4 -4
  60. package/dist/commerce/model/omsReadModelHelpers.d.ts +4 -4
  61. package/dist/commerce/offerAvailabilitySchemas.d.ts +1 -1
  62. package/dist/commerce/oms/omsContractBase.d.ts +15 -15
  63. package/dist/commerce/oms/omsContractReadAuxSchemas.d.ts +11 -11
  64. package/dist/commerce/oms/omsContractReadSchemas.d.ts +121 -121
  65. package/dist/commerce/oms/omsContractRequests.d.ts +13 -13
  66. package/dist/commerce/oms/omsControlPlane.d.ts +22 -22
  67. package/dist/commerce/oms/omsFulfillmentContractSchemas.d.ts +12 -12
  68. package/dist/commerce/oms/omsFulfillmentDebugSchemas.d.ts +12 -12
  69. package/dist/commerce/orderReviewContracts.d.ts +33 -33
  70. package/dist/commerce/outboxEventSchemas.d.ts +4 -4
  71. package/dist/commerce/schemas.d.ts +21 -21
  72. package/dist/commerce/server/orderReviewHandlers.d.ts +10 -10
  73. package/dist/communications/consentPurposeRegistry.d.ts +1 -1
  74. package/dist/communications/newsletterIntegrationContracts.d.ts +8 -8
  75. package/dist/composition/accountSupportContribution.d.ts +18 -0
  76. package/dist/composition/accountSupportContribution.js +21 -0
  77. package/dist/composition/index.d.ts +1 -0
  78. package/dist/composition/index.js +1 -0
  79. package/dist/fulfillment/handlerSchemas.d.ts +40 -40
  80. package/dist/identity/customerContracts.d.ts +2 -2
  81. package/dist/invoicing/snapshot.d.ts +1 -1
  82. package/dist/pricing/acquisitionQuoteBinding.d.ts +1 -1
  83. package/dist/pricing/catalogFactsSchemas.d.ts +1 -1
  84. package/dist/pricing/quotePromotionEvidence.d.ts +1 -1
  85. package/dist/pricing/quoteSchemas.d.ts +56 -56
  86. package/dist/promotions/adminPromotionCodesContracts.d.ts +30 -30
  87. package/dist/promotions/adminPromotionsContracts.d.ts +14 -14
  88. package/package.json +12 -2
  89. package/release-gates.json +30 -3
  90. package/sql/20261026120000_account_support_operator_authority.sql +693 -0
  91. package/src/account-support/accountReadFacade.ts +15 -0
  92. package/src/account-support/accountReadModels.ts +371 -0
  93. package/src/account-support/bindings.ts +28 -0
  94. package/src/account-support/contracts/account.ts +306 -0
  95. package/src/account-support/contracts/capabilities.ts +30 -0
  96. package/src/account-support/contracts/commands.ts +243 -0
  97. package/src/account-support/contracts/customer360.ts +150 -0
  98. package/src/account-support/contracts/index.ts +141 -0
  99. package/src/account-support/contracts/invoice.ts +44 -0
  100. package/src/account-support/contracts/operator.ts +123 -0
  101. package/src/account-support/contribution.ts +35 -0
  102. package/src/account-support/customer360.ts +268 -0
  103. package/src/account-support/customerAccountReadDiagnostics.ts +83 -0
  104. package/src/account-support/index.ts +72 -0
  105. package/src/account-support/invoiceAccess.ts +63 -0
  106. package/src/account-support/migrations.ts +7 -0
  107. package/src/account-support/operatorAuthority.ts +393 -0
  108. package/src/account-support/operatorRecovery.ts +136 -0
  109. package/src/account-support/orderHistory.ts +309 -0
  110. package/src/account-support/paymentMethodComposition.ts +8 -0
  111. package/src/account-support/postgresOperatorAuthority.ts +92 -0
  112. package/src/account-support/selfService.ts +83 -0
  113. package/src/account-support/subscriptionCommandCodec.ts +48 -0
  114. package/src/composition/accountSupportContribution.ts +28 -0
  115. package/src/composition/index.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,173 @@ in the source repository.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.28.0]
14
+
15
+ - Publishable on the npm `latest` dist-tag as `0.28.0`, from tag
16
+ `openlup-platform-v0.28.0`.
17
+
18
+ Add experimental account-support and type-only account-support/contracts exports
19
+ with five owner-derived envelopes, explicit capability types, unchanged account-read
20
+ diagnostics and an injected read facade. Hosts retain authorization, projections,
21
+ private extensions and driver selection; command envelopes install no executor.
22
+ Add owner-equality, browser, delegation, reference and packed-consumer witnesses.
23
+
24
+ Migration: none for existing callers. The new subpaths are additive and the
25
+ reference diagnostic path retains its exports and behavior. The catalog,
26
+ commerce-server, commerce, fulfillment, identity, pricing and promotions API
27
+ reports (`api/catalog.api.md`, `api/commerce-server.api.md`, `api/commerce.api.md`,
28
+ `api/fulfillment.api.md`, `api/identity.api.md`, `api/pricing.api.md`,
29
+ `api/promotions.api.md`) reorder existing enum/union members because declaration
30
+ emit order changed after adding the module: member order only, no declaration
31
+ change; no member is added, removed or changed. No SQL migration or activation.
32
+
33
+ Add bounded account/support read composition through the existing experimental
34
+ account-support and type-only account-support/contracts entries. New runtime
35
+ exports: CUSTOMER_ACCOUNT_V2_CONTRACT_VERSION, readAccountSnapshot,
36
+ isCustomerVisibleSubscription, recurringPrice, computeEditState, editCutoff,
37
+ buildActionRequired, CUSTOMER_ORDERS_CONTRACT_VERSION, readCustomerOrderSummaries,
38
+ readCustomerOrderDetail, customerOrderMoney, toOrderMoneyHeader, toOrderMoneyItem,
39
+ mapCustomerOrderLines, lineListTotalMinor, SUPPORT_CUSTOMER_360_CONTRACT_VERSION,
40
+ projectCustomer360Snapshot, deriveContactHealth, boundedCustomerJourneyAudit,
41
+ createCustomer360ReadFacade, createInvoiceAccess, downloadOwnedInvoicePdf and
42
+ deriveCustomerDocumentDeliveryStatus. Add neutral account/order/support DTOs and
43
+ typed source, projection and invoice-owner ports; preserve R1 exports.
44
+
45
+ Reference factories and host-fed views are default-off/unmounted. Native support
46
+ reads use the existing authorized PostgreSQL scope; unselected capabilities
47
+ refuse explicitly. Pricing, captured presentation and private extensions stay
48
+ host injected. Invoice access binds the document to a found owned-order history
49
+ before ticket resolution or artifact IO, adding one history read; foreign/unknown
50
+ documents return denied. Download requires a bound owned-order history; an unbound
51
+ history reports unsupported (host_binding_required). Denied, unknown and unsupported
52
+ history results retain their distinct M09 outcomes before ticket/artifact IO;
53
+ thrown history stays unknown. M09 PDF validation remains unchanged.
54
+ Customer 360 facade authorization now runs before every source read and returns
55
+ denied with zero source IO on refusal. The reference binding uses that callback
56
+ once per call before opening a governed journey or independent diagnostic scope.
57
+ Customer 360 subscription pointer enrichment includes optional nullable
58
+ paymentMethodKind, preserving selected-empty null and unread omission. Reference
59
+ diagnostic search, segment history and v2 overview select their own authorized
60
+ scope; reference line presentation picks only its declared display fields.
61
+
62
+ Migration: the unreleased Customer360Subscription gains optional nullable
63
+ paymentMethodKind. Selected Customer360ProjectionInput.subscriptionPointers values
64
+ now supply paymentMethodKind alongside shippingAddressId; use null for known-empty
65
+ evidence and omit the pointer source when unread. Callers of the unreleased
66
+ createCustomer360ReadFacade now supply authorize(): Promise<boolean> alongside
67
+ journey, summary and diagnostics, and handle the added { kind: "denied" } result
68
+ on every method. No SQL migration is required.
69
+
70
+ The unchanged generator also regenerates these sibling API reports:
71
+ - `packages/platform/api/catalog.api.md`
72
+ - `packages/platform/api/commerce-server.api.md`
73
+ - `packages/platform/api/commerce.api.md`
74
+ - `packages/platform/api/communications.api.md`
75
+ - `packages/platform/api/fulfillment.api.md`
76
+ - `packages/platform/api/identity.api.md`
77
+ - `packages/platform/api/invoicing.api.md`
78
+ - `packages/platform/api/pricing.api.md`
79
+ - `packages/platform/api/promotions.api.md`
80
+
81
+ These generated companions are member order only, no declaration change. No
82
+ snapshot is hand-edited; no member is added, removed or changed in those reports.
83
+
84
+ Add experimental self-service composition returning SelfServiceCommandFacade,
85
+ with required host capabilities and every guarded output lane. ENV-R3-1 keeps
86
+ input lanes optional and adds nativeLegacySubscription plus subscriptionControl.
87
+ Unselected methods return AccountSupportLaneUnavailable: paymentMethod uses the
88
+ host paymentMethodSetup refusal by identity, commerce uses commerceRecovery,
89
+ and every other lane uses a frozen host_binding_required refusal after its guard.
90
+ Native routing retains ownership-before-quote behavior and explicit pause; typed,
91
+ raw, profile, method, commerce and recovery delegates keep owner results/refusals.
92
+ Raw/typed admission requires the supplied clientId before every owner call. The
93
+ trailing `ControlSnapshot = unknown` generic preserves snapshot DTOs and existing
94
+ twelve-argument consumers.
95
+ The generic M07 adapter maps setupMethod to paymentMethod.execute. No owner type
96
+ imports or new module-graph edges. Native repair is a registered follow-up, not a
97
+ cut; token handlers stay in reference source. The reference binding remains off.
98
+
99
+ The unchanged API generator leaves two sibling snapshots changed from final R1:
100
+ `commerce-server.api.md` and `commerce.api.md` under `packages/platform/api/`.
101
+ These are disclosed generated companions: member order only, no
102
+ declaration change, proven by AST comparison normalizing union/enum member order.
103
+
104
+ Migration: development-preview envelope delta ENV-R3-1. Supply verified context,
105
+ AccountSupportCapabilities and complete selected owner lanes. Handle the named
106
+ unavailable arm in method results. Supported paymentMethodSetup requires paymentMethod; supported
107
+ commerceRecovery/configuredPurchase require commerce; supported subscription
108
+ genericBundleCommands/commandBoundReceipts require a subscription command lane. No schema, dependency, release cap, activation or browser cutover change.
109
+
110
+ Add explicit operator recovery composition, current managed email claim/settlement,
111
+ managed account link and human recovery fence, and native support delegation to
112
+ M10 through injected executors. Preserve donor callback and failure ordering;
113
+ expose actual optional owner receipts and truthful link-then-action partial results.
114
+ The reference binding remains default-off and unmounted.
115
+
116
+ Migration:
117
+ - Introduce the frozen native support-authority SQL and packed twin plus the
118
+ managed current-authority forward, after complete same-rail predecessors.
119
+ - Retire `customer_support_correct_subject_email_v1`: human calls raise 55000
120
+ `customer_support_email_correction_requires_admission`; drain old callers and
121
+ use admission → claim → claim-fenced identity commit → settlement.
122
+ - operator_subscription_actions: 3 combined email calls now execute admission → claim → claimed auth move (linked only, deferred fence forced before settlement) → settlement; existing success/replay/collision/stale/audit expectations retained; human roster fixture added.
123
+ - operator_contact_correction: 4 combined email calls now execute admission → claim → claimed auth move (linked only, deferred fence forced before settlement) → settlement; existing success/replay/collision/stale/audit expectations retained; human roster fixture added.
124
+ - runtime_capability_boundary: missing-subject/null-clock correction uses admission (same subject_not_found result); human admission fixture added; machine retired-entry 42501 unchanged.
125
+ - marketing_lead_email_namespace: 1 combined email calls now execute admission → claim → claimed auth move (linked only, deferred fence forced before settlement) → settlement; existing success/replay/collision/stale/audit expectations retained; human roster fixture added.
126
+ - absorb_lead: 1 combined email calls now execute admission → claim → claimed auth move (linked only, deferred fence forced before settlement) → settlement; existing success/replay/collision/stale/audit expectations retained; human roster fixture added.
127
+ - CD-8: use `status = 'payment_pending'` for native residual-unpaid detection,
128
+ matching the native cycle CHECK; native outcomes and the managed predicate stay
129
+ unchanged. The native witness covers resume with and without that cycle.
130
+ - CD-9 standing donor-adopter adoption mapping: link keeps the same body; the donor adopter uses
131
+ INVOKER with table-wide `service_role` access, while OpenLup uses DEFINER under
132
+ column-level capability closure. Preserve the migration owner, fixed search
133
+ path and service-only EXECUTE; widen no table grant. Retired email correction
134
+ and recovery remain INVOKER.
135
+ - RD-R4-4 link refusal proof: machine/non-human, missing and inactive operators
136
+ leave clients, support commands and audit rows unchanged. Subject refusals
137
+ leave clients and auth identities unchanged and write exactly one refusal
138
+ receipt plus one matching audit row for the key, with no other row/xmin changes.
139
+ Unknown subjects return `refused` / `subject_not_found`; email expectation,
140
+ foreign-identity and already-linked conflicts return `conflict` with
141
+ `email_expectation_conflict`, `identity_linked_elsewhere` and
142
+ `subject_account_linked`, respectively. Same-key replay returns the stored
143
+ refusal unchanged with zero further writes.
144
+ - Native M03 contact/link and unsupported M10 subcases remain named refusals;
145
+ no historical migration, pin, module graph or source-release contract changes.
146
+
147
+ API generator companions and measured verification are recorded in the module plan.
148
+
149
+ Add inert account/support graph bindings, guarded owner services and composition
150
+ descriptors over the R1–R4 envelopes. The reference recipe is default-off, mounts
151
+ nothing and starts no workers. Service/port/route aliases share one callable
152
+ guard; readiness is observed before every entrance. Owner authorization, keys,
153
+ receipts, refusals and M04 delivery/replay remain with their existing owners.
154
+ The reference operator subscription adapter restores donor BFF command metadata
155
+ around one R4 dispatch and serializes only the strict donor outcome fields,
156
+ including decoded ISO timestamps and explicit nulls. Optional native `ownerReceipt`
157
+ evidence stays server-side and is absent from the response. The composition witness
158
+ distinguishes that response from SQL storage.
159
+
160
+ Migration: additive `createAccountSupportBindings`, `createAccountSupportServices`
161
+ and `createAccountSupportContribution` exports. Hosts supply one graph, prebound
162
+ operations, exact selected schema and complete catalogue identity, map admission
163
+ refusals before serving routes, and explicitly compose declared owner contributions.
164
+ Null selected operations remain required/unbound. Commerce is a nullable injected
165
+ record returning `unsupported/host_binding_required` when unbound. The reference
166
+ `commerceOwner` option accepts the host-built M11 selection over bound checkout,
167
+ recovery and ATP callables, with the complete account/M11/ATP schema union and
168
+ matching enablement/readiness. R5b does not construct M11 or import its adapters;
169
+ it uses a local structural selection type. Supply the existing effect registry
170
+ as `commerceRegistry` and forward guarded services and contributions once;
171
+ unknown stock, unsupported options and commerce outcomes remain unchanged.
172
+ While account-support is disabled, a supplied M11 selection stays cold: the
173
+ keyed commerce entrance returns the disabled refusal before the selected owner
174
+ or the injected record runs, and no M11 contribution, port, route, trigger,
175
+ reference handle or schema requirement is forwarded.
176
+ Configured recovery/purchase elements use explicit host paths and clients. No SQL, version, serving
177
+ activation or source-release snapshot changes. Regenerated account-support and
178
+ composition API reports describe these additions; no sibling API report changed.
179
+
13
180
  ## [0.27.0]
14
181
 
15
182
  - Publishable on the npm `latest` dist-tag as `0.27.0`, from tag
@@ -165,112 +332,3 @@ Migration: managed hosts must pass exact applied-transition attribution to the n
165
332
 
166
333
  Native attempt-replay parity remains REGISTERED with M10; these managed forwards
167
334
  do not implement native parity or authorize host activation.
168
-
169
- ## [0.25.0]
170
-
171
- - Publishable on the npm `latest` dist-tag as `0.25.0`, from tag
172
- `openlup-platform-v0.25.0`.
173
-
174
- - Re-pin the pending M10/F17 control fixtures after landed M08/M09 without
175
- changing either installation rail, the migration manifest or landed N1. The
176
- 16-entry packet has seven native and nine managed pins. Native X restores
177
- ATP-counted late-positive stock recovery; Y filters paid retry candidates
178
- before LIMIT. Fold command-preview receipt replay into uninstalled N2, keeping
179
- apply unchanged. Preserve the historical 14-pin approval reader and exact
180
- prefix, definition, statement, ACL and catalog controls. Real PostgreSQL
181
- witnesses cover ATP, starvation, all 43 fresh command scenarios and raw preview
182
- replay with no counts/columns/xmin delta.
183
-
184
- No package SQL asset, export, runtime activation or external CI dependency is
185
- introduced. The development-preview boundary remains.
186
-
187
- - Fix uninstalled N3 normal_due pagination to exclude waiting/stock_secured cases before LIMIT, preventing normal-renewal starvation.
188
-
189
- - Repair uninstalled N2 donor no-op truth for native bundle/resize, plan, package, add-on and same-UTC-day slide commands before repricing: preserve locked prices after catalogue changes, writing only the command receipt, with no quote, event or version increment. Native resize compares lines/cadence; portion mode/factor remain host-owned without native storage. Predicate-removal mutants cover every mapped donor action; apply stays unchanged.
190
-
191
- - Audit pending M10 donor change and no-op semantics together. N2 plan edits
192
- apply requested core lines; new add-ons normalize quantity, preserve cadence
193
- and compare UUIDs by value. N3 preserves paused waits, filters eligible recovery
194
- before LIMIT, binds frozen reads to the current active schedule, reports free
195
- stock separately from own holds, and ignores closed/unpaid realization notices.
196
- Real PostgreSQL tables cover applied state, no-op/refusal/replay and rolled-back
197
- assignment mutants. Installed rails and N2 apply remain unchanged; channel
198
- exposure/admission parity stays outside the frozen stock-seam claim.
199
-
200
- - Close the 0.24.0 known limitation that managed dunning exhaustion still pauses active subscriptions.
201
- - Land the reviewed managed M1/M2 prefix: refunds preserve subscription lifecycle and paid history; exhausted dunning stays open with NULL retry and active service until authorized same-cycle repair.
202
- - Folded scope E-gate-replay-loop-landed-untested: retain the existing interleaving-aware catalog replay and add the Docker-free landed N1/M1/M2 witness.
203
- - Folded scope D-earlier-pin-digest-unplanted: prove CI and release refuse changed earlier M1 bytes beneath landed M2.
204
-
205
- Migration notes: Apply M1 then M2. Existing paused, expired and refund-cancelled history is not rewritten or reactivated. The existing first-cycle refund stock-release guard remains; later refund-evidence parity and stock-wait/winback changes are separate. No runner is activated.
206
-
207
- - Add native N2 command preview/apply stores and a P1 command adapter with atomic future terms, actor/key/actual-command receipts and applied/replayed/noop/refused outcomes; preserve frozen current obligations and existing native callers.
208
- - Type-level flip for dev-preview consumers: `NATIVE_SUBSCRIPTION_CAPABILITIES.genericBundleCommands.supported` and `.commandBoundReceipts.supported` change from `false` to `true`; command results now include `SubscriptionCommandRefusal`.
209
-
210
- Migration: install N1 then N2 through the complete native manifest; preserve receipts on rollback. Accepted future prices use lock_until_edit, proration none. Address mutation and private introductory/graduation policy stay host-owned; native activation continues to require captured payment evidence.
211
-
212
- Migration (C73, temporary limitation): managed `subscription_create_provisional_for_checkout` stamps an explicit timezone literal equal to today's `subscriptions.timezone` column DEFAULT. Adopters changing that DEFAULT must also replace the function until the scheduled follow-up forward follows the DEFAULT; no managed SQL changes here.
213
-
214
- Migration: `SubscriptionCommandPort.apply()` may now return `SubscriptionCommandRefusal` (`outcome: "refused"`), so callers must handle it.
215
-
216
- - Type-level change visible to dev-preview consumers: `RenewalPaymentRail.execute` adds an optional `failure` field for explicit failure evidence.
217
- - A host or driver skips `openCase` after a replayed `applyFailure` receipt only when that rung's case propagation already committed; otherwise recovery must complete propagation. The P8 retry driver must add a replay/case-advanced signal and a zero-delta witness for replay after committed propagation.
218
- - N2 preview follows the supplied core lines for plan-length changes (omitted lines retain stored expansion); new add-ons normalize missing/nonpositive quantity to one, add-on actions preserve cadence, and quantity updates/removals compare variant UUIDs case-insensitively.
219
-
220
- Land the seven reviewed managed stock-wait/ATP and F17 refund-parity forwards.
221
- Managed hosts can use the service-role SQL functions and pgTAP witnesses; the
222
- package declares the SQL surface and keeps TypeScript stock recovery unavailable
223
- because no managed adapter implements the stock-wait/availability ports.
224
-
225
- Migration: apply the complete managed prefix through `20261024185100` before
226
- calling stock-wait or refund-evidence functions. M4 extends M2's active/open
227
- continuity with wait exclusion before LIMIT. M5 makes positive customer
228
- cancellations immediately winback-eligible within 120 days, retaining episode
229
- dedupe, and maps started/resumed notices. F17 accepts cumulative provider snapshots,
230
- emits one refunded event on transition, and preserves M1 refund/lifecycle
231
- independence. Keep captured obligations and receipts on rollback and disable the
232
- host stock-wait driver first. SQL installs no scheduler or payment executor.
233
-
234
- ATP protects active upcoming demand within 14 days plus live provider hard holds.
235
- The exposure hook remains zero; current donor channel admission is deferred.
236
- This is a development-preview SQL surface, not a composed managed TypeScript port
237
- or a claim of advance future-cycle reservations or stable installation support.
238
-
239
- Native stock-wait persistence, frozen discovery and stock-only refusal recovery
240
- now have transaction-bound adapters. The native ATP/new-purchase read protects
241
- hard holds and fixed 14-day soft subscription demand; the renewal allocator uses
242
- the same seam. X restores late-paid released stock once, and Y filters paid and
243
- settled retry obligations before LIMIT. Managed stock wait and runner composition
244
- remain separate; native selection still requires passing real-PostgreSQL proof.
245
-
246
- Migration: install the native N3, ATP seam, allocator, X and Y prefix in filename
247
- order, with their package twins and regenerated selected-catalog-v2 inventory.
248
- Migration: upgrading hosts must grant their native inventory-reserving runtime
249
- role EXECUTE on public.inventory_available_to_promise(text,text,timestamptz,boolean)
250
- and public.inventory_channel_exposure_quantity(text,text), plus SELECT on the
251
- seam's underlying relations as listed in Data and migrations, before using the
252
- updated allocator or N3 stock-wait paths.
253
- `StockWaitStorePort.listCandidates` now returns `StockWaitFrozenCase[]`: discovery
254
- may have no durable case yet. Hosts must retain its frozen snapshot and binding.
255
- Frozen discovery requires the active current schedule; paused current waits remain open.
256
- Deficits separate own reserved units from free ATP and subtract both for missing
257
- units. Closed or pending-payment resume callbacks return null without writes; paid
258
- fulfillment-pending orders can complete realization admission.
259
- No advance reservation, physical coverage guarantee or one-time checkout writer
260
- is introduced. No pause, payment execution or parcel-arrival fact is added.
261
- Uncaptured stock refusals rotate on the operation selection timestamp even when
262
- missing or stale stock prevents case creation, allowing replenished work through
263
- a bounded candidate page.
264
-
265
- M10 P6 + P8: composed subscriptions (development preview)
266
-
267
- Migration: Additive `./subscriptions` facades are `createSubscriptionServices`, `createSubscriptionCommandExamples`, `createSubscriptionLifecycleMessages` and `subscriptionLifecycleTemplate`; hosts explicitly supply readiness, execution, commands and M04 delivery. No factory activates serving work. `SubscriptionLifecycleFact` is exported from this entry; `subscriptionLifecycleTemplate(kind, retryAttempt?)` preserves the installed payment-failure rungs (1, 2, otherwise 3). `runRenewalBatchRows` exposes the existing per-row error-result isolation for composed hosts.
268
- Migration: Additive `./composition` entry `createSubscriptionContribution` describes exactly one selected subscription schedule; off supplies none. Hosts bind its callable to their existing population lease and observe the complete installed schema.
269
- Migration: `createPostgresRetryStore` adds `failureProgress(operationId,key)`, returning receipt replay and committed case progression. The native retry driver completes interrupted propagation and skips already advanced cases; existing applyFailure/openCase signatures remain unchanged.
270
-
271
- The inert native reference binding composes mandatory G23, dunning and stock wait.
272
- Captured alignment cases retain authority under off. Prepared attempts reconcile
273
- without re-execution; ordinary retries bind the frozen mandate and logical cycle.
274
- M04 owns delivery; M12 owns aggregation. No SQL asset, serving swap, release or
275
- managed TypeScript recovery is introduced. Native multi-cycle prepaid and M07
276
- prepared-attempt-store capabilities retain their named unsupported boundaries.
package/README.md CHANGED
@@ -10,18 +10,23 @@ Development preview. This package is part of the publishable set with core and o
10
10
 
11
11
  It holds the runnable server substrate an OpenLup application composes: the Node HTTP runtime, BFF dispatch, scheduling and job leases, blob storage, data gateways, the node-postgres migration runner and bundle composition. Ports and their contracts stay in `@openlup/core/platform-runtime`.
12
12
 
13
- For the prepared `0.27.0` set, read the [adjacent-release migration and known
14
- limitations](CHANGELOG.md#0270) before selecting optional services. Experimental
13
+ For the prepared `0.28.0` set, read the [adjacent-release migration and known
14
+ limitations](CHANGELOG.md#0280) before selecting optional services. Experimental
15
+ account/support APIs use `./account-support` and the type-only
16
+ `./account-support/contracts`; reference bindings remain inert and default-off.
17
+ Apply the M12 support-authority forwards after complete same-rail predecessors
18
+ and follow the email-correction admission, claim, identity-commit and settlement
19
+ migration notes before replacing retired callers. Experimental
15
20
  commerce schemas and ports use `./commerce` and `./commerce/contracts`;
16
21
  handlers, adapters and checkout engines use the Node-only `./commerce/server`.
17
22
  The commerce contribution and reference binding remain inert and default-off.
18
- Install the complete native chain through position 86
19
- (`20261024184600_subscription_retry_candidate_payment_filter.sql`); M11 adds no
20
- native SQL. Sparse SQL projections are not an install chain. Native runtime
23
+ Install the complete native chain through the M12 support-authority forward
24
+ (`20261026120000_account_support_operator_authority.sql`). Sparse SQL projections
25
+ are not an install chain. Native runtime
21
26
  roles need the ATP/exposure EXECUTE and underlying SELECT grants described in
22
27
  the release notes.
23
- Managed hosts apply the complete prefix through `20261025110000`, including
24
- M11's nine forwards for preference/return ownership, operator receipts,
28
+ Managed hosts apply the complete prefix through `20261026120100`, including
29
+ the current support-authority forward and M11's nine forwards for preference/return ownership, operator receipts,
25
30
  acquisition/finalize admission, ATP preview and starter graduation. Legacy
26
31
  omitted-country input uses the configured settlement region; neutral commands
27
32
  require explicit country. Starter graduation admits 14, 21 or 28 days; rollback
@@ -45,7 +50,7 @@ Adopters must not activate unselected or unready invoicing; installation and
45
50
  inert contributions register no runner, worker, route or schedule.
46
51
  M06 managed-host proof classes remain pending in the
47
52
  [M06 parity ledger](../../docs/platform/plans/oss-m06-stock-reservations-delivery.md#parity-pending-rows).
48
- Size comparison uses the published `0.26.0` tarball. Preparation and offline
53
+ Size comparison uses the published `0.27.0` tarball. Preparation and offline
49
54
  adapter evidence grant no publication or provider-account certification.
50
55
 
51
56
  Longer module recipes live in the [platform package reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md).
@@ -1041,3 +1046,101 @@ legacy fallback and forward-only migration limits are owned by the
1041
1046
  [M09 migration section](../../docs/platform/DATA_AND_MIGRATIONS.md#m09-invoicing-forward-design-and-control-approval).
1042
1047
 
1043
1048
  OMS read projections are optional. Omitting the host health classifier preserves the original unprojected empty health snapshot (`ok`, no reasons or evidence IDs); it does not evaluate provider health. The reference composition injects its existing classifier and evidence readers.
1049
+
1050
+ ## Account and support contracts
1051
+
1052
+ Experimental `@openlup/platform/account-support` supplies `createAccountReadFacade`
1053
+ and the unchanged account-read diagnostic helpers. Inject account and order owner
1054
+ ports; delegation preserves their arguments, receivers, results, nulls and thrown
1055
+ failures. Authentication, authorization and private profile/market projection stay
1056
+ with the host. Importing this entry selects no driver or capability.
1057
+
1058
+ `account-support/contracts` is type-only and browser-safe. It declares account,
1059
+ Customer 360, self-service command, operator recovery and invoice-access envelopes
1060
+ with explicit capability flags. These declarations do not install their services.
1061
+ The [account/support reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#account-and-support-contracts)
1062
+ owns the available boundary and later-phase limits.
1063
+
1064
+ R2 adds `readAccountSnapshot` with the two-stage fan-out and a store-level recent
1065
+ 20-order request, stored-money order history/detail, Customer 360 projections
1066
+ and M09 invoice history/PDF delegation. `createInvoiceAccess` checks the requested
1067
+ document against the owned account/order history before resolving its ticket or
1068
+ reading PDF bytes; foreign or unknown documents return `{ kind: "denied" }`. Select pricing, captured line
1069
+ presentation, private extensions and fulfillment evidence through typed host
1070
+ ports. Missing evidence stays unknown; owner refusals retain their distinctions.
1071
+ The default-off reference selections and host-fed read views are unmounted.
1072
+ Native Customer 360 uses the existing authorized PostgreSQL support reader;
1073
+ account/history/invoice drivers still require explicit host selection.
1074
+ Subscription pointer enrichment preserves optional nullable `paymentMethodKind`:
1075
+ selected-empty evidence is null, while unread evidence is omitted. Reference
1076
+ line presentation explicitly picks the declared display keys before projection.
1077
+
1078
+ `createCustomer360ReadFacade({ authorize, journey, summary, diagnostics })`
1079
+ requires `authorize(): Promise<boolean>` before every method's source read.
1080
+ Refused callers receive `{ kind: "denied" }`; authorized delegates preserve
1081
+ arguments, results, nulls and thrown failures. The reference binding supplies
1082
+ that authorization once per call, before opening either support scope.
1083
+
1084
+ The [account/support reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#account-and-support-contracts)
1085
+ owns the available R1 boundary and later-phase limits.
1086
+
1087
+
1088
+ R3 adds `createSelfServiceCommandFacade({ context, capabilities, ...lanes })`,
1089
+ returning `SelfServiceCommandFacade` with required host capabilities and every
1090
+ managedSubscription, nativeLegacySubscription, subscriptionControl, typed/raw,
1091
+ profile, paymentMethod, commerce and recovery output lane. Input lanes are optional.
1092
+ Unselected methods return `{ supported: false, refusalCode }`; paymentMethod uses
1093
+ the host paymentMethodSetup refusal by identity, commerce uses commerceRecovery,
1094
+ and other lanes use a frozen host_binding_required refusal. Every lane guards
1095
+ the principal; typed/raw lanes require a supplied clientId equal to context.clientId.
1096
+ The trailing `ControlSnapshot = unknown` generic retains the control snapshot type.
1097
+ Native legacy routing preserves
1098
+ explicit pause and ownership before bundle quote validation. Owner results,
1099
+ refusals and nulls retain identity. Supported paymentMethodSetup requires a
1100
+ paymentMethod lane; supported commerceRecovery/configuredPurchase require commerce.
1101
+ Supported genericBundleCommands/commandBoundReceipts require a selected subscription
1102
+ command lane. Missing required lanes refuse customer_self_service_lane_configuration_required.
1103
+ `encodeNativeSubscriptionCommand`, `decodeNativeSubscriptionPreview` and
1104
+ `createNativeSubscriptionDriver` retain the raw owner protocol and apply key;
1105
+ apply never previews. `createPaymentMethodComposition` adapts generic M07
1106
+ setupMethod to paymentMethod.execute without owner imports. Native repair is a
1107
+ [registered follow-up](../../docs/platform/plans/oss-m12-account-support.md#follow-up-register).
1108
+ The default-off reference binding mounts nothing; browser key retention and
1109
+ native profile/start remain unselected.
1110
+
1111
+
1112
+ R4 adds `createOperatorRecovery`, `createManagedOperatorAuthority`,
1113
+ `createPostgresOperatorAuthority`, `operatorAuthorityCapabilities`,
1114
+ `moveIdentityForEmailCorrection`, `executeOperatorAccountLink`, `linkThenApply`
1115
+ and `ACCOUNT_SUPPORT_MIGRATIONS`. The host injects its transaction/RPC and identity
1116
+ ports, verified human operator and recovery-path policy. Recovery token generation
1117
+ and SHA-256 hashing use the runtime Web Crypto API without a Node import; the
1118
+ host may still inject its opaque-token generator. Managed email admission
1119
+ and claim precede identity mutation and settlement. Native lifecycle commands
1120
+ delegate to M10, with actual optional owner receipts and named unavailable
1121
+ subcases. Link-then-action reports a completed link separately when the second
1122
+ command refuses or fails. The reference binding is default-off and unmounted;
1123
+ no import provisions authority or activates a route.
1124
+
1125
+ R5a adds `createAccountSupportBindings` and `createAccountSupportServices` here,
1126
+ and `createAccountSupportContribution` in `/composition`. Supply already bound
1127
+ R1–R4/owner operations for one explicit managed/native graph, host capabilities
1128
+ and a readiness observer. Each distinct callable receives one guard shared by
1129
+ its service, port and route aliases; each entrance re-observes readiness. Disabled
1130
+ construction calls no observer. Refusals are `disabled`, `schema_unknown` and
1131
+ `schema_unsatisfied`; owner results and thrown failures pass through unchanged.
1132
+ A null selected operation remains a required port without an executable binding.
1133
+ The separate injected commerce record uses `commerce(key, ...args)` and returns
1134
+ `{ kind: "unsupported", code: "host_binding_required" }` for a null record/member.
1135
+ The reference host may select real M11 checkout/recovery, ATP and existing effect
1136
+ descriptors by supplying its already-built selection through `commerceOwner`
1137
+ and its existing registry through `commerceRegistry`. R5b does not construct M11
1138
+ or import its adapters; the host supplies the complete account/M11/ATP schema
1139
+ and matching enablement/readiness. Keep capability flags unsupported until
1140
+ their owner callables are bound. This adds no package export or owner import to
1141
+ account-support contracts. One M11 result is forwarded without rewrapping its
1142
+ guarded services; unknown stock, unsupported options and handler outcomes retain
1143
+ their owner meaning. Contribution descriptors install no routes, handlers,
1144
+ schedules or workers. See the
1145
+ [reference recipe](../../docs/platform/RUNTIME_AND_SELF_HOSTING.md#opt-in-disposable-subscription-reference)
1146
+ for the host's schema and transport obligations.
@@ -0,0 +1,8 @@
1
+ import type { AccountReadPort } from "./contracts/index.js";
2
+ /** Pure delegation to selected owner reads. Authorization, defaults, diagnostics,
3
+ * private fields and transport refusal mapping remain with the injected owners.
4
+ */
5
+ export declare function createAccountReadFacade<Account, OrderList, OrderDetail>(ports: {
6
+ account: Pick<AccountReadPort<Account, OrderList, OrderDetail>, "getAccount">;
7
+ orders: Pick<AccountReadPort<Account, OrderList, OrderDetail>, "listOrders" | "getOrderDetail">;
8
+ }): AccountReadPort<Account, OrderList, OrderDetail>;
@@ -0,0 +1,10 @@
1
+ /** Pure delegation to selected owner reads. Authorization, defaults, diagnostics,
2
+ * private fields and transport refusal mapping remain with the injected owners.
3
+ */
4
+ export function createAccountReadFacade(ports) {
5
+ return {
6
+ getAccount(userId) { return ports.account.getAccount(userId); },
7
+ listOrders(userId, input) { return ports.orders.listOrders(userId, input); },
8
+ getOrderDetail(userId, orderId) { return ports.orders.getOrderDetail(userId, orderId); },
9
+ };
10
+ }
@@ -0,0 +1,69 @@
1
+ import type { AccountActionRequired, AccountSnapshot, AccountSubscription, AccountSubscriptionLine, AccountOrderSummary } from "./contracts/account.js";
2
+ import type { SubscriptionPaymentMethodStatus } from "./contracts/commands.js";
3
+ export declare const CUSTOMER_ACCOUNT_V2_CONTRACT_VERSION: "customer.account.v3";
4
+ type Row = Record<string, unknown>;
5
+ export interface CustomerSubscriptionEligibilityInput {
6
+ subscriptionId: string;
7
+ status: AccountSubscription["status"];
8
+ nextCycleAt: string | null;
9
+ editCutoffAt: string | null;
10
+ paymentMethodKind: string | null;
11
+ paymentMethodRefPresent: boolean;
12
+ paymentMethodStatus?: SubscriptionPaymentMethodStatus;
13
+ }
14
+ export interface CustomerSubscriptionEligibility {
15
+ canEdit: boolean;
16
+ reason: AccountSubscription["editBlockedReason"];
17
+ }
18
+ export interface SubscriptionActionState {
19
+ subscriptionId: string;
20
+ orderId: string | null;
21
+ blockedReason: AccountActionRequired["blockedReason"];
22
+ failureCause: AccountActionRequired["failureCause"];
23
+ recoveryEligible: boolean;
24
+ dueAt: string | null;
25
+ nextRetryAt: string | null;
26
+ }
27
+ export interface AccountReadSources<Extension, ChargeEvidence = AccountSubscription["nextCharge"], PaymentEvidence = unknown> {
28
+ readExtension(clientId: string): Promise<Extension>;
29
+ /** The selected store applies the bound BEFORE visibility filtering. */
30
+ readSubscriptionRows(clientId: string, limit: number): Promise<Row[]>;
31
+ readAddresses(clientId: string): Promise<AccountSnapshot["addresses"]>;
32
+ readOrdererProfiles(clientId: string): Promise<AccountSnapshot["ordererProfiles"]>;
33
+ readPaymentPreferences(clientId: string): Promise<AccountSnapshot["paymentPreferences"]>;
34
+ readDeliveryPreferences(clientId: string): Promise<AccountSnapshot["deliveryPreferences"]>;
35
+ readOrders(clientId: string, limit: number): Promise<{
36
+ orders: AccountOrderSummary[];
37
+ }>;
38
+ readEvents(clientId: string): Promise<AccountSnapshot["events"]>;
39
+ readSubscriptionLines(ids: string[]): Promise<Map<string, AccountSubscriptionLine[]>>;
40
+ readSubscriptionBlockers(ids: string[], nextCycles: Map<string, string | null>): Promise<Map<string, NonNullable<AccountSubscription["editBlockedReason"]>>>;
41
+ readPauseWindows(ids: string[]): Promise<Map<string, Pick<AccountSubscription, "pausePreset" | "pauseStartedAt" | "pauseEndsAt">>>;
42
+ readPaymentEvidence(ids: string[]): Promise<Map<string, PaymentEvidence>>;
43
+ /** Owner interprets M08 refusal; unsupported MUST throw, never return an empty Map. */
44
+ readDeliveryAlignments(nextCycles: Map<string, string | null>): Promise<Map<string, {
45
+ state: "protected" | "aligned";
46
+ }>>;
47
+ readNextCharges(rows: Row[]): Promise<Map<string, ChargeEvidence>>;
48
+ readActionStates(ids: string[]): Promise<Map<string, SubscriptionActionState>>;
49
+ }
50
+ export interface AccountReadProjectionPolicy<ChargeEvidence = AccountSubscription["nextCharge"], PaymentEvidence = unknown> {
51
+ paymentMethodStatus(input: {
52
+ clientId: string;
53
+ clientEmail: string | null;
54
+ row: Row;
55
+ evidence: PaymentEvidence | undefined;
56
+ }): SubscriptionPaymentMethodStatus;
57
+ canUsePaymentMethodForRenewal(status: SubscriptionPaymentMethodStatus): boolean;
58
+ packageSummary(lines: AccountSubscriptionLine[], constraint: unknown): string | null;
59
+ /** Pricing authority selects payable-cycle/acquisition shipping precedence. */
60
+ withNextCharge(recurring: AccountSubscription["recurringPrice"], next: ChargeEvidence | undefined): Pick<AccountSubscription, "recurringPrice" | "nextCharge">;
61
+ }
62
+ /** Two observation stages, including the original nested subscription fan-out. Auth/ownership precedes this call. */
63
+ export declare function readAccountSnapshot<Extension, ChargeEvidence, PaymentEvidence>(sources: AccountReadSources<Extension, ChargeEvidence, PaymentEvidence>, policy: AccountReadProjectionPolicy<ChargeEvidence, PaymentEvidence>, client: Row): Promise<AccountSnapshot<Extension>>;
64
+ export declare function isCustomerVisibleSubscription(row: Row): boolean;
65
+ export declare function recurringPrice(lines: AccountSubscriptionLine[]): AccountSubscription["recurringPrice"];
66
+ export declare function editCutoff(nextCycleAt: string | null, editWindowHours: number | null): string | null;
67
+ export declare function computeEditState(input: CustomerSubscriptionEligibilityInput, blockers: ReadonlyMap<string, NonNullable<AccountSubscription["editBlockedReason"]>>, canUse: AccountReadProjectionPolicy["canUsePaymentMethodForRenewal"]): CustomerSubscriptionEligibility;
68
+ export declare function buildActionRequired(subscriptions: AccountSubscription[], orders: AccountOrderSummary[], states: Map<string, SubscriptionActionState> | undefined, canUse: AccountReadProjectionPolicy["canUsePaymentMethodForRenewal"]): AccountActionRequired[];
69
+ export {};