@openlup/platform 0.23.0 → 0.25.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 (165) hide show
  1. package/CHANGELOG.md +327 -269
  2. package/README.md +123 -12
  3. package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +3 -2
  4. package/dist/communications/contracts/subscriptionPaymentExpired.js +1 -1
  5. package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +4 -3
  6. package/dist/communications/contracts/subscriptionPaymentFailed.js +4 -5
  7. package/dist/composition/index.d.ts +1 -0
  8. package/dist/composition/index.js +1 -0
  9. package/dist/composition/subscriptionContribution.d.ts +18 -0
  10. package/dist/composition/subscriptionContribution.js +19 -0
  11. package/dist/fulfillment/contracts/dispatch.d.ts +4 -0
  12. package/dist/fulfillment/dispatchProjection.d.ts +1 -1
  13. package/dist/fulfillment/dispatchProjection.js +4 -2
  14. package/dist/fulfillment/omnipack/client.js +14 -6
  15. package/dist/fulfillment/omnipack/index.js +5 -2
  16. package/dist/fulfillment/providerDispatchWorker.d.ts +38 -0
  17. package/dist/fulfillment/providerDispatchWorker.js +19 -1
  18. package/dist/inventory/index.d.ts +2 -0
  19. package/dist/inventory/index.js +1 -0
  20. package/dist/inventory/postgresStockAvailability.d.ts +24 -0
  21. package/dist/inventory/postgresStockAvailability.js +48 -0
  22. package/dist/invoicing/accountingCanonicalProviderLines.d.ts +5 -0
  23. package/dist/invoicing/accountingCanonicalProviderLines.js +104 -0
  24. package/dist/invoicing/accountingLineAllocation.d.ts +2 -0
  25. package/dist/invoicing/accountingLineAllocation.js +69 -0
  26. package/dist/invoicing/adapterConformance.d.ts +42 -0
  27. package/dist/invoicing/adapterConformance.js +296 -0
  28. package/dist/invoicing/artifacts.d.ts +7 -0
  29. package/dist/invoicing/artifacts.js +20 -0
  30. package/dist/invoicing/bindings.d.ts +46 -0
  31. package/dist/invoicing/bindings.js +69 -0
  32. package/dist/invoicing/channelPolicy.d.ts +28 -0
  33. package/dist/invoicing/channelPolicy.js +27 -0
  34. package/dist/invoicing/continuity.d.ts +12 -0
  35. package/dist/invoicing/continuity.js +18 -0
  36. package/dist/invoicing/contracts/facts.d.ts +11 -1
  37. package/dist/invoicing/contracts/host.d.ts +3 -4
  38. package/dist/invoicing/contracts/index.d.ts +1 -1
  39. package/dist/invoicing/contracts/store.d.ts +15 -5
  40. package/dist/invoicing/contribution.d.ts +21 -0
  41. package/dist/invoicing/contribution.js +19 -0
  42. package/dist/invoicing/correction.d.ts +42 -0
  43. package/dist/invoicing/correction.js +44 -0
  44. package/dist/invoicing/delivery.d.ts +85 -0
  45. package/dist/invoicing/delivery.js +79 -0
  46. package/dist/invoicing/documentHistory.d.ts +50 -0
  47. package/dist/invoicing/documentHistory.js +213 -0
  48. package/dist/invoicing/documentSync.d.ts +24 -0
  49. package/dist/invoicing/documentSync.js +26 -0
  50. package/dist/invoicing/dutyCollector.d.ts +15 -0
  51. package/dist/invoicing/dutyCollector.js +35 -0
  52. package/dist/invoicing/fulfillmentTrigger.d.ts +56 -0
  53. package/dist/invoicing/fulfillmentTrigger.js +90 -0
  54. package/dist/invoicing/handoff.d.ts +37 -0
  55. package/dist/invoicing/handoff.js +62 -0
  56. package/dist/invoicing/index.d.ts +38 -0
  57. package/dist/invoicing/index.js +36 -0
  58. package/dist/invoicing/issue.d.ts +39 -0
  59. package/dist/invoicing/issue.js +55 -0
  60. package/dist/invoicing/migrations.d.ts +48 -0
  61. package/dist/invoicing/migrations.js +25 -0
  62. package/dist/invoicing/nativeUnsupported.d.ts +9 -0
  63. package/dist/invoicing/nativeUnsupported.js +22 -0
  64. package/dist/invoicing/paymentReadback.d.ts +20 -0
  65. package/dist/invoicing/paymentReadback.js +47 -0
  66. package/dist/invoicing/postgresInvoiceStore.d.ts +55 -0
  67. package/dist/invoicing/postgresInvoiceStore.js +344 -0
  68. package/dist/invoicing/readModel.d.ts +74 -0
  69. package/dist/invoicing/readModel.js +90 -0
  70. package/dist/invoicing/readback.d.ts +4 -0
  71. package/dist/invoicing/readback.js +30 -0
  72. package/dist/invoicing/reversal.d.ts +37 -0
  73. package/dist/invoicing/reversal.js +28 -0
  74. package/dist/invoicing/sellerRevision.d.ts +19 -0
  75. package/dist/invoicing/sellerRevision.js +14 -0
  76. package/dist/invoicing/settlementSync.d.ts +18 -0
  77. package/dist/invoicing/settlementSync.js +32 -0
  78. package/dist/invoicing/snapshot.d.ts +52 -0
  79. package/dist/invoicing/snapshot.js +141 -0
  80. package/dist/subscriptions/commandExamples.d.ts +6 -0
  81. package/dist/subscriptions/commandExamples.js +20 -0
  82. package/dist/subscriptions/contracts/commands.d.ts +8 -1
  83. package/dist/subscriptions/contracts/index.d.ts +2 -2
  84. package/dist/subscriptions/contracts/stockWait.d.ts +12 -1
  85. package/dist/subscriptions/index.d.ts +22 -4
  86. package/dist/subscriptions/index.js +22 -3
  87. package/dist/subscriptions/lifecycleMessages.d.ts +9 -0
  88. package/dist/subscriptions/lifecycleMessages.js +38 -0
  89. package/dist/subscriptions/paymentOutcomes.js +1 -1
  90. package/dist/subscriptions/postgresCommandStore.d.ts +44 -0
  91. package/dist/subscriptions/postgresCommandStore.js +172 -0
  92. package/dist/subscriptions/postgresRetryStore.d.ts +6 -0
  93. package/dist/subscriptions/postgresRetryStore.js +11 -0
  94. package/dist/subscriptions/postgresStockWaitStore.d.ts +62 -0
  95. package/dist/subscriptions/postgresStockWaitStore.js +174 -0
  96. package/dist/subscriptions/services.d.ts +31 -0
  97. package/dist/subscriptions/services.js +15 -0
  98. package/package.json +3 -3
  99. package/release-gates.json +21 -7
  100. package/sql/20260809210000_accounting_document_rail.sql +889 -0
  101. package/sql/20260811150000_accounting_payout_rail.sql +333 -0
  102. package/sql/20260812130000_accounting_document_lifecycle_rail.sql +460 -0
  103. package/sql/20261022190000_invoicing_durable_duties.sql +494 -0
  104. package/sql/20261022191000_invoicing_document_effects.sql +249 -0
  105. package/sql/20261022192000_invoicing_payment_decoupling.sql +144 -0
  106. package/sql/20261022195000_invoicing_seller_revision.sql +65 -0
  107. package/sql/20261024170000_subscription_command_lifecycle.sql +404 -0
  108. package/sql/20261024180000_subscription_stock_wait.sql +330 -0
  109. package/sql/20261024183000_inventory_available_to_promise.sql +70 -0
  110. package/sql/20261024184000_subscription_renewal_reserve_uses_seam.sql +147 -0
  111. package/sql/20261024184500_subscription_retry_late_positive_stock.sql +59 -0
  112. package/sql/20261024184600_subscription_retry_candidate_payment_filter.sql +22 -0
  113. package/src/communications/contracts/subscriptionPaymentExpired.ts +4 -3
  114. package/src/communications/contracts/subscriptionPaymentFailed.ts +8 -8
  115. package/src/composition/index.ts +1 -0
  116. package/src/composition/subscriptionContribution.ts +25 -0
  117. package/src/fulfillment/contracts/dispatch.ts +4 -0
  118. package/src/fulfillment/dispatchProjection.ts +4 -2
  119. package/src/fulfillment/omnipack/client.ts +13 -6
  120. package/src/fulfillment/omnipack/index.ts +5 -2
  121. package/src/fulfillment/providerDispatchWorker.ts +14 -1
  122. package/src/inventory/index.ts +2 -0
  123. package/src/inventory/postgresStockAvailability.ts +54 -0
  124. package/src/invoicing/accountingCanonicalProviderLines.ts +134 -0
  125. package/src/invoicing/accountingLineAllocation.ts +69 -0
  126. package/src/invoicing/adapterConformance.ts +249 -0
  127. package/src/invoicing/artifacts.ts +19 -0
  128. package/src/invoicing/bindings.ts +80 -0
  129. package/src/invoicing/channelPolicy.ts +50 -0
  130. package/src/invoicing/continuity.ts +15 -0
  131. package/src/invoicing/contracts/facts.ts +12 -1
  132. package/src/invoicing/contracts/host.ts +3 -4
  133. package/src/invoicing/contracts/index.ts +1 -1
  134. package/src/invoicing/contracts/store.ts +11 -7
  135. package/src/invoicing/contribution.ts +28 -0
  136. package/src/invoicing/correction.ts +56 -0
  137. package/src/invoicing/delivery.ts +122 -0
  138. package/src/invoicing/documentHistory.ts +301 -0
  139. package/src/invoicing/documentSync.ts +51 -0
  140. package/src/invoicing/dutyCollector.ts +31 -0
  141. package/src/invoicing/fulfillmentTrigger.ts +144 -0
  142. package/src/invoicing/handoff.ts +71 -0
  143. package/src/invoicing/index.ts +38 -0
  144. package/src/invoicing/issue.ts +64 -0
  145. package/src/invoicing/migrations.ts +25 -0
  146. package/src/invoicing/nativeUnsupported.ts +24 -0
  147. package/src/invoicing/paymentReadback.ts +70 -0
  148. package/src/invoicing/postgresInvoiceStore.ts +334 -0
  149. package/src/invoicing/readModel.ts +80 -0
  150. package/src/invoicing/readback.ts +26 -0
  151. package/src/invoicing/reversal.ts +34 -0
  152. package/src/invoicing/sellerRevision.ts +20 -0
  153. package/src/invoicing/settlementSync.ts +37 -0
  154. package/src/invoicing/snapshot.ts +192 -0
  155. package/src/subscriptions/commandExamples.ts +19 -0
  156. package/src/subscriptions/contracts/commands.ts +35 -2
  157. package/src/subscriptions/contracts/index.ts +2 -2
  158. package/src/subscriptions/contracts/stockWait.ts +14 -2
  159. package/src/subscriptions/index.ts +30 -3
  160. package/src/subscriptions/lifecycleMessages.ts +37 -0
  161. package/src/subscriptions/paymentOutcomes.ts +1 -1
  162. package/src/subscriptions/postgresCommandStore.ts +183 -0
  163. package/src/subscriptions/postgresRetryStore.ts +11 -0
  164. package/src/subscriptions/postgresStockWaitStore.ts +170 -0
  165. package/src/subscriptions/services.ts +21 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,333 @@ in the source repository.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.25.0]
14
+
15
+ - Publishable on the npm `latest` dist-tag as `0.25.0`, from tag
16
+ `openlup-platform-v0.25.0`.
17
+
18
+ - Re-pin the pending M10/F17 control fixtures after landed M08/M09 without
19
+ changing either installation rail, the migration manifest or landed N1. The
20
+ 16-entry packet has seven native and nine managed pins. Native X restores
21
+ ATP-counted late-positive stock recovery; Y filters paid retry candidates
22
+ before LIMIT. Fold command-preview receipt replay into uninstalled N2, keeping
23
+ apply unchanged. Preserve the historical 14-pin approval reader and exact
24
+ prefix, definition, statement, ACL and catalog controls. Real PostgreSQL
25
+ witnesses cover ATP, starvation, all 43 fresh command scenarios and raw preview
26
+ replay with no counts/columns/xmin delta.
27
+
28
+ No package SQL asset, export, runtime activation or external CI dependency is
29
+ introduced. The development-preview boundary remains.
30
+
31
+ - Fix uninstalled N3 normal_due pagination to exclude waiting/stock_secured cases before LIMIT, preventing normal-renewal starvation.
32
+
33
+ - 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.
34
+
35
+ - Audit pending M10 donor change and no-op semantics together. N2 plan edits
36
+ apply requested core lines; new add-ons normalize quantity, preserve cadence
37
+ and compare UUIDs by value. N3 preserves paused waits, filters eligible recovery
38
+ before LIMIT, binds frozen reads to the current active schedule, reports free
39
+ stock separately from own holds, and ignores closed/unpaid realization notices.
40
+ Real PostgreSQL tables cover applied state, no-op/refusal/replay and rolled-back
41
+ assignment mutants. Installed rails and N2 apply remain unchanged; channel
42
+ exposure/admission parity stays outside the frozen stock-seam claim.
43
+
44
+ - Close the 0.24.0 known limitation that managed dunning exhaustion still pauses active subscriptions.
45
+ - 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.
46
+ - 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.
47
+ - Folded scope D-earlier-pin-digest-unplanted: prove CI and release refuse changed earlier M1 bytes beneath landed M2.
48
+
49
+ 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.
50
+
51
+ - 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.
52
+ - 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`.
53
+
54
+ 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.
55
+
56
+ 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.
57
+
58
+ Migration: `SubscriptionCommandPort.apply()` may now return `SubscriptionCommandRefusal` (`outcome: "refused"`), so callers must handle it.
59
+
60
+ - Type-level change visible to dev-preview consumers: `RenewalPaymentRail.execute` adds an optional `failure` field for explicit failure evidence.
61
+ - 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.
62
+ - 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.
63
+
64
+ Land the seven reviewed managed stock-wait/ATP and F17 refund-parity forwards.
65
+ Managed hosts can use the service-role SQL functions and pgTAP witnesses; the
66
+ package declares the SQL surface and keeps TypeScript stock recovery unavailable
67
+ because no managed adapter implements the stock-wait/availability ports.
68
+
69
+ Migration: apply the complete managed prefix through `20261024185100` before
70
+ calling stock-wait or refund-evidence functions. M4 extends M2's active/open
71
+ continuity with wait exclusion before LIMIT. M5 makes positive customer
72
+ cancellations immediately winback-eligible within 120 days, retaining episode
73
+ dedupe, and maps started/resumed notices. F17 accepts cumulative provider snapshots,
74
+ emits one refunded event on transition, and preserves M1 refund/lifecycle
75
+ independence. Keep captured obligations and receipts on rollback and disable the
76
+ host stock-wait driver first. SQL installs no scheduler or payment executor.
77
+
78
+ ATP protects active upcoming demand within 14 days plus live provider hard holds.
79
+ The exposure hook remains zero; current donor channel admission is deferred.
80
+ This is a development-preview SQL surface, not a composed managed TypeScript port
81
+ or a claim of advance future-cycle reservations or stable installation support.
82
+
83
+ Native stock-wait persistence, frozen discovery and stock-only refusal recovery
84
+ now have transaction-bound adapters. The native ATP/new-purchase read protects
85
+ hard holds and fixed 14-day soft subscription demand; the renewal allocator uses
86
+ the same seam. X restores late-paid released stock once, and Y filters paid and
87
+ settled retry obligations before LIMIT. Managed stock wait and runner composition
88
+ remain separate; native selection still requires passing real-PostgreSQL proof.
89
+
90
+ Migration: install the native N3, ATP seam, allocator, X and Y prefix in filename
91
+ order, with their package twins and regenerated selected-catalog-v2 inventory.
92
+ Migration: upgrading hosts must grant their native inventory-reserving runtime
93
+ role EXECUTE on public.inventory_available_to_promise(text,text,timestamptz,boolean)
94
+ and public.inventory_channel_exposure_quantity(text,text), plus SELECT on the
95
+ seam's underlying relations as listed in Data and migrations, before using the
96
+ updated allocator or N3 stock-wait paths.
97
+ `StockWaitStorePort.listCandidates` now returns `StockWaitFrozenCase[]`: discovery
98
+ may have no durable case yet. Hosts must retain its frozen snapshot and binding.
99
+ Frozen discovery requires the active current schedule; paused current waits remain open.
100
+ Deficits separate own reserved units from free ATP and subtract both for missing
101
+ units. Closed or pending-payment resume callbacks return null without writes; paid
102
+ fulfillment-pending orders can complete realization admission.
103
+ No advance reservation, physical coverage guarantee or one-time checkout writer
104
+ is introduced. No pause, payment execution or parcel-arrival fact is added.
105
+ Uncaptured stock refusals rotate on the operation selection timestamp even when
106
+ missing or stale stock prevents case creation, allowing replenished work through
107
+ a bounded candidate page.
108
+
109
+ M10 P6 + P8: composed subscriptions (development preview)
110
+
111
+ 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.
112
+ 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.
113
+ 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.
114
+
115
+ The inert native reference binding composes mandatory G23, dunning and stock wait.
116
+ Captured alignment cases retain authority under off. Prepared attempts reconcile
117
+ without re-execution; ordinary retries bind the frozen mandate and logical cycle.
118
+ M04 owns delivery; M12 owns aggregation. No SQL asset, serving swap, release or
119
+ managed TypeScript recovery is introduced. Native multi-cycle prepaid and M07
120
+ prepared-attempt-store capabilities retain their named unsupported boundaries.
121
+
122
+ ## [0.24.0]
123
+
124
+ - Publishable on the npm `latest` dist-tag as `0.24.0`, from tag
125
+ `openlup-platform-v0.24.0`.
126
+
127
+ - Require Zod `^4.6.6` to fix GHSA-mrhx-c7xc-m3w5; oversized constrained
128
+ request collections fail before element validation accumulates errors.
129
+ - Preserve the observation adapter's accepted minute-precision occurrence timestamps and raw
130
+ idempotency-key bytes with the updated validator; impossible dates still fail.
131
+
132
+ - Add the optional `runFulfillmentDispatchWorker.shadowCommandFingerprint` callback for a pure, local adopter command hash in shadow mode. Without it, shadow evidence still hashes the same `JSON.stringify(request)` bytes with SHA-256. The callback must return a lowercase 64-hex SHA-256 digest of the adopter's canonical command bytes, never command contents, credentials or contact data. The package accepts only strings matching `/^[a-f0-9]{64}$/`; invalid output or a throw returns a typed refusal with closed cause `adopter_fingerprint_invalid` or `adopter_fingerprint_failed`, without raw output, exception text or claim/attempt/evidence writes. Stage/live never invoke the callback. The fingerprint is used across shadow claim/readback/attempt, including mapped-attempt replay; shadow never begins, and live preparation must produce the same identity; shadow still performs no provider preparation, credentials lookup or POST.
133
+ - Preserve optional boolean `submissionAttempted` and `responseBodyRead` facts on typed dispatch errors and finalize evidence. `submissionAttempted: false` proves no provider submission was attempted; absence is unknown. `responseBodyRead: true` means the response body was read, including empty or malformed JSON; `false` means reading failed, and absence means there is no body-read evidence. Credential/request-construction failures include explicit non-submission proof; command validation/rebuild retains its closed `not_dispatchable` refusal. No raw body, exception prose or credentials enter these facts; durable projections admit only actual booleans.
134
+
135
+ Migration: existing callers need no changes. `shadowDispatchEvidence(request)` becomes `shadowDispatchEvidence(request, commandFingerprint?)`; omitting the new optional argument keeps the same evidence bytes and hash. These facts allow adopter classification without inferring uncertainty from retryability. Package classification remains unchanged: definitive rejections (including an unreadable HTTP 400 body) are `not_dispatched`; ambiguous submission and unreadable successful acknowledgements are `unknown`. No release, default binding, route, schedule or activation is added.
136
+
137
+ - Add inert native unsupported invoicing ports and runner-independent offline adapter conformance for exact recovery, parent identity, scoped absence, declared host capabilities and safe evidence.
138
+ - Document the invoicing design and host boundaries without installing workers, stores, fiscal providers, routes or activation.
139
+
140
+ - Extract invoice issue sequencing, snapshot/canonical line verification, unchanged allocation, payment evidence and handoff helpers into the existing invoicing entry; retain host payloads, keys, seller/tax policy and routing.
141
+ - Migration: compatibility callbacks preserve existing RPC/provider request bytes, issue fences and handoff descriptors. No native store, D7/O2 behavior, default provider, executor registration or activation is added.
142
+
143
+ - Add correction and reversal workers to the experimental invoicing entry, preserving durable correction identity, recovery, host event/key semantics and fenced outcomes. The reference host requires an explicit conforming correction bridge; its legacy vendor copy stays unchanged and unselected.
144
+ - Migration: introduce the two pinned managed v2/compatibility forwards with versioned adapter and pgTAP callers. Unkeyed attempted legacy corrections remain visibly unresolved for provider reconciliation. Preview correction references use correctionRef. Native forwards and runtime activation remain separate.
145
+ - See the [M09 forward owner](../../docs/platform/DATA_AND_MIGRATIONS.md#m09-invoicing-forward-design-and-control-approval) for sync-first settlement and permanent-failure parking.
146
+ - Registered limit: multi-reason / late-issue compensation can yield more than one full correction per invoice, as the incumbent does today.
147
+
148
+ - Add an experimental structural-executor native invoice store, a create/readback issue binding, separate native/managed migration descriptors, and six byte-identical sparse SQL assets. Read-only bounded discovery exposes duty/order IDs before facts are installed. Missing host fiscal facts refuse before writes; local-only document construction retains its previous behavior. Native fresh non-ready preflights settle before dispatch; stale preflight/finalizer results write no failure.
149
+ - Migration: append the three reviewed native duty/effect/payment forwards at positions 77–79 after the unchanged 160000/165000 prefix. Install the complete catalogue. Native child-document and managed base-row corrections have distinct descriptors. Seller revision and activation remain separate.
150
+
151
+ ### Independent native invoicing duties
152
+
153
+ Experimental invoicing adds `collectInvoiceDuties` and
154
+ `createIndependentInvoiceDutyBinding` for explicitly invoked, separately committed
155
+ duty collection. Native fulfillment no longer waits for accounting readiness or
156
+ invoice requests. Managed dispatch behavior stays unchanged.
157
+
158
+ Install the full native catalogue, including 190000/191000 before the exact
159
+ reviewed 192000 payment-decoupling forward. Captured settlement and dunning
160
+ recovery survive invoice capture failure; retained paid/handoff facts support
161
+ later repair. New unlinked payment events retain `accountingRequested=false`,
162
+ including after independent issue; historical linked events retain their readback.
163
+ Use owed-duty readback for invoice progress. No payment
164
+ export, provider activation, scheduler registration or fiscal default is added.
165
+
166
+ - Extract invoice delivery, PDF validation, accepted-document synchronization, payout item recording and document-history/read helpers into the existing invoicing entry; bind the reference host facades through explicit callbacks.
167
+ - Migration: F8 retains A2 payout transport and exact settlement keys; the legacy batch/payment importer preserves donor calls and aggregate results, while package receipt reuse across item scopes is an identity conflict with continued processing and no extra write; distinct recorded receipts require an item-capable host recorder/resolver. F11 retains M04 content, recipient, locale, transport and uncertainty. F9 bounds reference consumers; F12 leaves runbooks and customer correction intent host-owned. Native delivery uses an optional host envelope projection over P4’s store; job store mode binds fenced terminal/backoff outcomes (whole seconds clamp 60..86400, absent/invalid 900, retryable:false parks); callback mode requires terminalFailure before claim; native history requires a safe owned projection. PDF downloads now refuse invalid bytes; the reference panel displays closed diagnostic codes without free-text provider errors. No SQL, activation, executor or fiscal-policy change.
168
+
169
+ Explicit invoicing composition and first-claim seller revision
170
+
171
+ PART A: `createInvoiceServices`, `InvoiceServices` and `createInvoiceContribution`
172
+ use the existing `/invoicing` entry. Host selection is default-off; readiness
173
+ precedes factories and claim. Native helpers compose the real P4/P5 store,
174
+ collection, delivery, sync and read-model implementations. Host-specific factories
175
+ retain auth, configuration, transport/query projection and the existing executor,
176
+ registry and lease. Targeted module runs refuse before leasing.
177
+
178
+ PART B — Migration: native 195000 and managed 195100 are forward-only,
179
+ byte-identical introductions of the approved CTL-M09-4 fixtures. Eligible
180
+ obligations freeze the seller at their first-ever durable claim, independently
181
+ for corrections; retries retain it. Previously claimed legacy obligations keep
182
+ execution-time fallback. Issued documents and installed buyer/line facts are
183
+ unchanged. Native reversals use the correction request branch; managed order
184
+ reversals preserve incumbent results through the seller request wrapper.
185
+ Unknown/unsupported seller reads and order-scoped managed corrections refuse
186
+ before claim. SQL replay conflicts surface as typed identity conflicts.
187
+
188
+ ### Selection and installation boundary
189
+
190
+ Invoicing remains EXPERIMENTAL and DEFAULT-OFF. The issue/correction/reversal,
191
+ durable duty collection, native store, delivery/document/payout sync, safe history
192
+ and first-claim seller revision helpers are available for explicit host composition.
193
+ Select a provider and capability, bind host ports and establish readiness before
194
+ factories or claim; the structural contribution registers nothing itself. Fiscal
195
+ policy, ownership/authentication, M04 transport, artifact/history projections,
196
+ execution leases and route/job registration remain host responsibilities. No live
197
+ provider, fiscal acceptance or inbox-delivery evidence is established. Adopters
198
+ must not activate unselected or unready invoicing, or infer activation from SQL.
199
+
200
+ M10 subscription renewal/retry stages remain EXPERIMENTAL, INCOMPLETE and
201
+ DEFAULT-OFF, not for adopter activation: contracts, native stores/executor and
202
+ N1 SQL are present, but runner activation and the G23/N1 host composition,
203
+ correlation, authorization and replay obligations remain pending. Native delivery
204
+ alignment must remain off or shadow until the host composes the renewal runner
205
+ with its G23 admission decorator.
206
+
207
+ Migration: upgrade core, outbox and platform together from `0.23.0` to `0.24.0`
208
+ for exact internal peers. Install the complete canonical native migration chain
209
+ through position 80 (`20261022195000_invoicing_seller_revision.sql`), including
210
+ invoicing positions 77/78/79 (`190000`/`191000`/`192000`); P5 adds no SQL and P7
211
+ adds position 80. Sparse package projections are not an installation chain.
212
+ Managed installations use their own ordered forwards, including correction
213
+ `193000`/`193100` and seller `195100`; managed descriptor paths are catalogue
214
+ references, not files installed by the npm tarball. Preserve first-claim seller
215
+ snapshots and legacy fallback; there is no retroactive backfill or reversal of
216
+ forward SQL on application rollback. Retain the `0.23.0` shadow/observation retry
217
+ and legacy stock-fingerprint migration precautions when upgrading older rows.
218
+
219
+ ### Limits closed by this set
220
+
221
+ - The earlier invoicing contract-only/no-SQL/no-worker surface limit is closed:
222
+ P1b–P7 introduce explicit services, native store and helpers, with CTL-M09-1–4
223
+ reviewed forwards at native positions 77–80 and the managed correction/seller
224
+ forwards; see the [design boundary](../../docs/platform/plans/oss-m09-invoicing.md#p7-composition-and-seller-revision).
225
+ Default activation and live fiscal/provider acceptance remain unclaimed.
226
+ - M08 stock-evidence replay/reopen was already closed in `0.23.0` by position 76;
227
+ this set does not close its legacy fingerprint conflict or other M08 gaps.
228
+
229
+ ### Known limitations
230
+
231
+ - Managed dunning exhaustion still pauses active subscriptions; retaining active status needs a managed forward. Native N1 lands the bounded retry/failure repair, with the host obligations below still pending.
232
+ - D8-1: native advisory v2 promo-code candidates/rejection details unavailable.
233
+ - D8-2: native mounted v2 issue/honor/fallback unavailable.
234
+ - D8-3: native acquisition-only mounted issuance/honor unavailable.
235
+ - D8-4: full native/managed eligibility equivalence unavailable.
236
+ - Bundle-1: independent DB human-only actor-kind enforcement absent natively; first in the native-backend parity round.
237
+ - Bundle-2: managed-equivalent actor-kind/email history absent natively.
238
+ - Bundle-3 closes injected-reader M05 mounted admin/feed readback only. Native new-purchase stock read absent despite P5a installed-store proof; deferred second after bundle-1 (owner 2026-10-21); readiness refuses.
239
+ - Bundle-4: incumbent real-PostgreSQL contention only; no exactly-once guarantee.
240
+ - Managed schema/pgTAP retain `44.404`; removal needs owner decision/forward; reference composition supplies it to app code.
241
+ - A1 offline only; account/hosted-time/owner TEST evidence unclaimed; `communications/klaviyo` verification-pending.
242
+ - M05 omitted opt-ins preserve defaults/outputs/read order/schedules/refusals/acceptance-token bytes/SQL.
243
+ - Native inventory adjustment unavailable; address writes refuse readiness. Flat-rate save needs selected port/Core readiness/applied-seed observation.
244
+ - Native shipping audit unavailable; handler swallows best-effort audit failure.
245
+ - Native flat-rate integer bounds (0 through host maximum; reference 100,000 minor units) use request schema, not DB CHECK.
246
+ - Managed ATP/forecast/dated-supply/pagination readback unproved/pending M06.
247
+ - Managed two-session locks/concurrency/uncovered compensation unproved/pending M06.
248
+ - Managed exact-prefix upgrade/ledger unproved/pending M06.
249
+ - Managed address idempotency/conflict/readback unproved/pending M06.
250
+ - Managed successful flat-rate read/save unproved/pending host authority.
251
+ - M06 stock-wait lifecycle/durable timing/staging controls retain C5/C6; busy/try-gate, continuity/flag/TTL transfers are dispositions, not PASS.
252
+ - Shipping national-registry fields/locale-specific `canonicalAddressKey` fold await M16 host market pack/key migration; reference shipping copy stays locale-specific until M16.
253
+ - Native durable prepared storage, method setup, absence reopen and cumulative refunds unavailable; no production installation parity claimed.
254
+ - Typed refusal-envelope forwarding unavailable (`failureReason` only); reusable registration needs host ownership resolution.
255
+ - Incomplete chargebacks stay refunds/unapplied: reclassification bypasses evidence validation into dispute apply; limited operator recovery.
256
+ - Audit compatibility still detects `chargeId`; refund operation identity/original money supply no typed charge identity.
257
+ - M07 follow-up: repair poll can clear host redirect; post-timeout verify never restarts polling; unlocalized poller; fixture builds/never calls handler.
258
+ - M07 follow-up: reference status route wrong-rail witness.
259
+ - M07 follow-up: explicit reference-route refusal for unsupported method setup.
260
+ - M07 follow-up: deployment-neutral disabled-verify reason.
261
+ - M07 follow-up: reference card normalizer missing-amount path; package settling evidence already requires positive money.
262
+
263
+ - Native delivery alignment stays off or shadow until a host composes the native automatic-renewal runner with the G23 renewal admission decorator. The decorator alone neither composes nor activates the runner.
264
+ - The core fulfillment status map carries localized adopter labels; replace them with host-injected labels or internationalization keys at the host presentation boundary.
265
+ - The warehouse adapter example is opt-in and has offline conformance only; no provider-account proof or activation is established. Exact absence, label create/void and cancellation remain unsupported.
266
+ - After an alignment extension, a deferred renewal operation at the old schedule remains claimed with no reader or reservation effect. Changed terms snapshots conflict under the existing snapshot-conflict rules.
267
+
268
+ Native parity remains host-owned at these seams. Missing native bindings use the shared `FULFILLMENT_NATIVE_UNSUPPORTED` refusal; no partial write or parity claim is implied.
269
+
270
+ | Amendment | Host-owned seam and native boundary |
271
+ | --- | --- |
272
+ | G18 | Replacement creation and atomic eligibility/replay receipts; native replacement callback refuses. |
273
+ | G19 | Operator mutations, actor attribution and replay receipts; native mutation callbacks refuse. |
274
+ | G20 | Customer alignment rows; native reader refuses, while the pure delay projection remains callable. |
275
+ | G21 | Commerce list/detail and shipments overview; native read callbacks refuse. |
276
+ | G22 | Authoritative preparation edits, authorization and replay receipts; missing preparation binding refuses before dispatch, after disabled/selection/readiness checks. |
277
+
278
+ - M08 parity D2 KEEP-GAP: native dispatch finish still loses rejected/unknown error detail.
279
+ - M08 parity KEEP-GAP: immutable stock snapshot/alert evidence storage is absent; cursor JSON is overwritten. Hosts retain referenced evidence.
280
+ - Stock-evidence replay/reopen is CLOSED by native position 76; legacy `0.22.0` alert fingerprints still conflict with `23505`, including after resolution.
281
+
282
+ ### Invoicing registered limitations
283
+
284
+ These are notes carried from the landed design, not fixes in this preparation.
285
+
286
+ - M07 `payment_truth_readback` still joins `accounting_documents`: operator
287
+ ACCESS EXCLUSIVE DDL or denied ACL can block/refuse the call. New unlinked
288
+ payment events remain `accountingRequested=false` after independent issue;
289
+ use owed-duty readback for invoice progress (PR #334).
290
+ - Managed multi-reason and late-issue compensation can create more than one full
291
+ correction per invoice. A later finalizer can be fenced `claim_inactive`, leaving
292
+ its row `processing`; failed/pending rows on already-corrected parents may never
293
+ be reclaimed. Reconcile provider identity/evidence, including unresolved attempted
294
+ legacy corrections. Broader reversal/manual arbitration needs a separately
295
+ designed replacement forward (PR #329, #330, #348).
296
+ - An in-flight issue can still compensate outside the seller wrapper with
297
+ `legacy_fallback`; latest-parent reselection retains incumbent behavior.
298
+ Managed keys are scoped to invoice/provider/reason, and delegated void stores
299
+ no key; native cross-order reuse refuses. Pre-wrapper native reversal-key
300
+ retries can conflict after wrapper evidence is added (PR #346, #348).
301
+ - Managed paid/handoff contention (`55P03`) is a visible retryable no-effect
302
+ refusal with no automatic adapter retry. Fail-soft dispatch can finish without
303
+ an invoice request; durable recreation can require operator recovery and delayed
304
+ shipped-without-invoice monitoring (PR #348).
305
+ - A bad host fiscal revision can refuse an entire scoped/provider batch. A null
306
+ payment `providerRef` falls back to the fiscal provider: hosts must supply explicit
307
+ payment identity. A failing `store.fail` aborts remaining leased work; retain
308
+ lease recovery and host retry handling (PR #334).
309
+ - Reversed-duty fact installation can still report owed: read authoritative
310
+ reversal/duty evidence, never treat that answer as permission to issue.
311
+ Unsupported reversal and parked document/request residues remain visible and
312
+ unclaimable; later fact installation/reversal retry can change their diagnostics
313
+ (PR #332, #334; design phase obligations).
314
+ - Native corrections ride the issue batch; a separate correction operation without
315
+ a host factory refuses `host_binding_required`. Unknown native seller selection
316
+ currently maps to non-retryable unsupported; hosts must handle recovery explicitly
317
+ (PR #348).
318
+ - Delivery visibility must exceed transport timeout. Fenced settlement, database
319
+ failure or lease expiry can abort a batch and leave unsent leased rows uncertain.
320
+ Retryable/unsupported transport diagnostics may project as `retryable`; counters
321
+ omit projection failures/parked mismatches, so inspect durable status/error
322
+ evidence. Malformed projections and permanently invalid PDFs can retry without
323
+ an attempt cap (PR #332, #344).
324
+ - Reused settlement-receipt detection continues within one call only; it does not
325
+ detect another item's reuse in a later run. Legacy host aggregates expose item
326
+ conflicts through count differences; distinct receipts require an item-capable
327
+ recorder/resolver (PR #344).
328
+ - Hosts retain accepted-document observation polling and safe history composition.
329
+ `resolveDownload` must bind the document to the authorized order; the package
330
+ ticket check compares `documentRef`. Opaque-reference filtering covers its listed
331
+ schemes only (PR #344).
332
+ - Closed diagnostic policy reduces managed message-only/non-allowlisted errors to
333
+ `unknown`; an empty/non-string earlier `code` can hide a later closed code. The
334
+ separate OMS projection retains redacted free text. Missing-order cleanup can
335
+ log error rather than warn with the same refused/discarded outcome (PR #344, #348).
336
+ - PDF content-type normalization retains OpenLup behavior; signature checks are
337
+ stricter than donor ASCII decoding. `invoicePdfFilename` falls back to English
338
+ `invoice`; supply host captions (PR #344).
339
+
13
340
  ## [0.23.0]
14
341
 
15
342
  - Publishable on the npm `latest` dist-tag as `0.23.0`, from tag
@@ -231,272 +558,3 @@ Native parity remains host-owned at these seams. Missing native bindings use the
231
558
  - M08 parity D2 KEEP-GAP: native dispatch finish still loses rejected/unknown error detail.
232
559
  - M08 parity KEEP-GAP: immutable stock snapshot/alert evidence storage is absent; cursor JSON is overwritten. Hosts retain referenced evidence.
233
560
  - Stock-evidence replay/reopen is CLOSED by native position 76; legacy `0.22.0` alert fingerprints still conflict with `23505`, including after resolution.
234
-
235
- ## [0.22.0]
236
-
237
- - Publishable on the npm `latest` dist-tag as `0.22.0`, from tag
238
- `openlup-platform-v0.22.0`.
239
-
240
- - Add eleven experimental reference-application support exports on the existing payment vendor subpaths. Reuse contributed execution, readback, mapping and diagnostic helpers; preserve the no-charge error class identity. Neutral payment exports and default activation remain unchanged.
241
-
242
- Migration: none.
243
-
244
- ### Opt-in warehouse fulfillment example
245
-
246
- Add the experimental, opt-in warehouse fulfillment entry described in the README behind the frozen neutral fulfillment ports: explicit injected I/O, prepared-byte binding, closed evidence, token observations and positive readback. Default-off; account readiness is host-owned. Exact absence, label create/void and cancellation remain unsupported.
247
-
248
- Missing or malformed evidence refuses before credential resolution or HTTP.
249
-
250
- Migration: none
251
-
252
- ### Offline warehouse fulfillment conformance
253
-
254
- Prove the opt-in warehouse fulfillment entry described in the README with M08's offline conformance runner using injected
255
- HTTP and synthetic fixtures. Cover dispatch replay and refusals, observation,
256
- readback, stock and product sync, plus real-worker host-ledger fences after
257
- restart and retention eviction. No provider-account or activation proof is claimed.
258
-
259
- Migration: none
260
-
261
- ### Fulfillment contracts and status canon
262
-
263
- Add experimental `fulfillment` and type-only `fulfillment/contracts` entries with
264
- contributed status decisions, strict core parser bindings, concrete provider/store
265
- ports and injected default-off capabilities. No adapter, executor, route or default
266
- profile is activated; existing reference integrations remain unchanged.
267
-
268
- Declared adaptation: empty or absent provider selection is a typed refusal in the
269
- new package, rather than the donor host's implicit simulator alias. The donor alias
270
- remains an open owner follow-up; this contribution does not change donor logic.
271
- Private provider trace columns and registry/environment values are excluded from
272
- the neutral package; persisted command fingerprints and opaque host keys are retained.
273
-
274
- Migration: none (new surface; no existing reference behavior changes).
275
-
276
- ### Fulfillment paid handoff and fenced dispatch
277
-
278
- Add the paid outbox handler/recovery classifier, injected dispatch worker and
279
- separate durable command-ledger protocol through the new fulfillment entry.
280
- Preserve one contact remap, opaque host keys, actual-command fingerprints,
281
- readback/attempt/begin order and local accepted-proof repair without another POST.
282
- Provider/money/inventory authority remains injected; no SQL, route or activation.
283
-
284
- Approved port amendment G14 adds recordProviderAttempt to the new
285
- FulfillmentStorePort. It records only sanitized prepared DispatchEvidence plus
286
- mode/recorded status and opaque references, after authoritative claim readback;
287
- same-key replay writes no second attempt and contact remap retains its own key.
288
- No new named export or subpath is added by this method. Other contracts are unchanged.
289
-
290
- Correctable draft re-claim must refresh fingerprint and evidence atomically.
291
- Store conformance and native durability/fencing and SQL proofs remain later work.
292
-
293
- Migration: none (new surface; contracts and orchestration land in one release).
294
-
295
- ### Fulfillment observation and sync workers
296
-
297
- Add neutral observation effects, verified ingress, observation reconciliation,
298
- tracking, stock/product sync, read-only evidence handlers and the offline
299
- runFulfillmentAdapterConformance at the existing fulfillment entry.
300
-
301
- Migration: approved G15 extends the unreleased SyncCursor with optional
302
- coverageGapSkus (legacy absence reads as []). Only consecutive succeeded runs
303
- confirm a reservation coverage gap; running/failed cursors clear the set.
304
- Migration: approved G16 changes readLocalInventoryStock(requestedAt) to typed
305
- unaggregated lines with skuRef, quantity balances, fulfillable, locationStatus,
306
- lotStatus and expiresAt. The worker filters/sums at the captured clock; expiry
307
- exactly then is excluded. Inventory authority and the provider stock-sync shape
308
- are unchanged.
309
- Migration: approved G17 adds inline localPersistence: ingress records eventKey
310
- receipts preserving firstReceivedAt and marks processing idempotently;
311
- reconciliation reads local status/latestStatusOccurredAt/handedOverAt. No named
312
- persistence type is exported. Durable replay and processing remain host obligations.
313
- A superseding conflict returns superseded but persists only processed status,
314
- without a dedicated superseded-reason field.
315
-
316
- Correlated ingress requires a nonblank observation or dispatch external reference
317
- before acceptance/status/effects/processed mark; failure leaves the receipt
318
- unprocessed. Stock-contention annotation is best-effort before the original stock
319
- failure is rethrown; recovered-picked receipt diagnostics remain typed. Effects
320
- retain stock → handover → tracking → invoice and callback/throw order.
321
- Reconciliation fails the run on unknown readback and projects unmapped correlation
322
- evidence before host calls. Product evidence reads retain safe authorization/read
323
- refusal detail. Private codecs, keys, carrier URLs and provider errors stay
324
- host-owned; typed evidence replaces raw payload pass-through. The conformance
325
- runner accepts adapter-owned offline subjects and returns sanitized evidence;
326
- fixture checks do not establish durable store atomicity or arrival alignment.
327
-
328
- ### Fulfillment native persistence and delivery alignment
329
-
330
- Add native shipment, evidence, stock, recovery, dispatch, paid-handoff and
331
- alignment stores through the existing fulfillment entry. Sparse migration
332
- projections bind native units 5/27/51/73/74; install the complete catalogue.
333
- Coverage-gap cursor state and received/status/processed evidence are
334
- durable, while local inventory lines and contact preparation remain explicit
335
- host inputs. Native 3pl acceptance uses a dispatch evidence receipt and preserves
336
- the cancellation fence without inventing an owned label or physical packing.
337
-
338
- Native admission: overdue-delivery admission guards only NEW cycle
339
- admission/insert, matching the donor's guard_cycle_insert. Existing-cycle retries
340
- through renewal operations and dunning bypass admission and neither mint nor
341
- consume a one-use receipt. No retry_scheduled state or payments lifecycle change is
342
- introduced. Native continuity requires the complete canonical migration graph,
343
- real-PostgreSQL installation, replay and access-control checks.
344
-
345
- ### Fulfillment operator lifecycle and customer delay projection
346
-
347
- Add host-owned operator and replacement handlers through the fulfillment entry.
348
- Mutation callbacks require actor attribution and idempotency keys; the host owns
349
- atomic replay receipts and replacement eligibility, reservation and hold effects.
350
- Native bindings return a shared typed unsupported refusal without writing.
351
- Customer delay projection keeps absent cases distinct, hides aligned history
352
- when the schedule advances and never presents manual review as protection.
353
- Label helpers preserve transient downloads and cleanup uncertainty. Current
354
- parcel helpers retain sequence selection and companion attribution. These
355
- exports mount no route, dispatch no parcel and attest no replacement arrival.
356
-
357
- ### Fulfillment commerce reads and recorded progress
358
-
359
- Add host-owned commerce list/detail projections, a shipments overview handler and
360
- typed read callbacks. Projected payment status passes through unchanged and
361
- native reads return the shared unsupported refusal. Preserve opaque host overview
362
- buckets and the legacy shipment-status facade. Progress completion requires
363
- recorded milestones and uses the host-resolved customer step.
364
-
365
- ### Fulfillment internal simplification
366
-
367
- Reuse the empty stock-balance constructor in aggregation and sync, and append to
368
- private recovery groups without copying each growing array. Fulfillment results,
369
- public contracts, key bytes and effect order remain unchanged.
370
-
371
- ### Fulfillment service composition and preparation
372
-
373
- Add explicit default-off fulfillment services, a structural contribution and an
374
- inert reference preparation binding. Authoritative source edits and redacted
375
- context synchronization share the native dispatch and shipment locks. Missing
376
- preparation refuses readiness. No route, schedule, renewal wrapper or automatic
377
- dispatch is activated.
378
-
379
- ### Fulfillment presentation ownership
380
-
381
- The status canon, actual-evidence tracking progress, current-parcel selection and
382
- canonical fact parsers belong to `@openlup/core/fulfillment`. Platform keeps thin
383
- compatibility re-exports and preserves its existing narrowed fact type names.
384
- Fulfillment contracts re-export the shared status and progress types from core.
385
- Server orchestration remains in platform. Browser code, including the host
386
- status, fact and current-parcel facades and the account order views, imports
387
- these helpers from core, so no browser graph loads the platform fulfillment
388
- runtime.
389
-
390
- Migration: existing platform imports remain valid; no application or schema
391
- migration is required. Core exposes narrowed fact aliases with a `Canonical`
392
- prefix while its generic fact exports retain their names.
393
-
394
- Migration: upgrade core, outbox and platform together from `0.21.0` to `0.22.0` for exact peer pins. Install the complete canonical native migration chain through units 73/74 (`20261022080000_fulfillment_command_ledger.sql` and `20261022090000_fulfillment_delivery_alignment.sql`), never the sparse package projections alone. Before, these fulfillment services were host-owned; after, explicitly compose selected ports and default-off services. Nothing mounts routes, schedules dispatch or composes the native renewal runner automatically. Keep native alignment off or shadow until the G23 decorator is composed. Arrival alignment remains once and later-only; undelivered replacements remain outstanding, and replacement confirmation must only record actual customer arrival. Preserve G15–G17 cursor, receipt and local-status persistence when implementing host stores. An application rollback does not reverse the forward migrations; older runners refuse the extended ledger.
395
-
396
- ### Known limitations
397
-
398
- - Portable dunning repair has no managed twin: exhaustion still pauses active subscriptions there; retaining active status needs a managed forward.
399
- - D8-1: native advisory v2 promo-code candidates/rejection details unavailable.
400
- - D8-2: native mounted v2 issue/honor/fallback unavailable.
401
- - D8-3: native acquisition-only mounted issuance/honor unavailable.
402
- - D8-4: full native/managed eligibility equivalence unavailable.
403
- - Bundle-1: independent DB human-only actor-kind enforcement absent natively; first in the native-backend parity round.
404
- - Bundle-2: managed-equivalent actor-kind/email history absent natively.
405
- - Bundle-3 closes injected-reader M05 mounted admin/feed readback only. Native new-purchase stock read absent despite P5a installed-store proof; deferred second after bundle-1 (owner 2026-10-21); readiness refuses.
406
- - Bundle-4: incumbent real-PostgreSQL contention only; no exactly-once guarantee.
407
- - Managed schema/pgTAP retain `44.404`; removal needs owner decision/forward; reference composition supplies it to app code.
408
- - A1 offline only; account/hosted-time/owner TEST evidence unclaimed; `communications/klaviyo` verification-pending.
409
- - M05 omitted opt-ins preserve defaults/outputs/read order/schedules/refusals/acceptance-token bytes/SQL.
410
- - Native inventory adjustment unavailable; address writes refuse readiness. Flat-rate save needs selected port/Core readiness/applied-seed observation.
411
- - Native shipping audit unavailable; handler swallows best-effort audit failure.
412
- - Native flat-rate integer bounds (0 through host maximum; reference 100,000 minor units) use request schema, not DB CHECK.
413
- - Managed ATP/forecast/dated-supply/pagination readback unproved/pending M06.
414
- - Managed two-session locks/concurrency/uncovered compensation unproved/pending M06.
415
- - Managed exact-prefix upgrade/ledger unproved/pending M06.
416
- - Managed address idempotency/conflict/readback unproved/pending M06.
417
- - Managed successful flat-rate read/save unproved/pending host authority.
418
- - M06 stock-wait lifecycle/durable timing/staging controls retain C5/C6; busy/try-gate, continuity/flag/TTL transfers are dispositions, not PASS.
419
- - Shipping national-registry fields/locale-specific `canonicalAddressKey` fold await M16 host market pack/key migration; reference shipping copy stays locale-specific until M16.
420
- - Native durable prepared storage, method setup, absence reopen and cumulative refunds unavailable; no production installation parity claimed.
421
- - Typed refusal-envelope forwarding unavailable (`failureReason` only); reusable registration needs host ownership resolution.
422
- - Incomplete chargebacks stay refunds/unapplied: reclassification bypasses evidence validation into dispute apply; limited operator recovery.
423
- - Audit compatibility still detects `chargeId`; refund operation identity/original money supply no typed charge identity.
424
- - M07 follow-up: repair poll can clear host redirect; post-timeout verify never restarts polling; unlocalized poller; fixture builds/never calls handler.
425
- - M07 follow-up: reference status route wrong-rail witness.
426
- - M07 follow-up: explicit reference-route refusal for unsupported method setup.
427
- - M07 follow-up: deployment-neutral disabled-verify reason.
428
- - M07 follow-up: reference card normalizer missing-amount path; package settling evidence already requires positive money.
429
-
430
- - Native delivery alignment stays off or shadow until a host composes the native automatic-renewal runner with the G23 renewal admission decorator. The decorator alone neither composes nor activates the runner.
431
- - The core fulfillment status map carries localized adopter labels; replace them with host-injected labels or internationalization keys before any stable-framework claim.
432
- - The warehouse adapter example is opt-in and has offline conformance only; no provider-account proof or activation is established. Exact absence, label create/void and cancellation remain unsupported.
433
- - After an alignment extension, a deferred renewal operation at the old schedule remains claimed with no reader or reservation effect. Changed terms snapshots conflict under the existing snapshot-conflict rules.
434
-
435
- Native parity remains host-owned at these seams. Missing native bindings use the shared `FULFILLMENT_NATIVE_UNSUPPORTED` refusal; no partial write or parity claim is implied.
436
-
437
- | Amendment | Host-owned seam and native boundary |
438
- | --- | --- |
439
- | G18 | Replacement creation and atomic eligibility/replay receipts; native replacement callback refuses. |
440
- | G19 | Operator mutations, actor attribution and replay receipts; native mutation callbacks refuse. |
441
- | G20 | Customer alignment rows; native reader refuses, while the pure delay projection remains callable. |
442
- | G21 | Commerce list/detail and shipments overview; native read callbacks refuse. |
443
- | G22 | Authoritative preparation edits, authorization and replay receipts; missing preparation binding refuses before dispatch, after disabled/selection/readiness checks. |
444
-
445
- ## [0.21.0]
446
-
447
- - Publishable on the npm `latest` dist-tag as `0.21.0`, from tag
448
- `openlup-platform-v0.21.0`.
449
- - Preview set: core/outbox unchanged, UI private `0.0.0`; published `0.20.0` size baselines, unchanged caps.
450
-
451
- ### Cumulative M07 status: payment truth and repair surfaces complete for this wave
452
-
453
- - Experimental payments/contracts/runtime: unchanged prepared ordering; neutral execution/evidence/readback/conformance, verified truth, first-receipt ingress, method lifecycle/reconciliation; host-owned persistence, translation/failure policy.
454
- - Native PostgreSQL truth/settlement/later-only alignment; three unchanged sparse SQL projections, not an install chain. Refunds never cancel subscriptions.
455
- - Repair/recovery/buyer verify inject rail capabilities; unknown rails refuse. Reference BFF retains mapping/schemas/ownership/auth order/transient callbacks. Browser/verify outcomes never prove payment success.
456
- - Reference-application source (no new export), opt-in repair view: `commerce/paymentStatusClient`, `commerce/paymentVerifyClient`, `payment/components/PaymentStatusPoller`; stored paid alone confirms, redirects require HTTPS, collection/confirmation stay injected, unsupported setup is visible. Exact file/specifier guards refuse broad commerce/operator clients; source-import proof keeps default view unmounted.
457
- - Truth services/one optional named binder use the host executor, no new schedule/executor. Selectors default-off: nothing activates by default. First-insert adapter fingerprint excludes receipt time/audit.
458
- - Two experimental example adapter subpaths under `./payments/`, named in the README. Card-processor example: three frozen exports, injected host client/neutral ports; refund creation, split authorization/capture and exact absence unavailable; cancellation needs host support.
459
- - Regional-processor example: host I/O, Model O aliases, verified observations, purpose-sensitive readback; check certificate validity/notification freshness. Both examples have no import I/O/default binding and await account TEST evidence.
460
- - Example adapter advisory: mismatched nonzero refusal money stays unknown/manual; trusted document refusals mean customer data correction; configuration mismatches throw before I/O. Unpaid/transient no-dispatch classifications unchanged.
461
- - Settling money missing/invalid/non-positive or blank currency refuses as amount mismatch; conformance requires positive money. Empty optional transients stop false leak refusals; JSON-escaped transients in diagnostics/readbacks/stored payloads and payer contact in execution results now refuse.
462
- - Private types reuse canonical money/attempts; unused imports removed, runtime/API unchanged.
463
-
464
- Migration: upgrade all `@openlup/*` `0.20.0` → `0.21.0` for exact pins. No schema migration; install the canonical catalogue, not sparse projections. Attempts add optional method selection/transient payer contact; contact is dispatch-only, never persisted/audited/logged/diagnosed. Missing adapter-required input requires exact before-dispatch `notDispatched`. Registration refs/kind/status require host `resolveMethodOwner` client/subscription ownership or are omitted. Lifecycle/normalized nested audit copies typed fields only; conformance scans all for secrets/contact. Adapter-filtered redacted audit never stores raw bodies; typed evidence overrides reader facts, audit bag fills untyped facts; identity/fingerprint exclude bag/receipt time. Other changes need no migration, and nothing rewires a host automatically.
465
-
466
- Migration: F2 replaces assumed full refund with `require-evidence`: missing/null kind/amount/operation identity is durably recorded/acknowledged, not applied. Supply original money, stable operation identity and cumulative snapshot, event delta or explicit full reversal (`refund`/`chargeback`); full evidence stays valid. Former default needs `refundEvidencePolicy: "legacy-assume-full"`, also in the reference handler; no native parity implied.
467
-
468
- Migration: D11 changes every caller of the reference payment control port (the selected verified ingress, the existing provider webhook handler and the captured reference checkout): apply/post-process redelivery using the first stored receipt instant, not redelivery time, so it cannot shift the cycle again. Replay reads winning receipt evidence and refuses (503) when that instant is unavailable. A legacy pre-fingerprint row takes the later clock once. Retain receipt evidence on upgrade; provider routes are not switched to opt-in ingress.
469
-
470
- ### Known limitations
471
-
472
- - Portable dunning repair has no managed twin: exhaustion still pauses active subscriptions there; retaining active status needs a managed forward.
473
- - D8-1: native advisory v2 promo-code candidates/rejection details unavailable.
474
- - D8-2: native mounted v2 issue/honor/fallback unavailable.
475
- - D8-3: native acquisition-only mounted issuance/honor unavailable.
476
- - D8-4: full native/managed eligibility equivalence unavailable.
477
- - Bundle-1: independent DB human-only actor-kind enforcement absent natively; first in the native-backend parity round.
478
- - Bundle-2: managed-equivalent actor-kind/email history absent natively.
479
- - Bundle-3 closes injected-reader M05 mounted admin/feed readback only. Native new-purchase stock read absent despite P5a installed-store proof; deferred second after bundle-1 (owner 2026-10-21); readiness refuses.
480
- - Bundle-4: incumbent real-PostgreSQL contention only; no exactly-once guarantee.
481
- - Managed schema/pgTAP retain `44.404`; removal needs owner decision/forward; reference composition supplies it to app code.
482
- - A1 offline only; account/hosted-time/owner TEST evidence unclaimed; `communications/klaviyo` verification-pending.
483
- - M05 omitted opt-ins preserve defaults/outputs/read order/schedules/refusals/acceptance-token bytes/SQL.
484
- - Native inventory adjustment unavailable; address writes refuse readiness. Flat-rate save needs selected port/Core readiness/applied-seed observation.
485
- - Native shipping audit unavailable; handler swallows best-effort audit failure.
486
- - Native flat-rate integer bounds (0 through host maximum; reference 100,000 minor units) use request schema, not DB CHECK.
487
- - Managed ATP/forecast/dated-supply/pagination readback unproved/pending M06.
488
- - Managed two-session locks/concurrency/uncovered compensation unproved/pending M06.
489
- - Managed exact-prefix upgrade/ledger unproved/pending M06.
490
- - Managed address idempotency/conflict/readback unproved/pending M06.
491
- - Managed successful flat-rate read/save unproved/pending host authority.
492
- - M06 stock-wait lifecycle/durable timing/staging controls retain C5/C6; busy/try-gate, continuity/flag/TTL transfers are dispositions, not PASS.
493
- - Shipping national-registry fields/locale-specific `canonicalAddressKey` fold await M16 host market pack/key migration; reference shipping copy stays locale-specific until M16.
494
- - Native durable prepared storage, method setup, absence reopen and cumulative refunds unavailable; no production installation parity claimed.
495
- - Typed refusal-envelope forwarding unavailable (`failureReason` only); reusable registration needs host ownership resolution.
496
- - Incomplete chargebacks stay refunds/unapplied: reclassification bypasses evidence validation into dispute apply; limited operator recovery.
497
- - Audit compatibility still detects `chargeId`; refund operation identity/original money supply no typed charge identity.
498
- - M07 follow-up: repair poll can clear host redirect; post-timeout verify never restarts polling; unlocalized poller; fixture builds/never calls handler.
499
- - M07 follow-up: reference status route wrong-rail witness.
500
- - M07 follow-up: explicit reference-route refusal for unsupported method setup.
501
- - M07 follow-up: deployment-neutral disabled-verify reason.
502
- - M07 follow-up: reference card normalizer missing-amount path; package settling evidence already requires positive money.