@openlup/platform 0.21.0 → 0.23.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 (349) hide show
  1. package/CHANGELOG.md +432 -146
  2. package/README.md +82 -589
  3. package/dist/composition/composeBundle.d.ts +7 -0
  4. package/dist/composition/composeBundle.js +2 -0
  5. package/dist/composition/fulfillmentContribution.d.ts +21 -0
  6. package/dist/composition/fulfillmentContribution.js +19 -0
  7. package/dist/composition/index.d.ts +1 -0
  8. package/dist/composition/index.js +1 -0
  9. package/dist/fulfillment/adapterConformance.d.ts +3 -0
  10. package/dist/fulfillment/adapterConformance.js +223 -0
  11. package/dist/fulfillment/bindings.d.ts +3 -0
  12. package/dist/fulfillment/bindings.js +29 -0
  13. package/dist/fulfillment/commerceFulfillmentHandlers.d.ts +29 -0
  14. package/dist/fulfillment/commerceFulfillmentHandlers.js +184 -0
  15. package/dist/fulfillment/commerceFulfillmentReadModel.d.ts +86 -0
  16. package/dist/fulfillment/commerceFulfillmentReadModel.js +131 -0
  17. package/dist/fulfillment/contracts/alignment.d.ts +25 -0
  18. package/dist/fulfillment/contracts/alignment.js +1 -0
  19. package/dist/fulfillment/contracts/bindings.d.ts +51 -0
  20. package/dist/fulfillment/contracts/bindings.js +1 -0
  21. package/dist/fulfillment/contracts/capabilities.d.ts +29 -0
  22. package/dist/fulfillment/contracts/capabilities.js +1 -0
  23. package/dist/fulfillment/contracts/conformance.d.ts +95 -0
  24. package/dist/fulfillment/contracts/conformance.js +1 -0
  25. package/dist/fulfillment/contracts/customerAlignment.d.ts +6 -0
  26. package/dist/fulfillment/contracts/customerAlignment.js +1 -0
  27. package/dist/fulfillment/contracts/dispatch.d.ts +143 -0
  28. package/dist/fulfillment/contracts/dispatch.js +1 -0
  29. package/dist/fulfillment/contracts/index.d.ts +18 -0
  30. package/dist/fulfillment/contracts/index.js +1 -0
  31. package/dist/fulfillment/contracts/label.d.ts +35 -0
  32. package/dist/fulfillment/contracts/label.js +1 -0
  33. package/dist/fulfillment/contracts/nativeUnsupported.d.ts +6 -0
  34. package/dist/fulfillment/contracts/nativeUnsupported.js +1 -0
  35. package/dist/fulfillment/contracts/observation.d.ts +72 -0
  36. package/dist/fulfillment/contracts/observation.js +1 -0
  37. package/dist/fulfillment/contracts/operator.d.ts +64 -0
  38. package/dist/fulfillment/contracts/operator.js +1 -0
  39. package/dist/fulfillment/contracts/read.d.ts +110 -0
  40. package/dist/fulfillment/contracts/read.js +1 -0
  41. package/dist/fulfillment/contracts/readback.d.ts +59 -0
  42. package/dist/fulfillment/contracts/readback.js +1 -0
  43. package/dist/fulfillment/contracts/replacement.d.ts +34 -0
  44. package/dist/fulfillment/contracts/replacement.js +1 -0
  45. package/dist/fulfillment/contracts/store.d.ts +89 -0
  46. package/dist/fulfillment/contracts/store.js +1 -0
  47. package/dist/fulfillment/contracts/sync.d.ts +226 -0
  48. package/dist/fulfillment/contracts/sync.js +1 -0
  49. package/dist/fulfillment/currentFulfillmentParcel.d.ts +2 -0
  50. package/dist/fulfillment/currentFulfillmentParcel.js +1 -0
  51. package/dist/fulfillment/delayReadModel.d.ts +11 -0
  52. package/dist/fulfillment/delayReadModel.js +45 -0
  53. package/dist/fulfillment/deliveryAlignmentReadModel.d.ts +4 -0
  54. package/dist/fulfillment/deliveryAlignmentReadModel.js +12 -0
  55. package/dist/fulfillment/dispatchProjection.d.ts +26 -0
  56. package/dist/fulfillment/dispatchProjection.js +107 -0
  57. package/dist/fulfillment/fulfillmentObservationEffects.d.ts +66 -0
  58. package/dist/fulfillment/fulfillmentObservationEffects.js +36 -0
  59. package/dist/fulfillment/handlerSchemas.d.ts +647 -0
  60. package/dist/fulfillment/handlerSchemas.js +213 -0
  61. package/dist/fulfillment/handlerSupport.d.ts +33 -0
  62. package/dist/fulfillment/handlerSupport.js +25 -0
  63. package/dist/fulfillment/index.d.ts +38 -0
  64. package/dist/fulfillment/index.js +37 -0
  65. package/dist/fulfillment/labelLifecycle.d.ts +24 -0
  66. package/dist/fulfillment/labelLifecycle.js +9 -0
  67. package/dist/fulfillment/lowStockEvidenceHandler.d.ts +36 -0
  68. package/dist/fulfillment/lowStockEvidenceHandler.js +46 -0
  69. package/dist/fulfillment/migrations.d.ts +32 -0
  70. package/dist/fulfillment/migrations.js +9 -0
  71. package/dist/fulfillment/nativeUnsupported.d.ts +10 -0
  72. package/dist/fulfillment/nativeUnsupported.js +18 -0
  73. package/dist/fulfillment/normalizedFulfillmentFacts.d.ts +2 -0
  74. package/dist/fulfillment/normalizedFulfillmentFacts.js +1 -0
  75. package/dist/fulfillment/observationProjection.d.ts +32 -0
  76. package/dist/fulfillment/observationProjection.js +90 -0
  77. package/dist/fulfillment/omnipack/capabilities.d.ts +3 -0
  78. package/dist/fulfillment/omnipack/capabilities.js +16 -0
  79. package/dist/fulfillment/omnipack/client.d.ts +39 -0
  80. package/dist/fulfillment/omnipack/client.js +172 -0
  81. package/dist/fulfillment/omnipack/index.d.ts +55 -0
  82. package/dist/fulfillment/omnipack/index.js +408 -0
  83. package/dist/fulfillment/omnipack/mappers.d.ts +79 -0
  84. package/dist/fulfillment/omnipack/mappers.js +199 -0
  85. package/dist/fulfillment/omnipack/observation.d.ts +28 -0
  86. package/dist/fulfillment/omnipack/observation.js +72 -0
  87. package/dist/fulfillment/omnipack/omnipackDispatchPayload.d.ts +36 -0
  88. package/dist/fulfillment/omnipack/omnipackDispatchPayload.js +63 -0
  89. package/dist/fulfillment/omnipack/omnipackOutboundOrderPayload.d.ts +83 -0
  90. package/dist/fulfillment/omnipack/omnipackOutboundOrderPayload.js +113 -0
  91. package/dist/fulfillment/omnipack/omnipackProductPackPayload.d.ts +11 -0
  92. package/dist/fulfillment/omnipack/omnipackProductPackPayload.js +38 -0
  93. package/dist/fulfillment/omnipack/omnipackProductPayload.d.ts +18 -0
  94. package/dist/fulfillment/omnipack/omnipackProductPayload.js +51 -0
  95. package/dist/fulfillment/omnipack/omnipackReconciliationPayload.d.ts +1 -0
  96. package/dist/fulfillment/omnipack/omnipackReconciliationPayload.js +3 -0
  97. package/dist/fulfillment/omnipack/omnipackStatusVocabulary.d.ts +4 -0
  98. package/dist/fulfillment/omnipack/omnipackStatusVocabulary.js +87 -0
  99. package/dist/fulfillment/omnipack/omnipackWebhookPayload.d.ts +9 -0
  100. package/dist/fulfillment/omnipack/omnipackWebhookPayload.js +76 -0
  101. package/dist/fulfillment/omnipack/productSyncMappers.d.ts +18 -0
  102. package/dist/fulfillment/omnipack/productSyncMappers.js +43 -0
  103. package/dist/fulfillment/omnipack/providerError.d.ts +25 -0
  104. package/dist/fulfillment/omnipack/providerError.js +47 -0
  105. package/dist/fulfillment/omnipack/reconciliation.d.ts +15 -0
  106. package/dist/fulfillment/omnipack/reconciliation.js +55 -0
  107. package/dist/fulfillment/omnipack/trackingReferences.d.ts +16 -0
  108. package/dist/fulfillment/omnipack/trackingReferences.js +52 -0
  109. package/dist/fulfillment/paidFulfillmentRecovery.d.ts +67 -0
  110. package/dist/fulfillment/paidFulfillmentRecovery.js +154 -0
  111. package/dist/fulfillment/paidHandoff.d.ts +27 -0
  112. package/dist/fulfillment/paidHandoff.js +86 -0
  113. package/dist/fulfillment/paidHandoffPorts.d.ts +24 -0
  114. package/dist/fulfillment/paidHandoffPorts.js +3 -0
  115. package/dist/fulfillment/postgresDeliveryAlignment.d.ts +4 -0
  116. package/dist/fulfillment/postgresDeliveryAlignment.js +12 -0
  117. package/dist/fulfillment/postgresDispatchStore.d.ts +16 -0
  118. package/dist/fulfillment/postgresDispatchStore.js +44 -0
  119. package/dist/fulfillment/postgresEvidenceReadPort.d.ts +25 -0
  120. package/dist/fulfillment/postgresEvidenceReadPort.js +45 -0
  121. package/dist/fulfillment/postgresPaidFulfillmentRecovery.d.ts +25 -0
  122. package/dist/fulfillment/postgresPaidFulfillmentRecovery.js +26 -0
  123. package/dist/fulfillment/postgresPaidHandoffStore.d.ts +4 -0
  124. package/dist/fulfillment/postgresPaidHandoffStore.js +10 -0
  125. package/dist/fulfillment/postgresShipmentSpine.d.ts +70 -0
  126. package/dist/fulfillment/postgresShipmentSpine.js +246 -0
  127. package/dist/fulfillment/postgresStockSyncPort.d.ts +8 -0
  128. package/dist/fulfillment/postgresStockSyncPort.js +66 -0
  129. package/dist/fulfillment/productReconciliationEvidenceHandler.d.ts +36 -0
  130. package/dist/fulfillment/productReconciliationEvidenceHandler.js +50 -0
  131. package/dist/fulfillment/providerCapabilities.d.ts +9 -0
  132. package/dist/fulfillment/providerCapabilities.js +17 -0
  133. package/dist/fulfillment/providerCommandLedger.d.ts +143 -0
  134. package/dist/fulfillment/providerCommandLedger.js +14 -0
  135. package/dist/fulfillment/providerDispatchAcceptance.d.ts +27 -0
  136. package/dist/fulfillment/providerDispatchAcceptance.js +29 -0
  137. package/dist/fulfillment/providerDispatchError.d.ts +6 -0
  138. package/dist/fulfillment/providerDispatchError.js +5 -0
  139. package/dist/fulfillment/providerDispatchWorker.d.ts +44 -0
  140. package/dist/fulfillment/providerDispatchWorker.js +199 -0
  141. package/dist/fulfillment/providerProductSyncWorker.d.ts +28 -0
  142. package/dist/fulfillment/providerProductSyncWorker.js +122 -0
  143. package/dist/fulfillment/providerReconciliationError.d.ts +9 -0
  144. package/dist/fulfillment/providerReconciliationError.js +17 -0
  145. package/dist/fulfillment/providerReconciliationTerminalSkip.d.ts +2 -0
  146. package/dist/fulfillment/providerReconciliationTerminalSkip.js +6 -0
  147. package/dist/fulfillment/providerReconciliationTimestamp.d.ts +1 -0
  148. package/dist/fulfillment/providerReconciliationTimestamp.js +27 -0
  149. package/dist/fulfillment/providerReconciliationWorker.d.ts +90 -0
  150. package/dist/fulfillment/providerReconciliationWorker.js +207 -0
  151. package/dist/fulfillment/providerStockAvailability.d.ts +13 -0
  152. package/dist/fulfillment/providerStockAvailability.js +51 -0
  153. package/dist/fulfillment/providerStockSyncWorker.d.ts +41 -0
  154. package/dist/fulfillment/providerStockSyncWorker.js +295 -0
  155. package/dist/fulfillment/providerTrackingReferences.d.ts +16 -0
  156. package/dist/fulfillment/providerTrackingReferences.js +23 -0
  157. package/dist/fulfillment/replacementRefusals.d.ts +5 -0
  158. package/dist/fulfillment/replacementRefusals.js +38 -0
  159. package/dist/fulfillment/replacementShipmentHandler.d.ts +5 -0
  160. package/dist/fulfillment/replacementShipmentHandler.js +46 -0
  161. package/dist/fulfillment/schemaCapabilities.d.ts +13 -0
  162. package/dist/fulfillment/schemaCapabilities.js +7 -0
  163. package/dist/fulfillment/shipmentsOverviewHandler.d.ts +16 -0
  164. package/dist/fulfillment/shipmentsOverviewHandler.js +54 -0
  165. package/dist/fulfillment/statusMap.d.ts +2 -0
  166. package/dist/fulfillment/statusMap.js +1 -0
  167. package/dist/fulfillment/trackingProgress.d.ts +1 -0
  168. package/dist/fulfillment/trackingProgress.js +1 -0
  169. package/dist/fulfillment/verifiedIngress.d.ts +79 -0
  170. package/dist/fulfillment/verifiedIngress.js +94 -0
  171. package/dist/invoicing/capabilities.d.ts +11 -0
  172. package/dist/invoicing/capabilities.js +10 -0
  173. package/dist/invoicing/contracts/capabilities.d.ts +40 -0
  174. package/dist/invoicing/contracts/capabilities.js +1 -0
  175. package/dist/invoicing/contracts/companyLookup.d.ts +49 -0
  176. package/dist/invoicing/contracts/companyLookup.js +1 -0
  177. package/dist/invoicing/contracts/delivery.d.ts +74 -0
  178. package/dist/invoicing/contracts/delivery.js +1 -0
  179. package/dist/invoicing/contracts/facts.d.ts +100 -0
  180. package/dist/invoicing/contracts/facts.js +1 -0
  181. package/dist/invoicing/contracts/host.d.ts +246 -0
  182. package/dist/invoicing/contracts/host.js +1 -0
  183. package/dist/invoicing/contracts/index.d.ts +16 -0
  184. package/dist/invoicing/contracts/index.js +1 -0
  185. package/dist/invoicing/contracts/provider.d.ts +126 -0
  186. package/dist/invoicing/contracts/provider.js +1 -0
  187. package/dist/invoicing/contracts/settlement.d.ts +66 -0
  188. package/dist/invoicing/contracts/settlement.js +1 -0
  189. package/dist/invoicing/contracts/store.d.ts +267 -0
  190. package/dist/invoicing/contracts/store.js +1 -0
  191. package/dist/invoicing/index.d.ts +1 -0
  192. package/dist/invoicing/index.js +1 -0
  193. package/dist/payments/stripe/index.d.ts +25 -0
  194. package/dist/payments/stripe/index.js +25 -0
  195. package/dist/payments/tpay/index.d.ts +30 -0
  196. package/dist/payments/tpay/index.js +30 -0
  197. package/dist/subscriptions/automaticRenewal.d.ts +44 -0
  198. package/dist/subscriptions/automaticRenewal.js +81 -0
  199. package/dist/subscriptions/automaticRenewalExecution.d.ts +21 -0
  200. package/dist/subscriptions/automaticRenewalExecution.js +44 -0
  201. package/dist/subscriptions/contracts/commands.d.ts +115 -0
  202. package/dist/subscriptions/contracts/commands.js +1 -0
  203. package/dist/subscriptions/contracts/dunning.d.ts +133 -0
  204. package/dist/subscriptions/contracts/dunning.js +1 -0
  205. package/dist/subscriptions/contracts/index.d.ts +6 -0
  206. package/dist/subscriptions/contracts/index.js +1 -0
  207. package/dist/subscriptions/contracts/messages.d.ts +43 -0
  208. package/dist/subscriptions/contracts/messages.js +1 -0
  209. package/dist/subscriptions/contracts/renewal.d.ts +533 -0
  210. package/dist/subscriptions/contracts/renewal.js +1 -0
  211. package/dist/subscriptions/contracts/stockWait.d.ts +73 -0
  212. package/dist/subscriptions/contracts/stockWait.js +1 -0
  213. package/dist/subscriptions/index.d.ts +39 -0
  214. package/dist/subscriptions/index.js +17 -0
  215. package/dist/subscriptions/paymentOutcomes.d.ts +8 -0
  216. package/dist/subscriptions/paymentOutcomes.js +27 -0
  217. package/dist/subscriptions/postgresRenewalStore.d.ts +20 -0
  218. package/dist/subscriptions/postgresRenewalStore.js +61 -0
  219. package/dist/subscriptions/postgresRetryStore.d.ts +78 -0
  220. package/dist/subscriptions/postgresRetryStore.js +142 -0
  221. package/dist/subscriptions/renewalCycleFailureMechanism.d.ts +34 -0
  222. package/dist/subscriptions/renewalCycleFailureMechanism.js +79 -0
  223. package/dist/subscriptions/renewalCycleMechanism.d.ts +46 -0
  224. package/dist/subscriptions/renewalCycleMechanism.js +157 -0
  225. package/dist/subscriptions/renewalCycleRefusalMechanism.d.ts +41 -0
  226. package/dist/subscriptions/renewalCycleRefusalMechanism.js +160 -0
  227. package/dist/subscriptions/renewalIdentity.d.ts +3 -0
  228. package/dist/subscriptions/renewalIdentity.js +4 -0
  229. package/package.json +37 -2
  230. package/release-gates.json +97 -3
  231. package/sql/20260808210000_fulfillment_shipment_rail.sql +810 -0
  232. package/sql/20260819150000_fulfillment_shipment_sequence.sql +98 -0
  233. package/sql/20261022080000_fulfillment_command_ledger.sql +786 -0
  234. package/sql/20261022090000_fulfillment_delivery_alignment.sql +1106 -0
  235. package/sql/20261022160000_subscription_retry_lifecycle.sql +328 -0
  236. package/sql/20261022165000_fulfillment_stock_evidence_replay_reopen.sql +30 -0
  237. package/src/composition/composeBundle.ts +4 -0
  238. package/src/composition/fulfillmentContribution.ts +28 -0
  239. package/src/composition/index.ts +1 -0
  240. package/src/fulfillment/adapterConformance.ts +195 -0
  241. package/src/fulfillment/bindings.ts +26 -0
  242. package/src/fulfillment/commerceFulfillmentHandlers.ts +263 -0
  243. package/src/fulfillment/commerceFulfillmentReadModel.ts +257 -0
  244. package/src/fulfillment/contracts/alignment.ts +13 -0
  245. package/src/fulfillment/contracts/bindings.ts +30 -0
  246. package/src/fulfillment/contracts/capabilities.ts +15 -0
  247. package/src/fulfillment/contracts/conformance.ts +63 -0
  248. package/src/fulfillment/contracts/customerAlignment.ts +4 -0
  249. package/src/fulfillment/contracts/dispatch.ts +73 -0
  250. package/src/fulfillment/contracts/index.ts +18 -0
  251. package/src/fulfillment/contracts/label.ts +9 -0
  252. package/src/fulfillment/contracts/nativeUnsupported.ts +6 -0
  253. package/src/fulfillment/contracts/observation.ts +26 -0
  254. package/src/fulfillment/contracts/operator.ts +31 -0
  255. package/src/fulfillment/contracts/read.ts +42 -0
  256. package/src/fulfillment/contracts/readback.ts +24 -0
  257. package/src/fulfillment/contracts/replacement.ts +15 -0
  258. package/src/fulfillment/contracts/store.ts +27 -0
  259. package/src/fulfillment/contracts/sync.ts +72 -0
  260. package/src/fulfillment/currentFulfillmentParcel.ts +2 -0
  261. package/src/fulfillment/delayReadModel.ts +60 -0
  262. package/src/fulfillment/deliveryAlignmentReadModel.ts +15 -0
  263. package/src/fulfillment/dispatchProjection.ts +105 -0
  264. package/src/fulfillment/fulfillmentObservationEffects.ts +86 -0
  265. package/src/fulfillment/handlerSchemas.ts +255 -0
  266. package/src/fulfillment/handlerSupport.ts +25 -0
  267. package/src/fulfillment/index.ts +39 -0
  268. package/src/fulfillment/labelLifecycle.ts +11 -0
  269. package/src/fulfillment/lowStockEvidenceHandler.ts +60 -0
  270. package/src/fulfillment/migrations.ts +9 -0
  271. package/src/fulfillment/nativeUnsupported.ts +23 -0
  272. package/src/fulfillment/normalizedFulfillmentFacts.ts +2 -0
  273. package/src/fulfillment/observationProjection.ts +92 -0
  274. package/src/fulfillment/omnipack/capabilities.ts +18 -0
  275. package/src/fulfillment/omnipack/client.ts +270 -0
  276. package/src/fulfillment/omnipack/index.ts +369 -0
  277. package/src/fulfillment/omnipack/mappers.ts +282 -0
  278. package/src/fulfillment/omnipack/observation.ts +79 -0
  279. package/src/fulfillment/omnipack/omnipackDispatchPayload.ts +93 -0
  280. package/src/fulfillment/omnipack/omnipackOutboundOrderPayload.ts +194 -0
  281. package/src/fulfillment/omnipack/omnipackProductPackPayload.ts +47 -0
  282. package/src/fulfillment/omnipack/omnipackProductPayload.ts +67 -0
  283. package/src/fulfillment/omnipack/omnipackReconciliationPayload.ts +7 -0
  284. package/src/fulfillment/omnipack/omnipackStatusVocabulary.ts +103 -0
  285. package/src/fulfillment/omnipack/omnipackWebhookPayload.ts +73 -0
  286. package/src/fulfillment/omnipack/productSyncMappers.ts +74 -0
  287. package/src/fulfillment/omnipack/providerError.ts +64 -0
  288. package/src/fulfillment/omnipack/reconciliation.ts +56 -0
  289. package/src/fulfillment/omnipack/trackingReferences.ts +77 -0
  290. package/src/fulfillment/paidFulfillmentRecovery.ts +252 -0
  291. package/src/fulfillment/paidHandoff.ts +122 -0
  292. package/src/fulfillment/paidHandoffPorts.ts +21 -0
  293. package/src/fulfillment/postgresDeliveryAlignment.ts +14 -0
  294. package/src/fulfillment/postgresDispatchStore.ts +55 -0
  295. package/src/fulfillment/postgresEvidenceReadPort.ts +59 -0
  296. package/src/fulfillment/postgresPaidFulfillmentRecovery.ts +29 -0
  297. package/src/fulfillment/postgresPaidHandoffStore.ts +11 -0
  298. package/src/fulfillment/postgresShipmentSpine.ts +338 -0
  299. package/src/fulfillment/postgresStockSyncPort.ts +68 -0
  300. package/src/fulfillment/productReconciliationEvidenceHandler.ts +64 -0
  301. package/src/fulfillment/providerCapabilities.ts +18 -0
  302. package/src/fulfillment/providerCommandLedger.ts +53 -0
  303. package/src/fulfillment/providerDispatchAcceptance.ts +37 -0
  304. package/src/fulfillment/providerDispatchError.ts +7 -0
  305. package/src/fulfillment/providerDispatchWorker.ts +159 -0
  306. package/src/fulfillment/providerProductSyncWorker.ts +154 -0
  307. package/src/fulfillment/providerReconciliationError.ts +20 -0
  308. package/src/fulfillment/providerReconciliationTerminalSkip.ts +8 -0
  309. package/src/fulfillment/providerReconciliationTimestamp.ts +34 -0
  310. package/src/fulfillment/providerReconciliationWorker.ts +206 -0
  311. package/src/fulfillment/providerStockAvailability.ts +60 -0
  312. package/src/fulfillment/providerStockSyncWorker.ts +318 -0
  313. package/src/fulfillment/providerTrackingReferences.ts +32 -0
  314. package/src/fulfillment/replacementRefusals.ts +43 -0
  315. package/src/fulfillment/replacementShipmentHandler.ts +47 -0
  316. package/src/fulfillment/schemaCapabilities.ts +7 -0
  317. package/src/fulfillment/shipmentsOverviewHandler.ts +73 -0
  318. package/src/fulfillment/statusMap.ts +2 -0
  319. package/src/fulfillment/trackingProgress.ts +1 -0
  320. package/src/fulfillment/verifiedIngress.ts +113 -0
  321. package/src/invoicing/capabilities.ts +9 -0
  322. package/src/invoicing/contracts/capabilities.ts +15 -0
  323. package/src/invoicing/contracts/companyLookup.ts +13 -0
  324. package/src/invoicing/contracts/delivery.ts +24 -0
  325. package/src/invoicing/contracts/facts.ts +60 -0
  326. package/src/invoicing/contracts/host.ts +85 -0
  327. package/src/invoicing/contracts/index.ts +16 -0
  328. package/src/invoicing/contracts/provider.ts +78 -0
  329. package/src/invoicing/contracts/settlement.ts +39 -0
  330. package/src/invoicing/contracts/store.ts +98 -0
  331. package/src/invoicing/index.ts +1 -0
  332. package/src/payments/stripe/index.ts +30 -0
  333. package/src/payments/tpay/index.ts +36 -0
  334. package/src/subscriptions/automaticRenewal.ts +87 -0
  335. package/src/subscriptions/automaticRenewalExecution.ts +39 -0
  336. package/src/subscriptions/contracts/commands.ts +46 -0
  337. package/src/subscriptions/contracts/dunning.ts +48 -0
  338. package/src/subscriptions/contracts/index.ts +6 -0
  339. package/src/subscriptions/contracts/messages.ts +18 -0
  340. package/src/subscriptions/contracts/renewal.ts +325 -0
  341. package/src/subscriptions/contracts/stockWait.ts +34 -0
  342. package/src/subscriptions/index.ts +24 -0
  343. package/src/subscriptions/paymentOutcomes.ts +23 -0
  344. package/src/subscriptions/postgresRenewalStore.ts +76 -0
  345. package/src/subscriptions/postgresRetryStore.ts +174 -0
  346. package/src/subscriptions/renewalCycleFailureMechanism.ts +119 -0
  347. package/src/subscriptions/renewalCycleMechanism.ts +225 -0
  348. package/src/subscriptions/renewalCycleRefusalMechanism.ts +215 -0
  349. package/src/subscriptions/renewalIdentity.ts +5 -0
package/README.md CHANGED
@@ -4,14 +4,21 @@ Development preview. This package is part of the publishable set with core and o
4
4
 
5
5
  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`.
6
6
 
7
- For the prepared `0.21.0` set, read the [adjacent-release migration and known
8
- limitations](CHANGELOG.md#0210) before selecting the opt-in M05 parity seams or
9
- M06 composition bindings, or the M07 payment selectors. M07 payment truth is complete for this wave; its selectors are default-off. M06 remains incomplete: inventory and shipping entries
10
- are development-preview surfaces, with managed-host proof classes pending in the
7
+ For the prepared `0.23.0` set, read the [adjacent-release migration and known
8
+ limitations](CHANGELOG.md#0230) before selecting the opt-in parity seams.
9
+ Install the complete native chain through position 76; follow the `0.22.0`
10
+ native-row migration notes. Native delivery alignment stays off or shadow until
11
+ a host composes its automatic-renewal runner with G23 admission.
12
+ M10 subscription renewal/retry (P1 exports, forward controls, P2 stores/executor,
13
+ native N1 SQL landed) and M09 invoicing selection/type-only contracts (no SQL)
14
+ are **EXPERIMENTAL, INCOMPLETE and DEFAULT-OFF**, not for adopter activation.
15
+ No runner is activated; G23/N1 host obligations remain pending.
16
+ M06 managed-host proof classes remain pending in the
11
17
  [M06 parity ledger](../../docs/platform/plans/oss-m06-stock-reservations-delivery.md#parity-pending-rows).
12
- The size gate compares the prepared `0.21.0` set with the published `0.20.0` tarball;
13
- preparation, offline adapter evidence and a passing size cap grant no publication
14
- or provider-account certification.
18
+ Size comparison uses the published `0.22.0` tarball. Preparation and offline
19
+ adapter evidence grant no publication or provider-account certification.
20
+
21
+ Longer module recipes live in the [platform package reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md).
15
22
 
16
23
  ## Package surface
17
24
 
@@ -34,7 +41,11 @@ or provider-account certification.
34
41
  | `./communications/contracts` | Pure renderer, block builders, copy-injected commerce/subscription factories and email/newsletter/Auth/intake/receipt types; no Zod, Node or provider runtime imports |
35
42
  | `./payments/stripe` | Opt-in Node payment example with an injected structural client, verified observations and purpose-sensitive readback; no SDK dependency or default activation. |
36
43
  | `./payments/tpay` | Opt-in Node payment example with injected HTTP/certificate I/O, Model O aliases and verified observations; no default activation. |
44
+ | `./fulfillment/omnipack` | Opt-in Node fulfillment example with injected I/O; default-off. |
37
45
  | `./payments` | Experimental prepared-attempt ordering with injected persistence, execution and failure policy; contracts at `./payments/contracts`. |
46
+ | `./fulfillment`, `./fulfillment/contracts` | [Experimental fulfillment services, contracts and status canon](../../docs/platform/ARCHITECTURE_AND_EXTENSIONS.md#fulfillment-contracts). |
47
+ | `./subscriptions`, `./subscriptions/contracts` | Default-off, incomplete; [experimental subscription contracts and renewal port](../../docs/platform/ARCHITECTURE_AND_EXTENSIONS.md#subscription-contracts). |
48
+ | `./invoicing`, `./invoicing/contracts` | Default-off, incomplete invoicing selection and type-only contracts; no SQL or activation. |
38
49
  | `./inventory` | Experimental schemas/ports, handlers, native stores, projection, injected forecast and SQL descriptor; `./inventory/contracts` DTOs. |
39
50
  | `./catalog` | Experimental neutral catalog schemas, drafts, reads, media source packs and publication ports |
40
51
  | `./catalog/contracts` | Dependency-free catalog DTOs, media resolver, authority and canonicalization helpers |
@@ -453,458 +464,23 @@ in both resolution modes with all three optional peers absent.
453
464
 
454
465
  ## Identity import candidate
455
466
 
456
- The OIDC API adds `createOidcIdentityVerifier`,
457
- `deriveOidcPrincipalId`, `createPostgresAccountLinkStore` and
458
- `identityOidcReadiness` from `@openlup/platform/identity`, which also exports
459
- `OIDC_FAILURE_CODES` and `OidcFailureCode` for hosts. The browser-shared
460
- `@openlup/platform/identity/contracts` entry excludes OIDC refusals.
461
- Inject the host's selected JWT library through `IdentityJwtLibraryLoader`.
462
- Discovery and rotating keys load only on verification or readiness. The opt-in
463
- direct composition uses normal reconcile with an explicit email-trust policy,
464
- authenticated actor reads and live operator membership. Managed storage requires
465
- native federation sessions and refuses raw upstream-token composition. Run
466
- `node tests/postgres/runOidcIdentityConformance.mjs` from the repository root with
467
- its cached pinned issuer and local prerequisites; the [OIDC recipe](../../docs/platform/IDENTITY.md#real-issuer-oidc-recipe)
468
- owns timing, refusal, session and certification boundaries. There is no schema or
469
- default login flow change; existing static session verification and default
470
- reference/browser flows retain their runtime behaviour.
471
-
472
- The existing `IdentityJwtLibrary.jwtVerify` contract widens with optional
473
- `currentDate?: Date` and `clockTolerance?: number` verify options and now returns
474
- `{ payload: IdentityJwtClaims }`, whose claims interface includes a string index
475
- signature. **Migration:** hosts implementing or typing their own
476
- `IdentityJwtLibrary` or `IdentityJwtLibraryLoader` must accept the optional verify
477
- options and return claims as `IdentityJwtClaims`.
478
-
479
- The direct operator API adds `createPostgresOperatorIdentityStore`,
480
- `createOperatorSessionService`, `createOperatorIdentityVerifier`,
481
- `createOperatorAdminAuth` and `createOperatorAuthHandlers` to `./identity`.
482
- `./identity/contracts` exposes strict operator challenge/session schemas and
483
- `OperatorBrowserAuthPort` without a server or provider import. Challenge delivery
484
- and session signing use the existing structural ports. Operator handlers send
485
- the padded generic acceptance before awaiting mailbox delivery, keeping delivery
486
- latency out of the response. Custom HTTP composition uses the session service's
487
- optional acceptance callback for the same ordering. Restoration reads preserve
488
- in-flight browser redemption; explicit sign-out still cancels it. Active operator
489
- login needs no pending invitation and preserves membership and invitation history. The new store's public
490
- signature exposes no driver types and loads its optional driver only on use.
491
-
492
- Apply the complete direct catalogue through position 68 before enabling human
493
- login; `sql/20261018180000_identity_operator_challenges.sql` is its exact projection.
494
- Configure a distinct operator audience and an adopter deployment route policy:
495
- the public policy refuses all mounted operator routes, including `me`, with
496
- `adopter_policy_required` before input or authentication-binding construction. The reference dispatcher accepts a
497
- session-binding factory through `createReferenceBffDispatch`; use it to compose
498
- separate operator delivery. Caller-supplied operator handlers retain the same
499
- policy boundary. The browser hook consumes guarded auth-port notifications rather
500
- than signing out from a stale post-redemption check. Use the
501
- explicit bootstrap/prune commands in the [identity guide](../../docs/platform/IDENTITY.md#direct-human-login).
502
- The bounded reference browser builds do not mount the admin shell; application
503
- composition must mount the provided pages and hook. First redemption activates the existing invitation and consumes the challenge in
504
- one transaction. Live membership, not a JWT role, authorizes each request. The
505
- cold consumer includes both identity entries and the new adapter's missing-peer
506
- refusal; real concurrency and upgrade proof needs the complete PostgreSQL chain.
507
-
508
- Creating a client/contact records commerce contact data, not an authentication
509
- identity. Creating an auth user provisions a principal. Neither a typed address
510
- nor a soft-account link proves mailbox ownership; reconcile may create a contact
511
- for an existing authenticated principal without creating that principal.
512
-
513
- Customer soft-account provisioning now creates unconfirmed auth users
514
- (`email_confirm:false`). The soft-account linker retains create-first lookup,
515
- normalized duplicate recovery and conditional linking. Checkout and paid-order
516
- retry are adopter composition that must call the linker. Failed links retain
517
- the provisioned identity for retry. Customer magic links keep
518
- `shouldCreateUser:false`: captured mailbox proof confirms that existing user;
519
- unknown addresses cannot sign themselves up through this path.
520
-
521
- The managed link store requires an injected `emailTrustPolicy`, assessed before
522
- creation or linking an existing identity by email. Unsafe or unavailable settings
523
- return a non-fatal soft-account refusal (`EMAIL_TRUST_ENVELOPE_REFUSED` or
524
- `EMAIL_TRUST_SETTINGS_UNAVAILABLE`) without creating an identity or link. Matching
525
- existing links retain their replay behaviour. The reference adapter binds managed
526
- settings assessment regardless of the selected bundle.
527
-
528
- **Migration:** soft-account provisioning requires a trusted envelope: automatic
529
- email confirmation disabled and every enabled non-email provider explicitly
530
- declared email-verifying. Automatic signup can otherwise confirm an unconfirmed
531
- user and issue a session to someone who merely knows the contact's address.
532
- Pass the policy to `createSupabaseClientAuthLinkStore(client, emailTrustPolicy)`;
533
- custom `ClientAuthLinkStore` implementations must expose `emailTrustPolicy`.
534
- An adopter may explicitly bind `createVerifierResultOnlyEmailTrustPolicy()` when
535
- its own trust boundary supplies the guarantee. Ensure the selected Auth installation can deliver and verify the
536
- first-login link for an existing unconfirmed user. Run the documented joint local conformance
537
- command after building core/platform. Existing identities, contact links,
538
- subscription references and migration history are not rewritten.
539
-
540
- Managed verification now requires the confirmation timestamp. Email-derived
541
- reconcile requires an injected `emailTrustPolicy`. Managed hosts share
542
- `createManagedEmailTrustPolicy` with `identityEmailTrustReadiness`; it reports
543
- module `identity` using core's existing codes. Hosts retaining verifier-only
544
- admission explicitly bind `createVerifierResultOnlyEmailTrustPolicy()`.
545
- See the [identity policy and migration](../../docs/platform/IDENTITY.md#responsibility-and-composition)
546
- for the empty provider allowlist, cache/deadline, 403/503 failures and the opt-in
547
- `node tests/postgres/runIdentityEnvelopeConformance.mjs --phase email-trust` and
548
- `node tests/postgres/runIdentityEnvelopeConformance.mjs --phase joint` prerequisites
549
- and conformance scope. Both phases replay the committed managed chain, including
550
- the identity capabilities forward, and prove association under the shipped managed
551
- reference grants.
552
- Construction and imports perform no settings read or SDK initialization.
553
-
554
-
555
- The `./identity` server entry imports the existing identity engine, authorization,
556
- profile readers, session adapters and BFF factories into one capability. Its
557
- `./identity/contracts` entry is declared browser-safe and currently exposes the
558
- customer auth port, value types and provider parser. Runtime-schema extraction
559
- is pending the contracts-boundary choice described in the
560
- [identity owner page](../../docs/platform/IDENTITY.md). Both entries remain an
561
- unpublished development-preview import candidate.
562
-
563
- Application composition supplies SDK clients/loaders, feature admission, redirect
564
- policy, rate limiting, messages, sender and deployment URLs. Factories use the
565
- foundation BFF envelope and accept the application's observed request-ID reader.
566
- The module depends only on the declared foundation entries, without changing the
567
- artifact's rail kind. Its schema contribution requires a host-selected inventory;
568
- its seven SQL files are verbatim projections at canonical positions 11, 12, 29,
569
- 60, 67, 68 and 69, not an independent migration chain. The owner page maps the characterization
570
- witnesses and records the remaining evidence.
571
-
572
- Identity authorizes stored operator roles only when they are `admin` or
573
- `distributor`; null and unknown values return `FORBIDDEN` (HTTP 403). The reference
574
- admin-profile reader reports those rows as non-admin, and admin magic links do
575
- not send for them while retaining the generic accepted response, padding and
576
- quota. Adopters needing legacy role mapping must do it in their own adapter
577
- before passing the role to the package; there is no package fallback option.
578
-
579
- Both managed contact stores match normalized addresses case-insensitively,
580
- including mixed-case stored contacts. Literal matching uses an anchored, escaped
581
- `imatch` database prefilter plus an exact `email.trim().toLowerCase()` comparison
582
- with the normalized input. Unicode regex folding alone cannot establish identity.
583
- Both lookups select email and fetch at most ten candidates. Soft linking selects
584
- the oldest accepted contact; reconciliation requires a single accepted contact
585
- and throws the existing multiple-row error if several remain. A match beyond the
586
- candidate bound is not selected. Injected structural query clients must implement
587
- `filter(column, "imatch", value)` and the bounded array query. The direct customer
588
- challenge already compares `lower(email)` to normalized input; no migration is
589
- needed.
590
-
591
- Magic-link factories default to the shared strict origin resolver. Pass
592
- `redirectOrigins: ["https://example.com", "https://secondary.example.com:8443"]`;
593
- the first configured origin builds the callback and every entry must be an exact
594
- HTTP(S) origin, without credentials, a path, query or fragment (a root trailing
595
- slash is accepted). Request headers never authorize an origin. Missing or invalid
596
- configuration returns BFF `UPSTREAM_UNAVAILABLE` (503), with details reason
597
- `magic_link_origin_not_configured`, before provider access. Customer `returnTo`
598
- is normalized to a same-origin relative path; unsafe targets are omitted for the
599
- callback's default landing page. An adopter needing its existing policy can keep
600
- passing `resolveOrigin`; that explicit injection overrides the default. See the
601
- [identity redirect contract](../../docs/platform/IDENTITY.md#magic-link-redirect-policy)
602
- for reference configuration and migration.
603
-
604
-
605
- ### Operator invitations
606
-
607
- `identity/contracts` exposes distinct direct pending-invitation and managed
608
- active-membership results. Matching runtime schemas remain in the server entry.
609
- The admin-action port returns `OperatorInviteResult`, a union of those results.
610
-
611
- `createDirectOperatorInvitationStore` provides the new pending, active, expired and
612
- revoked lifecycle in its trusted PostgreSQL transaction lane, including ordered
613
- membership locks and atomic membership/audit writes. Direct callers inject the
614
- store and a parsed TTL. `createDirectOperatorIdentityDirectory` commits principal
615
- creation/reuse separately. Apply the complete direct catalogue through position
616
- 67; the byte-identical package projection is for inspection and composition, not
617
- a standalone fresh chain. Direct human acceptance is a trusted command,
618
- unmounted from machine authentication.
619
-
620
- Managed hosts use `createInviteAdminUserGateway().activateMembership` in
621
- `runInviteAdminUserUseCase`. Insertion immediately creates active `admin_users`
622
- membership with invitation provenance; it omits `is_machine_actor` and relies on
623
- the database default false. The result carries principal ID, role, active state
624
- and `MEMBERSHIP_CREATED` or `ALREADY_ACTIVE`, without pending timestamps or an
625
- invitation ID. Identical repeats and concurrent insert losers return the existing
626
- membership without a second notification. Role differences conflict; revoked
627
- members refuse with `MANAGED_REINVITE_UNSUPPORTED`. Failures retain identities
628
- for retry, including after notification failure. No Auth metadata store,
629
- first-entry acceptance, expiry or compensation is used. Magic-link eligibility
630
- requires active membership and a known role. Authorization, removal and admin
631
- `me` retain their actor bindings without a service key for lifecycle state.
632
-
633
- **Migration:** direct hosts can adopt the new pending lifecycle by applying
634
- `20261018120000_identity_operator_invitations` after the existing direct catalogue
635
- and composing the store, trusted human acceptance and parsed TTL. Existing
636
- memberships are preserved. Managed immediate activation is retained; managed
637
- consumers must now parse the structured active result and its
638
- `MEMBERSHIP_CREATED`/`ALREADY_ACTIVE` codes instead of message-only success.
639
- Duplicates return existing membership rather than `ALREADY_ADDED`, and
640
- notification failure returns 503 `INVITATION_NOTIFICATION_FAILED` while keeping
641
- membership active. Managed pending/expiry remains a compatibility gap requiring
642
- a separate transactional store and reviewed forward. No managed SQL, RPC or SDK
643
- dependency is added. See the
644
- [identity lifecycle owner](../../docs/platform/IDENTITY.md#operator-invitation-lifecycle).
645
-
646
- The managed chain's identity capabilities forward
647
- `20261018160000_identity_service_role_capabilities.sql` grants `service_role`
648
- SELECT(email) and INSERT(id, email, role, membership_state, membership_provenance,
649
- membership_accepted_at) on `admin_users`.
650
- The opt-in managed conformance replays the complete committed chain with ambient
651
- default ACLs removed and adds no grant. It proves immediate activation,
652
- repeat/concurrent recovery and revoked-member refusal under the shipped grants.
653
- It does not establish managed/direct lifecycle parity.
654
-
655
- With a fresh local managed stack running, export its API URL, service key and
656
- PostgreSQL owner (`supabase_admin`) connection URL as `OPENLUP_MANAGED_CONFORMANCE_URL`,
657
- `OPENLUP_MANAGED_CONFORMANCE_SERVICE_KEY` and
658
- `OPENLUP_MANAGED_CONFORMANCE_DATABASE_URL`, then run from the repository root:
659
-
660
- ```sh
661
- npm --workspace @openlup/platform run build
662
- node --import tsx tests/postgres/operatorInvitationManaged.conformance.ts
663
- ```
664
-
665
- The module refuses non-loopback endpoints, an already-installed public schema,
666
- and existing synthetic fixture identities. It retains synthetic identities;
667
- discard the disposable stack after the run. Its database owner connection must
668
- be able to replay the committed prerequisites, baseline and ordered forwards.
467
+ `./identity` provides server identity services; `./identity/contracts` supplies browser-shareable contracts.
468
+ See the [identity recipe](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#identity-import-candidate) for composition, migrations and operator invitations.
669
469
 
670
470
  ## Personal data
671
471
 
672
- The experimental identity entry exposes `createPersonalDataContributorRegistry`,
673
- `createIdentityPersonalDataContributor`, `createPrivacyOperations`,
674
- `exportPersonalData`, `erasePersonalData`, `createPrivacyExportHandler` and
675
- `createPrivacyEraseHandler`. Browser requests, versioned contributor documents and
676
- receipts come from `@openlup/platform/identity/contracts`. Register every required
677
- contributor explicitly, with its owned fields, assessment, erase/retain operation
678
- and remote/retention obligations. Missing required owners refuse erasure; export
679
- reports missing coverage. This capability erases identity-owned data only.
680
-
681
- Direct hosts compose `createPostgresPrivacyUnitOfWork` and
682
- `createPostgresPrivacyStore` with the identity contributor and their domain vetoes
683
- using the same executor. The reference subscriptions contributor holds a relation
684
- lock through commit, refusing active and paused subscriptions without changing
685
- them. `IdentityPrivacyPolicy.retainedContactFields` names explicit retention
686
- owners for populated opaque columns; unknown ownership refuses. The reference
687
- retains lifecycle/acquisition fields, and refuses nonempty metadata or external
688
- references until an owner declares their disposition.
689
-
690
- Migration: apply the complete direct catalogue including
691
- `20261018190000_identity_privacy_erasures` before using privacy or the updated
692
- customer challenge store. The forward appends one receipt table at position 69
693
- without grants or stored functions. Direct erasure pseudonymizes identity-owned
694
- fields, deletes challenges and outstanding invitations, uses guarded membership
695
- revocation, clears only the selected contact's direct principal link, and commits
696
- an idempotent audit receipt atomically. Contact IDs and managed auth links never
697
- change. Failed writes roll back. Retained audit references are pseudonymous, not
698
- an assertion of anonymization. Already-issued tokens may remain valid until expiry.
699
- Customer challenge issuance and redemption reject a receipt for either the
700
- contact or principal under the same transaction-held challenge relation lock as
701
- erasure, including late challenges inserted after cleanup. Hosts must use the
702
- package adapters; calling the retained raw challenge SQL functions directly
703
- bypasses this erasure receipt fence.
704
-
705
- Managed hosts compose `createManagedPrivacyStore` with their structural service
706
- client for export. Coverage explicitly excludes inaccessible country and
707
- identity history/receipt fields. Managed erasure refuses with
708
- `MANAGED_PRIVACY_ERASURE_UNAVAILABLE`: a managed adopter must provide its own
709
- erasure path. The committed grants and structural client cannot provide the
710
- required mutations and atomic receipt. This change adds no managed forward or
711
- erasure grants. Provider identity is never deleted; any future composed provider
712
- erasure must disable it after committed local success. The managed refusal here
713
- occurs before reaching any provider mutation.
714
-
715
- The reference mounts authenticated human-admin export/erase POSTs and an Admin
716
- Settings readback panel. Direct and managed mounts require the adopter deployment
717
- policy under admin mutation risk; the public default returns
718
- `adopter_policy_required` before body/query reads, and direct mounts also refuse
719
- before authentication or privacy binding construction. The shipped dispatcher mounts
720
- both routes for managed bundles even when its caller supplies no routes. After admission,
721
- exports and receipts stay in memory with no-store
722
- responses. The maintenance `prune-challenges` command prunes separate bounded
723
- operator/customer batches. See [identity privacy](../../docs/platform/IDENTITY.md#identity-personal-data)
724
- for refusals, token limits and retained obligations.
725
-
726
- The complete direct conformance is included in
727
- `npm test -- tests/postgres/operatorIdentityUpgrade.test.ts` from the repository
728
- root after normal setup. A maintainer host resource broker is optional.
729
- For managed conformance, supply the same three `OPENLUP_MANAGED_CONFORMANCE_*`
730
- local disposable-stack settings described for operator invitations, with
731
- `OPENLUP_MANAGED_CONFORMANCE_DATABASE_URL` set to the database owner
732
- (`supabase_admin`) connection, then run
733
- `node --experimental-strip-types tests/postgres/identityPrivacyManaged.conformance.ts`.
734
- Use a fresh public schema and reset the disposable stack between proofs; the
735
- managed privacy proof replays the committed chain without fixture erasure grants.
736
- Replay through node-postgres omits only the psql-only pg_dump `\restrict` and
737
- `\unrestrict` guard lines; all migration SQL remains unchanged.
738
-
739
-
740
- Reference startup can compose identity through `createReferenceIdentity` and
741
- `startPublicReferenceServer({ identity })`, with explicit route functions,
742
- selected adapters, trusted schema/migration observation and the bundle-specific
743
- inventory. It consumes email-trust readiness before listening, and rejects
744
- unknown or unsatisfied candidates. Direct reconcile reads the existing actor
745
- link; direct invite/remove select the pending-invitation stores. The default
746
- static reference and browser page sets remain unchanged. See the
747
- [composition contract](../../docs/platform/IDENTITY.md#responsibility-and-composition).
748
-
749
- Both identity entries already belong to the public export map and build output;
750
- artifact availability does not imply registry publication or release activation.
751
- The cold installed-artifact consumer imports both entries without optional peers,
752
- compiles contracts without driver types, and invokes every driver-owning direct
753
- identity adapter for its missing-peer refusal. Managed factories consume
754
- structural clients. Server declarations compile after peer selection. Full
755
- installed-artifact and database proof require the existing supervisor-run package
756
- consumer command and an owned disposable database.
757
-
758
- The managed identity service-role capabilities forward in the committed chain
759
- supplies client link writes and operator membership insert/email-read
760
- permissions; the local conformance runners add no fixture grant. No migration is
761
- added by reference composition.
762
-
472
+ The experimental identity entry provides contributor-based personal-data export and erasure.
473
+ See the [personal-data recipe](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#personal-data) for composition, refusals and retained obligations.
763
474
 
764
475
  ## Disposable identity composition
765
476
 
766
- The reference application's opt-in identity shell consumes the existing
767
- `./identity` and `./identity/contracts` exports without changing their maturity
768
- or publishing a registry version. It reuses the customer/operator pages and
769
- captured-delivery port, with a private local mailbox and administrator privacy
770
- panel. Its explicit runtime must supply actual routes and readiness admission;
771
- the shell refuses a missing composition. See the
772
- [identity reference guide](../../docs/platform/IDENTITY.md#disposable-identity-reference)
773
- for both-bundle commands, the committed managed grants and installation limits.
477
+ The opt-in reference identity shell consumes the existing identity exports with explicit routes and readiness admission.
478
+ See [disposable identity composition](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#disposable-identity-composition) for its boundary and reference guide.
774
479
 
775
480
  ## Communications import
776
481
 
777
- For adoption from `0.16.0`, follow the [0.17.0 Migration guidance](CHANGELOG-HISTORY.md#0170) (source repository)
778
- for the complete package set, canonical SQL installation and host-owned bindings.
779
-
780
- M04 P1 relocates the existing public implementation without changing its reference
781
- outputs. The reference shims bind the existing renderer, egress resolver, origin
782
- defaults, delivery-shaping policy and receipt transaction lane. The package does
783
- not select a deployment, mount a route or schedule another executor.
784
- `createCommunicationsContribution` requires the host's version and schema
785
- inventory; supplied handlers, schedules, routes and ports describe only that
786
- host's selection.
787
-
788
- `COMMUNICATIONS_MIGRATIONS` projects three existing canonical units byte for byte:
789
- comms outbox (position 2), transactional receipts (9) and communications control
790
- plane (20). This sparse list is not a standalone migration chain. Apply the full
791
- selected canonical prefix through its existing runner; importing the module does
792
- not apply SQL or advertise missing managed/direct capabilities.
793
-
794
- Browser previews retain their reference renderer, content defaults and template
795
- policy. The Auth hook receives that same renderer through its reference shim.
796
- The standard Auth webhook and the maintained HTTP mail provider verifiers keep their separate signature
797
- formats and clocks; the generic helper added to `./http` replaces neither.
798
- E2 is applied: the payment webhook module delegates these five generic helpers.
799
- `readRawBody` is the same package function object with its original declared
800
- `(req: VercelRequest) => Promise<string>` signature; the other four exports are
801
- plain re-exports. The payment provider verification and its replay tolerance stay local.
802
- The maintained mail transport, credentials, callback verification/mapping,
803
- poll read/mapping, timeline and send-ledger adapters remain in reference source.
804
- B1 changes only the four raw-injection guard sites in the reference delivery
805
- adapters and the approved invoice test fixture; the concrete client and all
806
- other vendor-directory files retain the comparison-base bytes. The neutral
807
- `./communications` entry exposes transport/result contracts and capture without
808
- concrete mail wiring. The platform ships opt-in vendor adapter subpaths;
809
- default wiring includes none, and adopters choose or replace them.
810
- The type-only `CommunicationProvider<Provider>` and `EmailMessageReadModel<Provider>`
811
- accept host vocabulary; reference types retain their original literal.
812
-
813
- `createGuardedEmailTransport({ providerKind, policy, send })` is the network
814
- adapter constructor. At each send it awaits a fresh host policy, validates the
815
- whole decision and enters the sender only for a coherent `production`,
816
- `sandbox_direct` or `sandbox_sink` decision. The sender receives the effective
817
- recipient and a frozen context with intended recipient, host-selected credential,
818
- mode, reason and environment tag. It must consume that context when selecting
819
- credentials and emitting provider metadata. The neutral entry reads no environment
820
- and contains no provider client. Opt-in adapters consume this same guard and
821
- host-selected context. Missing/throwing policy, unknown modes, mismatched
822
- recipients/tags, blank credentials or unsupported fields fail with status zero,
823
- no identifier and bounded error codes. Reasons are lower-case token codes up to
824
- 80 characters. One unadorned `local@domain.example` recipient mailbox is required;
825
- whitespace, lists, display names and local-only domains are refused on this new
826
- alternate-transport policy boundary.
827
-
828
- `blocked` returns failure; explicit `drop` returns terminal suppression with no
829
- send, no identifier and an ineligible sent timestamp. Arbitrary injected objects
830
- are refused by `guardEmailTransport`; a provider name or copied capture shape
831
- cannot establish admission. Package-created capture retains its ordered envelopes
832
- and synthetic identifiers with no network effect. Capture acceptance remains
833
- local acceptance, never evidence of external delivery.
834
-
835
- `admitPolicyEnforcedEmailTransport` is the trusted host bridge for a transport
836
- that already enforces egress internally, as the maintained reference client does.
837
- The package registry owns its identity; this bridge performs no second routing
838
- or credential decision. It is a composition trust boundary, not a sandbox for
839
- host code: callers must not admit an unguarded network sender. New adapters should
840
- use the validating constructor above. The reference default retains its original
841
- sink/drop policy, key selection, optional payload fields, headers, signal and
842
- result/error semantics. `createAuthEmailTransport` preserves the Auth envelope
843
- mapping and admission; raw Auth closures are refused before their send method.
844
- Admin/control and required-audit ordering stay at their existing callers.
845
- No egress result authorizes a subscription-state or delivery-cycle mutation.
846
-
847
- `processEmailObservation` accepts already authenticated, decoded and environment-admitted
848
- input. It looks up a local send, constructs evidence only when found, applies one
849
- observation and records best-effort telemetry. Lookup and apply failures propagate.
850
- `runDeliveryReconciliation` polls candidates sequentially, rotates every non-404
851
- read, and delegates consecutive failed-404 abandonment at threshold three to the
852
- store. Rotation failure is counted without dropping delivery truth; apply failure
853
- continues the batch. Candidate-query, read and not-found-store throws propagate.
854
- The host classifies protocol snapshots after rotation and passes recipient/evidence
855
- through unchanged. The existing reference domain entry points use both engines;
856
- routes and schedules remain the same.
857
-
858
- Neither engine writes suppression or subscription state. Both callback and poll
859
- composition retain `communication_update_email_delivery_from_provider` as the
860
- single durable convergence/suppression writer. These ports add no in-memory
861
- replay authority, database store or second executor. Legacy transport identifier
862
- fields remain compatibility residue; new ports use `messageId`.
863
-
864
- `createCommunicationPurposeRegistry` composes immutable exact identifiers with a
865
- mandatory `marketing` or `non-marketing` classification. Its built-ins cannot be
866
- redeclared. Existing policy, token and newsletter schema calls keep their finite
867
- defaults. Passing a registry to policy evaluation, token verification or
868
- `createNewsletterIntegrationSchemas` recognizes its identifiers without granting
869
- permission. Custom marketing purposes still require a grant and respect
870
- suppression; built-in tester pause and permission rules stay in force.
871
-
872
- `createRegisteredPublicPreferenceTokenPort` requires an explicit host persistence
873
- function and passes the exact purpose and frozen classification to it. It creates
874
- no sync event. Stock managed permission and newsletter-sync tables retain their
875
- finite CHECKs; registering a purpose does not expand those stores. Additional
876
- persistence and schema requirements belong to the adopter. No new purpose, table,
877
- migration, preference UI, URL or default fan-out is installed.
878
-
879
- `processNewsletterWebhookEvent` supplies the existing event → permission →
880
- settlement sequence behind neutral ports. Reference HTTP admission and signature
881
- mapping stay local. Explicit registered purposes survive permission writes;
882
- purpose-less feedback still targets exactly the two existing marketing purposes.
883
- Verified opt-in, suppression and replay rules are unchanged. Registered dispatch
884
- checks the batch's purposes before provider effects and retains claim tokens,
885
- echo and capability skips, retry behavior and counters. Sync-settled and accepted
886
- receipts are distinct from delivered evidence. Existing job admission, binding,
887
- leases, finish-run linkage and operator readback retain their host composition.
888
- No shared sender pipeline is added: required audit and best-effort send paths
889
- keep their distinct ordering and failure semantics.
890
-
891
- `MarketingAutomationProviderPort` and `MarketingAutomationStorePort` describe
892
- explicit scope, claim/generation fences, admission/deadlines, idempotency,
893
- observations/history and ambiguity/backoff. The synthetic substitute-provider
894
- conformance suite is an executable contract, not an installed worker or a remote
895
- provider certification. Evidence carries opaque references; remote feedback does
896
- not grant local consent. No trigger catalogue, schedule or provider activation
897
- is supplied.
898
-
899
- The required selection retains the moved-code witnesses and neutral package
900
- characterization tests. The package W1 hook reader witnesses the Auth composition;
901
- provider-specific reference test paths remain in the complete suite. The
902
- [M04 ledger](../../docs/platform/plans/oss-m04-communications-triggers.md#verification-ledger)
903
- records counted cases, separate boundary iterations and local timing provenance.
904
- The clean-commit artifact gate enforces all merged caps, including the owner-read, measured limit on the complete contracts entry. Artifact admission still needs a
905
- clean supervisor commit.
906
- See the [M04 plan](../../docs/platform/plans/oss-m04-communications-triggers.md)
907
- for scope, later waves and verification limits.
482
+ `./communications` provides host-composed communications services; `./communications/contracts` supplies pure content and browser contracts.
483
+ See the [communications recipe](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#communications-import) for migration, email rendering and native operations.
908
484
 
909
485
  ## Package artifact limits
910
486
 
@@ -917,145 +493,6 @@ for measured sizes, current caps, the S1 baseline refresh and refusal remedies.
917
493
  Artifact checks require a clean package directory; `--manifest-only` supplies no
918
494
  artifact evidence.
919
495
 
920
- ### Pure email content and browser rendering
921
-
922
- `./communications/contracts` now exports `renderEmail`, the nine existing block
923
- constructors, `guideCardBlock` and per-template content factories.
924
- Each `create*ContentFactory` binds host-selected copy plus only the pure helpers
925
- it uses: order-reference formatting, payment-cause wording or marketing footer.
926
- Localized review routes remain in the reference helper.
927
- In P3 no copy pack, brand, locale choice, environment reader, provider client or
928
- sending policy moved into this entry. B2 adds the explicit neutral defaults below. The existing email DTOs remain its canonical types.
929
- Reference `petName` compatibility inputs are translated to neutral `contextName`
930
- by their existing facades. Complete subjects, preheaders, ordered blocks and
931
- HTML/text remain byte-identical, including omitted and explicit optional fields.
932
-
933
- Browser previews continue through those facades to contracts values only. Auth
934
- uses its existing server hook factory with the same host renderer injection;
935
- its inactive public content binding still refuses with 503. Standard Auth,
936
- mail callback, integration-event and generic HTTP verification remain separate
937
- policies with their existing raw-byte and replay behavior. No crypto refactor,
938
- new entry, dependency or graph edge is part of P3.
939
-
940
- The contracts conformance test compiles the complete entry with no Node types
941
- and checks its value inventory and import closure. The cold consumer repeats the
942
- exact inventory and renders with fetch forbidden and optional peers absent,
943
- retaining all other consumer checks. Browser size measures every runtime export
944
- of the built entry through `browserEntryBytes`; it never measures a tree-shaken
945
- consumer subset. See the M04 ledger for the measured size, owner-read cap and
946
- working-tree versus signed-candidate evidence limits.
947
-
948
- P3's complete built contracts entry measures **5,992 B minified+gzip**;
949
- the owner-read cap is **11,776 B**, rounded to the nearest 512 B at about
950
- twice that measurement. Only this browser limit changes. Existing pack classes,
951
- other browser limits and clean-candidate artifact checks remain binding.
952
-
953
-
954
- M04 B2 adds four default factories in this same pure contracts entry:
955
- `createInvoiceDocumentContentFactory`, `createRoleNotificationContentFactory`,
956
- `createInquiryContentFactory` and `createOptOutContentFactory`. Each accepts an
957
- optional complete bilingual copy replacement; each content call takes an explicit
958
- `pl`/`en` locale. Invoice takes resolved order/document references, kind and account
959
- URL; role takes role, operator URL and optional pending expiry. Inquiry builds
960
- receipt/notice blocks from caller details, signoff and URL without sending or
961
- promising a response time. Opt-out returns display strings for seven outcomes;
962
- it verifies no token and writes no consent. Hosts own brand, locale selection,
963
- URLs, policy and delivery.
964
-
965
- The reference invoice adapter defaults to its byte-identical Polish output; explicit
966
- construction locale EN maps to `/account?sekcja=orders`, while the production
967
- composition still omits locale. All existing role outputs remain identical.
968
- The reference opt-out page now selects Polish/EN throughout, escapes display values,
969
- and uses neutral selected-communications/service-message wording. Its methods,
970
- verification, purpose allowlist, durable RPC, headers and statuses are unchanged.
971
- Generic inquiry is only a pure binding; the existing private-label sender stays
972
- unchanged. Invoice/role gain Polish canon previews; no sender/registry activation.
973
- See the [complete B2 expectation ledger](../../docs/platform/plans/oss-m04-communications-triggers.md#b2-changed-expectations-and-preservation)
974
- and [default conformance tests](test/communications/contentDefaults.test.ts).
975
- The measured B2 contracts entry is 8,210 B minified+gzip under the unchanged
976
- 11,776 B cap; this is a local built-entry measurement, not release admission.
977
-
978
- ### Native communications operations (development preview)
979
-
980
- The server entry `@openlup/platform/communications` additionally exports
981
- `createPostgresDeliveryReconciliationPort`, `createPostgresCommunicationSyncStore`,
982
- `createPostgresNotificationRecipientsPort` and `createPostgresConsentEvaluator`.
983
- Install the complete canonical manifest through position 70 before selecting
984
- these factories. `COMMUNICATIONS_MIGRATIONS` now projects positions 2, 9, 20 and
985
- 70; it remains a sparse inventory, not an installer. Missing schema/configuration
986
- is an error, never an empty queue or an allow decision.
987
-
988
- Each factory owns a capability-local, role-free transaction lane and lazy `pg`
989
- pool, with `close()` for host cleanup. Only a trusted host may hold these owner
990
- credentials. Effective PUBLIC/browser table, column and inherited privileges
991
- cause refusal; the CREATE-only forward intentionally changes no old ACL or role.
992
- Do not expose a factory or its database lane to browser callers. The directory
993
- requires a verified active human operator, live communications authorization and
994
- absence of machine authority in the same transaction as each operation.
995
-
996
- A host registers `evidence: "network_accepted"` only after actual network
997
- acceptance, with a unique source key and binding. Capture is never registered as
998
- a network target. Polls and admitted callbacks call the same `applyObservation`
999
- writer; observation-key replay must preserve the immutable fact. Readback keeps
1000
- acceptance, observed state, attempt/404 counts and abandonment separate. Only
1001
- three consecutive 404s abandon a candidate; abandonment is not failed/delivered.
1002
- Bounce/complaint writes the authoritative fingerprint's suppression atomically.
1003
- No subscription or renewal state is changed.
1004
-
1005
- For newsletter sync, inject `rail: db => createPostgresOutboxStore(db)` from
1006
- `@openlup/outbox/postgres` in host composition. `db` is the current transaction,
1007
- so claim commits before I/O and rail ack and sidecar settlement commit together.
1008
- `registerWork` creates one existing-outbox identity for a source and target
1009
- binding. Successive preferences for one contact/target share the rail aggregate,
1010
- so newer work cannot overtake older unprocessed work. Configure a distinct
1011
- binding per target/provider, and exclude
1012
- `nativeSyncEventType(binding)` from generic dispatch registries. Invoke only
1013
- `runCommunicationSyncDispatch` with an explicit neutral membership provider.
1014
- The sidecar cannot claim work and has no lease or drainer. A membership settlement
1015
- records sync progress, never email delivery; remote exactly-once effects are not
1016
- promised across a process crash. There is no automatic backfill or activation.
1017
-
1018
- Native consent evaluates registered P4 policy against the authoritative native
1019
- permission and persists the decision before returning its id. Admin notices need
1020
- an active source-bound notification recipient. Optional `testerPaused` reads
1021
- host-owned authoritative pause state inside that transaction; omitted means no
1022
- pause policy. The capability explicitly declares `managedFrequencyCaps: false`,
1023
- `legacyContactTouching: false`, `sendTimeFence: false`: managed 16-hour / 2-day /
1024
- 4-week caps and legacy contact-touching are excluded. Evaluation does not fence a
1025
- later send against changed consent. Custom-purpose persistence remains host-owned.
1026
-
1027
- The [callable reference binding](../../server/runtime/communications/communicationsLifecycleBinding.ts)
1028
- selects only `PLATFORM_BUNDLE=node-postgres` with `DATABASE_URL`; it closes pools
1029
- on success/failure and supplies no network/provider default. Existing managed
1030
- HTTP cron/UI routes retain their existing composition. See the
1031
- [B3 expectation inventory](../../docs/platform/plans/oss-m04-communications-triggers.md#b3-native-stores)
1032
- and [real-PG witnesses](../../tests/postgres/communicationsNative.test.ts).
1033
-
1034
- C-compose extends the native delivery store with binding-scoped `findByMessageId`
1035
- and bounded `listEvidence({limit})` (1–100). Existing observation/replay and polling
1036
- methods retain their behavior. `registerPreference` on the native sync store
1037
- commits an authoritative denied/suppressed permission and default-purpose sync
1038
- work together; tester permission adds no marketing work. The trusted
1039
- `registerNativeSyncWorkInTransaction` helper contains the same registration SQL
1040
- used by `registerWork`; standalone input validation still precedes database entry.
1041
- This helper is a trusted host transaction seam: its caller-owned executor must
1042
- already hold the lane's safe effective privileges; the function does not check
1043
- them. Standard native sync factory transactions check
1044
- `public.communication_native_sync_state`, `public.outbox_events` and
1045
- `public.communication_recipient_consents`. The caller owns the transaction and
1046
- must commit or roll back permission, sidecar and existing-rail effects atomically.
1047
- Use a safely admitted lane; the helper grants no claim token or provider authority.
1048
-
1049
- Reference composition remains outside the package: actual installed factories,
1050
- Core readiness, explicit provider ports and host-supplied schedules. Native
1051
- readback and signed-token bridges do not promise managed frequency caps, legacy
1052
- tester-source parity, a send-time fence or a full native network sender. The
1053
- opt-in browser profile adds no npm entry or UI package export.
1054
-
1055
- Source contributors record notable changes in package changelog fragments;
1056
- release preparation assembles the shipped CHANGELOG. Follow the
1057
- [public contribution guide](https://github.com/openlup/openlup/blob/main/CONTRIBUTING.md#development-preview-checks).
1058
-
1059
496
  ## Payments prepared attempts
1060
497
 
1061
498
  `@openlup/platform/payments` exports `executePreparedAttemptMechanism`: validate before durable preparation, refuse prepared replay, dispatch once unless the host proves no charge, and retry one immutable local finalization. The host owns keys, fingerprints, nominal error trust and persistence. An unknown execution never authorizes redispatch. The reference facade retains its existing binding.
@@ -1218,3 +655,59 @@ provenance and failure prose stay absent. Payer, authorization, certificates and
1218
655
  raw bodies never enter the evidence; audit facts do not affect event identity or
1219
656
  fingerprints. The offline M07 P2 conformance witness uses two distinct intents,
1220
657
  attempts, amounts and provider references, with replay and refusal boundaries.
658
+
659
+ ### Reference-support surface
660
+
661
+ The vendor subpaths additionally expose these experimental helpers for the
662
+ reference application's existing host bindings. Each declaration names its exact
663
+ reference consumer and carries `@experimental`: Reference-application support
664
+ surface; may change.
665
+
666
+ | Entry | Additional exports |
667
+ | --- | --- |
668
+ | `@openlup/platform/payments/stripe` | `createStripeSandboxPaymentExecutionAdapter`, `createStripePaymentReconciliationProvider`, `mapStripeIntent`, `mapSetupIntent`, `normalizeStripeFailureEvidence` |
669
+ | `@openlup/platform/payments/tpay` | `createTpayPaymentExecutionAdapter`, `createTpayPaymentReconciliationProvider`, `createTpayHttpClient`, `normalizeTpayFailureEvidence`, `aliasValue`, `ProviderAttemptPreDispatchError` |
670
+
671
+ Types are inferred from those functions; no extra type export or neutral payment
672
+ entry is added. These are the existing contributed implementations, including
673
+ rich execution, recovery and filtered audit carriers. The host still owns SDK
674
+ construction, environment/feature flags, callback/return presentation, account
675
+ readiness and simulator composition. Its prepared-attempt facade re-exports the
676
+ same error class so `instanceof` preserves the no-charge trust boundary.
677
+ The M07 factories' neutral envelopes and capability limits remain unchanged;
678
+ reference-support availability establishes no provider activation or stable API.
679
+
680
+ ## Fulfillment stock evidence replay
681
+
682
+ The fulfillment migration projection additionally includes the native
683
+ `20261022165000_fulfillment_stock_evidence_replay_reopen.sql` forward at canonical
684
+ position 76 in this catalogue. Install the complete chain before stock adoption.
685
+ Matching-fingerprint alert replay refreshes severity/quantities, reopens status and
686
+ clears `resolved_at`, preserving identity, first-seen time and historical resolver
687
+ metadata. Mismatches, including legacy 0.22.0 whole-input fingerprints, still
688
+ raise `23505`; no rewrite is supplied. See the [migration owner](../../docs/platform/DATA_AND_MIGRATIONS.md#module-catalogues-and-installed-histories)
689
+ for upgrade and operational-dependency proof.
690
+
691
+ ## Subscription contracts and renewal port
692
+
693
+ The experimental `./subscriptions` entry exposes hosted renewal mechanisms and
694
+ an explicit native capability descriptor; `./subscriptions/contracts` is
695
+ browser-safe and type-only. The [subscription architecture and recipe](../../docs/platform/ARCHITECTURE_AND_EXTENSIONS.md#subscription-contracts)
696
+ owns the concrete ports, continuity rules, capability refusals and witnesses.
697
+ These entries do not install a store or activate a runner.
698
+
699
+ Native renewal and N1 retry stores accept injected SQL executors and explicit
700
+ snapshot/identity policy. The generic native executor consumes the subscription
701
+ ports; host composition supplies G23, M07, transaction and correlation policy.
702
+ The initial binding preserves case-before-outcome ordering with atomic bookkeeping.
703
+ N1's same-obligation recovery repairs the native decline stall (F16); it does not
704
+ supply M07 prepared-store parity or activate a runner.
705
+
706
+ ## Invoicing contracts
707
+
708
+ Experimental `@openlup/platform/invoicing` exposes `readInvoiceCapabilities`;
709
+ `invoicing/contracts` contains types only. Host selection is explicit and default-off.
710
+ Frozen facts, correction recovery, exact absence, owed duties and host-only fiscal,
711
+ artifact, delivery, payout and owned-history seams are described in the
712
+ [invoicing reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md#invoicing-contracts).
713
+ No store, worker, adapter, route or activation is supplied by this contract step.