@openlup/platform 0.20.0 → 0.22.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 (458) hide show
  1. package/CHANGELOG.md +272 -278
  2. package/README.md +195 -6
  3. package/dist/composition/composeBundle.d.ts +13 -0
  4. package/dist/composition/composeBundle.js +4 -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 +2 -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 +93 -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 +105 -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 +52 -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 +38 -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 +86 -0
  46. package/dist/fulfillment/contracts/store.js +1 -0
  47. package/dist/fulfillment/contracts/sync.d.ts +170 -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 +7 -0
  56. package/dist/fulfillment/dispatchProjection.js +18 -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 +37 -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 +27 -0
  70. package/dist/fulfillment/migrations.js +8 -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 +11 -0
  76. package/dist/fulfillment/observationProjection.js +37 -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 +37 -0
  80. package/dist/fulfillment/omnipack/client.js +162 -0
  81. package/dist/fulfillment/omnipack/index.d.ts +52 -0
  82. package/dist/fulfillment/omnipack/index.js +349 -0
  83. package/dist/fulfillment/omnipack/mappers.d.ts +73 -0
  84. package/dist/fulfillment/omnipack/mappers.js +177 -0
  85. package/dist/fulfillment/omnipack/observation.d.ts +21 -0
  86. package/dist/fulfillment/omnipack/observation.js +57 -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/trackingReferences.d.ts +16 -0
  106. package/dist/fulfillment/omnipack/trackingReferences.js +52 -0
  107. package/dist/fulfillment/paidFulfillmentRecovery.d.ts +67 -0
  108. package/dist/fulfillment/paidFulfillmentRecovery.js +154 -0
  109. package/dist/fulfillment/paidHandoff.d.ts +27 -0
  110. package/dist/fulfillment/paidHandoff.js +86 -0
  111. package/dist/fulfillment/paidHandoffPorts.d.ts +24 -0
  112. package/dist/fulfillment/paidHandoffPorts.js +3 -0
  113. package/dist/fulfillment/postgresDeliveryAlignment.d.ts +4 -0
  114. package/dist/fulfillment/postgresDeliveryAlignment.js +12 -0
  115. package/dist/fulfillment/postgresDispatchStore.d.ts +16 -0
  116. package/dist/fulfillment/postgresDispatchStore.js +44 -0
  117. package/dist/fulfillment/postgresEvidenceReadPort.d.ts +25 -0
  118. package/dist/fulfillment/postgresEvidenceReadPort.js +45 -0
  119. package/dist/fulfillment/postgresPaidFulfillmentRecovery.d.ts +25 -0
  120. package/dist/fulfillment/postgresPaidFulfillmentRecovery.js +26 -0
  121. package/dist/fulfillment/postgresPaidHandoffStore.d.ts +4 -0
  122. package/dist/fulfillment/postgresPaidHandoffStore.js +10 -0
  123. package/dist/fulfillment/postgresShipmentSpine.d.ts +63 -0
  124. package/dist/fulfillment/postgresShipmentSpine.js +232 -0
  125. package/dist/fulfillment/postgresStockSyncPort.d.ts +8 -0
  126. package/dist/fulfillment/postgresStockSyncPort.js +63 -0
  127. package/dist/fulfillment/productReconciliationEvidenceHandler.d.ts +36 -0
  128. package/dist/fulfillment/productReconciliationEvidenceHandler.js +50 -0
  129. package/dist/fulfillment/providerCapabilities.d.ts +9 -0
  130. package/dist/fulfillment/providerCapabilities.js +17 -0
  131. package/dist/fulfillment/providerCommandLedger.d.ts +143 -0
  132. package/dist/fulfillment/providerCommandLedger.js +14 -0
  133. package/dist/fulfillment/providerDispatchAcceptance.d.ts +26 -0
  134. package/dist/fulfillment/providerDispatchAcceptance.js +23 -0
  135. package/dist/fulfillment/providerDispatchError.d.ts +6 -0
  136. package/dist/fulfillment/providerDispatchError.js +5 -0
  137. package/dist/fulfillment/providerDispatchWorker.d.ts +31 -0
  138. package/dist/fulfillment/providerDispatchWorker.js +172 -0
  139. package/dist/fulfillment/providerProductSyncWorker.d.ts +28 -0
  140. package/dist/fulfillment/providerProductSyncWorker.js +122 -0
  141. package/dist/fulfillment/providerReconciliationError.d.ts +9 -0
  142. package/dist/fulfillment/providerReconciliationError.js +17 -0
  143. package/dist/fulfillment/providerReconciliationTerminalSkip.d.ts +2 -0
  144. package/dist/fulfillment/providerReconciliationTerminalSkip.js +6 -0
  145. package/dist/fulfillment/providerReconciliationTimestamp.d.ts +1 -0
  146. package/dist/fulfillment/providerReconciliationTimestamp.js +27 -0
  147. package/dist/fulfillment/providerReconciliationWorker.d.ts +82 -0
  148. package/dist/fulfillment/providerReconciliationWorker.js +151 -0
  149. package/dist/fulfillment/providerStockAvailability.d.ts +13 -0
  150. package/dist/fulfillment/providerStockAvailability.js +51 -0
  151. package/dist/fulfillment/providerStockSyncWorker.d.ts +37 -0
  152. package/dist/fulfillment/providerStockSyncWorker.js +186 -0
  153. package/dist/fulfillment/providerTrackingReferences.d.ts +15 -0
  154. package/dist/fulfillment/providerTrackingReferences.js +23 -0
  155. package/dist/fulfillment/replacementRefusals.d.ts +5 -0
  156. package/dist/fulfillment/replacementRefusals.js +38 -0
  157. package/dist/fulfillment/replacementShipmentHandler.d.ts +5 -0
  158. package/dist/fulfillment/replacementShipmentHandler.js +46 -0
  159. package/dist/fulfillment/schemaCapabilities.d.ts +13 -0
  160. package/dist/fulfillment/schemaCapabilities.js +7 -0
  161. package/dist/fulfillment/shipmentsOverviewHandler.d.ts +16 -0
  162. package/dist/fulfillment/shipmentsOverviewHandler.js +54 -0
  163. package/dist/fulfillment/statusMap.d.ts +2 -0
  164. package/dist/fulfillment/statusMap.js +1 -0
  165. package/dist/fulfillment/trackingProgress.d.ts +1 -0
  166. package/dist/fulfillment/trackingProgress.js +1 -0
  167. package/dist/fulfillment/verifiedIngress.d.ts +52 -0
  168. package/dist/fulfillment/verifiedIngress.js +66 -0
  169. package/dist/payments/adapterConformance.d.ts +8 -0
  170. package/dist/payments/adapterConformance.js +109 -0
  171. package/dist/payments/bindings.d.ts +3 -0
  172. package/dist/payments/bindings.js +17 -0
  173. package/dist/payments/checkoutActivePaymentActionResolver.d.ts +7 -0
  174. package/dist/payments/checkoutActivePaymentActionResolver.js +77 -0
  175. package/dist/payments/checkoutRecoveryPaymentResolver.d.ts +8 -0
  176. package/dist/payments/checkoutRecoveryPaymentResolver.js +87 -0
  177. package/dist/payments/contracts/adapter.d.ts +113 -0
  178. package/dist/payments/contracts/adapter.js +1 -0
  179. package/dist/payments/contracts/conformance.d.ts +155 -0
  180. package/dist/payments/contracts/conformance.js +1 -0
  181. package/dist/payments/contracts/evidence.d.ts +157 -0
  182. package/dist/payments/contracts/evidence.js +1 -0
  183. package/dist/payments/contracts/index.d.ts +10 -0
  184. package/dist/payments/contracts/index.js +1 -0
  185. package/dist/payments/contracts/preparedAttempt.d.ts +69 -0
  186. package/dist/payments/contracts/preparedAttempt.js +1 -0
  187. package/dist/payments/contracts/reconciliation.d.ts +303 -0
  188. package/dist/payments/contracts/reconciliation.js +1 -0
  189. package/dist/payments/contracts/repair.d.ts +92 -0
  190. package/dist/payments/contracts/repair.js +1 -0
  191. package/dist/payments/contracts/truth.d.ts +92 -0
  192. package/dist/payments/contracts/truth.js +1 -0
  193. package/dist/payments/eventConformanceRunner.d.ts +12 -0
  194. package/dist/payments/eventConformanceRunner.js +125 -0
  195. package/dist/payments/index.d.ts +16 -0
  196. package/dist/payments/index.js +16 -0
  197. package/dist/payments/paymentAttemptSilenceWindow.d.ts +10 -0
  198. package/dist/payments/paymentAttemptSilenceWindow.js +19 -0
  199. package/dist/payments/paymentMethodLifecycle.d.ts +11 -0
  200. package/dist/payments/paymentMethodLifecycle.js +37 -0
  201. package/dist/payments/paymentProviderReconciliationAbsenceReopen.d.ts +7 -0
  202. package/dist/payments/paymentProviderReconciliationAbsenceReopen.js +100 -0
  203. package/dist/payments/paymentProviderReconciliationEvidence.d.ts +36 -0
  204. package/dist/payments/paymentProviderReconciliationEvidence.js +91 -0
  205. package/dist/payments/paymentProviderReconciliationWorker.d.ts +4 -0
  206. package/dist/payments/paymentProviderReconciliationWorker.js +245 -0
  207. package/dist/payments/paymentTruth.d.ts +8 -0
  208. package/dist/payments/paymentTruth.js +125 -0
  209. package/dist/payments/paymentVerifyNowHandler.d.ts +27 -0
  210. package/dist/payments/paymentVerifyNowHandler.js +70 -0
  211. package/dist/payments/paymentVerifyNowService.d.ts +23 -0
  212. package/dist/payments/paymentVerifyNowService.js +93 -0
  213. package/dist/payments/paymentWebhookPostProcessing.d.ts +22 -0
  214. package/dist/payments/paymentWebhookPostProcessing.js +15 -0
  215. package/dist/payments/postgresPaymentTruth.d.ts +10 -0
  216. package/dist/payments/postgresPaymentTruth.js +126 -0
  217. package/dist/payments/preparedAttempt.d.ts +6 -0
  218. package/dist/payments/preparedAttempt.js +70 -0
  219. package/dist/payments/preparedAttemptFinalization.d.ts +5 -0
  220. package/dist/payments/preparedAttemptFinalization.js +12 -0
  221. package/dist/payments/schemaCapabilities.d.ts +10 -0
  222. package/dist/payments/schemaCapabilities.js +10 -0
  223. package/dist/payments/sql.d.ts +20 -0
  224. package/dist/payments/sql.js +6 -0
  225. package/dist/payments/stripe/classifyDecline.d.ts +46 -0
  226. package/dist/payments/stripe/classifyDecline.js +58 -0
  227. package/dist/payments/stripe/declineFailureHints.d.ts +46 -0
  228. package/dist/payments/stripe/declineFailureHints.js +87 -0
  229. package/dist/payments/stripe/donorContracts.d.ts +120 -0
  230. package/dist/payments/stripe/donorContracts.js +1 -0
  231. package/dist/payments/stripe/executionDecline.d.ts +53 -0
  232. package/dist/payments/stripe/executionDecline.js +107 -0
  233. package/dist/payments/stripe/index.d.ts +41 -0
  234. package/dist/payments/stripe/index.js +264 -0
  235. package/dist/payments/stripe/intentMapper.d.ts +26 -0
  236. package/dist/payments/stripe/intentMapper.js +51 -0
  237. package/dist/payments/stripe/methodFacts.d.ts +10 -0
  238. package/dist/payments/stripe/methodFacts.js +12 -0
  239. package/dist/payments/stripe/paymentFailureEvidence.d.ts +26 -0
  240. package/dist/payments/stripe/paymentFailureEvidence.js +33 -0
  241. package/dist/payments/stripe/stripeFailureEvidence.d.ts +41 -0
  242. package/dist/payments/stripe/stripeFailureEvidence.js +82 -0
  243. package/dist/payments/stripe/stripeIntentConfirmationEvidence.d.ts +28 -0
  244. package/dist/payments/stripe/stripeIntentConfirmationEvidence.js +32 -0
  245. package/dist/payments/stripe/stripePaymentReconciliationProvider.d.ts +35 -0
  246. package/dist/payments/stripe/stripePaymentReconciliationProvider.js +222 -0
  247. package/dist/payments/stripe/stripeRefundEvidence.d.ts +8 -0
  248. package/dist/payments/stripe/stripeRefundEvidence.js +17 -0
  249. package/dist/payments/stripe/stripeSandboxPaymentExecutionAdapter.d.ts +45 -0
  250. package/dist/payments/stripe/stripeSandboxPaymentExecutionAdapter.js +220 -0
  251. package/dist/payments/stripe/stripeWebhookNormalizer.d.ts +14 -0
  252. package/dist/payments/stripe/stripeWebhookNormalizer.js +243 -0
  253. package/dist/payments/stripe/webhookSignature.d.ts +14 -0
  254. package/dist/payments/stripe/webhookSignature.js +43 -0
  255. package/dist/payments/tpay/blikRecurringMapper.d.ts +37 -0
  256. package/dist/payments/tpay/blikRecurringMapper.js +24 -0
  257. package/dist/payments/tpay/capabilities.d.ts +3 -0
  258. package/dist/payments/tpay/capabilities.js +18 -0
  259. package/dist/payments/tpay/classifyDecline.d.ts +46 -0
  260. package/dist/payments/tpay/classifyDecline.js +58 -0
  261. package/dist/payments/tpay/declineFailureHints.d.ts +72 -0
  262. package/dist/payments/tpay/declineFailureHints.js +37 -0
  263. package/dist/payments/tpay/donorContracts.d.ts +140 -0
  264. package/dist/payments/tpay/donorContracts.js +1 -0
  265. package/dist/payments/tpay/index.d.ts +73 -0
  266. package/dist/payments/tpay/index.js +294 -0
  267. package/dist/payments/tpay/paymentFailureEvidence.d.ts +26 -0
  268. package/dist/payments/tpay/paymentFailureEvidence.js +33 -0
  269. package/dist/payments/tpay/preparedProviderAttempt.d.ts +22 -0
  270. package/dist/payments/tpay/preparedProviderAttempt.js +24 -0
  271. package/dist/payments/tpay/providerAttemptFailureDiagnostic.d.ts +3 -0
  272. package/dist/payments/tpay/providerAttemptFailureDiagnostic.js +95 -0
  273. package/dist/payments/tpay/tpayCreateTransactionInput.d.ts +25 -0
  274. package/dist/payments/tpay/tpayCreateTransactionInput.js +128 -0
  275. package/dist/payments/tpay/tpayDeclineEvidence.d.ts +126 -0
  276. package/dist/payments/tpay/tpayDeclineEvidence.js +177 -0
  277. package/dist/payments/tpay/tpayDispatchFailure.d.ts +60 -0
  278. package/dist/payments/tpay/tpayDispatchFailure.js +121 -0
  279. package/dist/payments/tpay/tpayFailureEvidence.d.ts +20 -0
  280. package/dist/payments/tpay/tpayFailureEvidence.js +61 -0
  281. package/dist/payments/tpay/tpayHttpClient.d.ts +52 -0
  282. package/dist/payments/tpay/tpayHttpClient.js +185 -0
  283. package/dist/payments/tpay/tpayHttpFailure.d.ts +57 -0
  284. package/dist/payments/tpay/tpayHttpFailure.js +143 -0
  285. package/dist/payments/tpay/tpayPaymentExecutionAdapter.d.ts +20 -0
  286. package/dist/payments/tpay/tpayPaymentExecutionAdapter.js +249 -0
  287. package/dist/payments/tpay/tpayPaymentReconciliationProvider.d.ts +5 -0
  288. package/dist/payments/tpay/tpayPaymentReconciliationProvider.js +244 -0
  289. package/dist/payments/tpay/tpayTransactionPayload.d.ts +120 -0
  290. package/dist/payments/tpay/tpayTransactionPayload.js +96 -0
  291. package/dist/payments/tpay/wallClockTime.d.ts +31 -0
  292. package/dist/payments/tpay/wallClockTime.js +57 -0
  293. package/dist/payments/tpay/webhookJwsVerifier.d.ts +17 -0
  294. package/dist/payments/tpay/webhookJwsVerifier.js +51 -0
  295. package/dist/payments/tpay/webhookNormalizer.d.ts +54 -0
  296. package/dist/payments/tpay/webhookNormalizer.js +200 -0
  297. package/dist/payments/verifiedEvidenceProjection.d.ts +12 -0
  298. package/dist/payments/verifiedEvidenceProjection.js +166 -0
  299. package/dist/payments/verifiedIngress.d.ts +119 -0
  300. package/dist/payments/verifiedIngress.js +220 -0
  301. package/package.json +37 -2
  302. package/release-gates.json +105 -3
  303. package/sql/20260808210000_fulfillment_shipment_rail.sql +810 -0
  304. package/sql/20260810180000_payment_settlement_rail.sql +574 -0
  305. package/sql/20260815150000_payment_truth_reconciliation.sql +479 -0
  306. package/sql/20260819150000_fulfillment_shipment_sequence.sql +98 -0
  307. package/sql/20260826100000_late_payment_shifts_the_subscription_cycle.sql +215 -0
  308. package/sql/20261022080000_fulfillment_command_ledger.sql +786 -0
  309. package/sql/20261022090000_fulfillment_delivery_alignment.sql +1106 -0
  310. package/src/composition/composeBundle.ts +13 -0
  311. package/src/composition/fulfillmentContribution.ts +28 -0
  312. package/src/composition/index.ts +2 -0
  313. package/src/fulfillment/adapterConformance.ts +195 -0
  314. package/src/fulfillment/bindings.ts +26 -0
  315. package/src/fulfillment/commerceFulfillmentHandlers.ts +263 -0
  316. package/src/fulfillment/commerceFulfillmentReadModel.ts +257 -0
  317. package/src/fulfillment/contracts/alignment.ts +13 -0
  318. package/src/fulfillment/contracts/bindings.ts +30 -0
  319. package/src/fulfillment/contracts/capabilities.ts +15 -0
  320. package/src/fulfillment/contracts/conformance.ts +61 -0
  321. package/src/fulfillment/contracts/customerAlignment.ts +4 -0
  322. package/src/fulfillment/contracts/dispatch.ts +58 -0
  323. package/src/fulfillment/contracts/index.ts +18 -0
  324. package/src/fulfillment/contracts/label.ts +9 -0
  325. package/src/fulfillment/contracts/nativeUnsupported.ts +6 -0
  326. package/src/fulfillment/contracts/observation.ts +18 -0
  327. package/src/fulfillment/contracts/operator.ts +31 -0
  328. package/src/fulfillment/contracts/read.ts +42 -0
  329. package/src/fulfillment/contracts/readback.ts +11 -0
  330. package/src/fulfillment/contracts/replacement.ts +15 -0
  331. package/src/fulfillment/contracts/store.ts +26 -0
  332. package/src/fulfillment/contracts/sync.ts +61 -0
  333. package/src/fulfillment/currentFulfillmentParcel.ts +2 -0
  334. package/src/fulfillment/delayReadModel.ts +60 -0
  335. package/src/fulfillment/deliveryAlignmentReadModel.ts +15 -0
  336. package/src/fulfillment/dispatchProjection.ts +20 -0
  337. package/src/fulfillment/fulfillmentObservationEffects.ts +86 -0
  338. package/src/fulfillment/handlerSchemas.ts +255 -0
  339. package/src/fulfillment/handlerSupport.ts +25 -0
  340. package/src/fulfillment/index.ts +38 -0
  341. package/src/fulfillment/labelLifecycle.ts +11 -0
  342. package/src/fulfillment/lowStockEvidenceHandler.ts +60 -0
  343. package/src/fulfillment/migrations.ts +8 -0
  344. package/src/fulfillment/nativeUnsupported.ts +23 -0
  345. package/src/fulfillment/normalizedFulfillmentFacts.ts +2 -0
  346. package/src/fulfillment/observationProjection.ts +41 -0
  347. package/src/fulfillment/omnipack/capabilities.ts +18 -0
  348. package/src/fulfillment/omnipack/client.ts +258 -0
  349. package/src/fulfillment/omnipack/index.ts +312 -0
  350. package/src/fulfillment/omnipack/mappers.ts +261 -0
  351. package/src/fulfillment/omnipack/observation.ts +61 -0
  352. package/src/fulfillment/omnipack/omnipackDispatchPayload.ts +93 -0
  353. package/src/fulfillment/omnipack/omnipackOutboundOrderPayload.ts +194 -0
  354. package/src/fulfillment/omnipack/omnipackProductPackPayload.ts +47 -0
  355. package/src/fulfillment/omnipack/omnipackProductPayload.ts +67 -0
  356. package/src/fulfillment/omnipack/omnipackReconciliationPayload.ts +7 -0
  357. package/src/fulfillment/omnipack/omnipackStatusVocabulary.ts +103 -0
  358. package/src/fulfillment/omnipack/omnipackWebhookPayload.ts +73 -0
  359. package/src/fulfillment/omnipack/productSyncMappers.ts +74 -0
  360. package/src/fulfillment/omnipack/providerError.ts +64 -0
  361. package/src/fulfillment/omnipack/trackingReferences.ts +77 -0
  362. package/src/fulfillment/paidFulfillmentRecovery.ts +252 -0
  363. package/src/fulfillment/paidHandoff.ts +122 -0
  364. package/src/fulfillment/paidHandoffPorts.ts +21 -0
  365. package/src/fulfillment/postgresDeliveryAlignment.ts +14 -0
  366. package/src/fulfillment/postgresDispatchStore.ts +55 -0
  367. package/src/fulfillment/postgresEvidenceReadPort.ts +59 -0
  368. package/src/fulfillment/postgresPaidFulfillmentRecovery.ts +29 -0
  369. package/src/fulfillment/postgresPaidHandoffStore.ts +11 -0
  370. package/src/fulfillment/postgresShipmentSpine.ts +321 -0
  371. package/src/fulfillment/postgresStockSyncPort.ts +65 -0
  372. package/src/fulfillment/productReconciliationEvidenceHandler.ts +64 -0
  373. package/src/fulfillment/providerCapabilities.ts +18 -0
  374. package/src/fulfillment/providerCommandLedger.ts +53 -0
  375. package/src/fulfillment/providerDispatchAcceptance.ts +31 -0
  376. package/src/fulfillment/providerDispatchError.ts +7 -0
  377. package/src/fulfillment/providerDispatchWorker.ts +131 -0
  378. package/src/fulfillment/providerProductSyncWorker.ts +154 -0
  379. package/src/fulfillment/providerReconciliationError.ts +20 -0
  380. package/src/fulfillment/providerReconciliationTerminalSkip.ts +8 -0
  381. package/src/fulfillment/providerReconciliationTimestamp.ts +34 -0
  382. package/src/fulfillment/providerReconciliationWorker.ts +150 -0
  383. package/src/fulfillment/providerStockAvailability.ts +60 -0
  384. package/src/fulfillment/providerStockSyncWorker.ts +222 -0
  385. package/src/fulfillment/providerTrackingReferences.ts +31 -0
  386. package/src/fulfillment/replacementRefusals.ts +43 -0
  387. package/src/fulfillment/replacementShipmentHandler.ts +47 -0
  388. package/src/fulfillment/schemaCapabilities.ts +7 -0
  389. package/src/fulfillment/shipmentsOverviewHandler.ts +73 -0
  390. package/src/fulfillment/statusMap.ts +2 -0
  391. package/src/fulfillment/trackingProgress.ts +1 -0
  392. package/src/fulfillment/verifiedIngress.ts +80 -0
  393. package/src/payments/adapterConformance.ts +118 -0
  394. package/src/payments/bindings.ts +17 -0
  395. package/src/payments/checkoutActivePaymentActionResolver.ts +97 -0
  396. package/src/payments/checkoutRecoveryPaymentResolver.ts +108 -0
  397. package/src/payments/contracts/adapter.ts +96 -0
  398. package/src/payments/contracts/conformance.ts +171 -0
  399. package/src/payments/contracts/evidence.ts +142 -0
  400. package/src/payments/contracts/index.ts +54 -0
  401. package/src/payments/contracts/preparedAttempt.ts +86 -0
  402. package/src/payments/contracts/reconciliation.ts +296 -0
  403. package/src/payments/contracts/repair.ts +95 -0
  404. package/src/payments/contracts/truth.ts +108 -0
  405. package/src/payments/eventConformanceRunner.ts +149 -0
  406. package/src/payments/index.ts +21 -0
  407. package/src/payments/paymentAttemptSilenceWindow.ts +26 -0
  408. package/src/payments/paymentMethodLifecycle.ts +50 -0
  409. package/src/payments/paymentProviderReconciliationAbsenceReopen.ts +130 -0
  410. package/src/payments/paymentProviderReconciliationEvidence.ts +117 -0
  411. package/src/payments/paymentProviderReconciliationWorker.ts +291 -0
  412. package/src/payments/paymentTruth.ts +131 -0
  413. package/src/payments/paymentVerifyNowHandler.ts +94 -0
  414. package/src/payments/paymentVerifyNowService.ts +125 -0
  415. package/src/payments/paymentWebhookPostProcessing.ts +36 -0
  416. package/src/payments/postgresPaymentTruth.ts +149 -0
  417. package/src/payments/preparedAttempt.ts +90 -0
  418. package/src/payments/preparedAttemptFinalization.ts +13 -0
  419. package/src/payments/schemaCapabilities.ts +10 -0
  420. package/src/payments/sql.ts +6 -0
  421. package/src/payments/stripe/classifyDecline.ts +62 -0
  422. package/src/payments/stripe/declineFailureHints.ts +89 -0
  423. package/src/payments/stripe/donorContracts.ts +87 -0
  424. package/src/payments/stripe/executionDecline.ts +126 -0
  425. package/src/payments/stripe/index.ts +265 -0
  426. package/src/payments/stripe/intentMapper.ts +58 -0
  427. package/src/payments/stripe/methodFacts.ts +21 -0
  428. package/src/payments/stripe/paymentFailureEvidence.ts +58 -0
  429. package/src/payments/stripe/stripeFailureEvidence.ts +115 -0
  430. package/src/payments/stripe/stripeIntentConfirmationEvidence.ts +34 -0
  431. package/src/payments/stripe/stripePaymentReconciliationProvider.ts +263 -0
  432. package/src/payments/stripe/stripeRefundEvidence.ts +19 -0
  433. package/src/payments/stripe/stripeSandboxPaymentExecutionAdapter.ts +283 -0
  434. package/src/payments/stripe/stripeWebhookNormalizer.ts +277 -0
  435. package/src/payments/stripe/webhookSignature.ts +55 -0
  436. package/src/payments/tpay/blikRecurringMapper.ts +42 -0
  437. package/src/payments/tpay/capabilities.ts +21 -0
  438. package/src/payments/tpay/classifyDecline.ts +62 -0
  439. package/src/payments/tpay/declineFailureHints.ts +90 -0
  440. package/src/payments/tpay/donorContracts.ts +104 -0
  441. package/src/payments/tpay/index.ts +293 -0
  442. package/src/payments/tpay/paymentFailureEvidence.ts +58 -0
  443. package/src/payments/tpay/preparedProviderAttempt.ts +38 -0
  444. package/src/payments/tpay/providerAttemptFailureDiagnostic.ts +99 -0
  445. package/src/payments/tpay/tpayCreateTransactionInput.ts +158 -0
  446. package/src/payments/tpay/tpayDeclineEvidence.ts +233 -0
  447. package/src/payments/tpay/tpayDispatchFailure.ts +186 -0
  448. package/src/payments/tpay/tpayFailureEvidence.ts +75 -0
  449. package/src/payments/tpay/tpayHttpClient.ts +290 -0
  450. package/src/payments/tpay/tpayHttpFailure.ts +186 -0
  451. package/src/payments/tpay/tpayPaymentExecutionAdapter.ts +297 -0
  452. package/src/payments/tpay/tpayPaymentReconciliationProvider.ts +285 -0
  453. package/src/payments/tpay/tpayTransactionPayload.ts +207 -0
  454. package/src/payments/tpay/wallClockTime.ts +57 -0
  455. package/src/payments/tpay/webhookJwsVerifier.ts +82 -0
  456. package/src/payments/tpay/webhookNormalizer.ts +279 -0
  457. package/src/payments/verifiedEvidenceProjection.ts +179 -0
  458. package/src/payments/verifiedIngress.ts +317 -0
@@ -0,0 +1,154 @@
1
+ const COMMERCE_ORDER_PAID_EVENT_TYPE = "commerce.order.paid";
2
+ export function collectPaidFulfillmentRecoveryCandidates(input) {
3
+ const minimumAgeSeconds = input.minimumAgeSeconds ?? 30 * 60;
4
+ const minimumAgeMs = minimumAgeSeconds * 1000;
5
+ const dispatchSubmissionStaleSeconds = input.dispatchSubmissionStaleSeconds ?? 5 * 60;
6
+ const fulfillmentByOrder = groupBy(input.fulfillmentOrders, (row) => row.order_id);
7
+ const dispatchRefsByFulfillment = groupBy(input.dispatchRefs ?? [], (row) => row.fulfillment_order_id);
8
+ const outboxByOrder = latestBy(input.orderPaidOutboxEvents.filter((row) => row.event_type === COMMERCE_ORDER_PAID_EVENT_TYPE), (row) => row.aggregate_id ?? "");
9
+ const candidates = [];
10
+ let checkedOrders = 0;
11
+ for (const order of input.orders) {
12
+ const status = clean(order.status);
13
+ if (!["paid", "fulfillment_pending"].includes(status))
14
+ continue;
15
+ const ageSeconds = secondsSince(order.updated_at ?? order.created_at ?? "", input.now);
16
+ if (ageSeconds * 1000 < minimumAgeMs)
17
+ continue;
18
+ checkedOrders += 1;
19
+ const outbox = outboxByOrder.get(order.id);
20
+ const fulfillments = fulfillmentByOrder.get(order.id) ?? [];
21
+ if (fulfillments.length === 0) {
22
+ candidates.push(candidateForMissingFulfillment(order, outbox, ageSeconds));
23
+ continue;
24
+ }
25
+ for (const fulfillment of fulfillments) {
26
+ const providerKind = clean(fulfillment.provider_kind);
27
+ if (providerKind !== input.providerRef)
28
+ continue;
29
+ const latestDispatchRef = latestBy(dispatchRefsByFulfillment.get(fulfillment.id) ?? [], (row) => row.fulfillment_order_id).get(fulfillment.id);
30
+ const decision = dispatchRecoveryDecision({
31
+ dispatchRef: latestDispatchRef,
32
+ fulfillmentCreatedAt: fulfillment.updated_at ?? fulfillment.created_at,
33
+ now: input.now,
34
+ missingRefGraceSeconds: minimumAgeSeconds,
35
+ staleSeconds: dispatchSubmissionStaleSeconds,
36
+ });
37
+ if (!decision)
38
+ continue;
39
+ candidates.push({
40
+ ...baseCandidate(order, outbox, ageSeconds),
41
+ fulfillmentOrderId: fulfillment.id,
42
+ providerKind: input.providerRef,
43
+ dispatchRefId: latestDispatchRef?.id ?? null,
44
+ dispatchStatus: clean(latestDispatchRef?.status) || null,
45
+ ...decision,
46
+ });
47
+ }
48
+ }
49
+ candidates.sort((a, b) => b.ageSeconds - a.ageSeconds || a.orderId.localeCompare(b.orderId));
50
+ return { checkedOrders, candidates };
51
+ }
52
+ function candidateForMissingFulfillment(order, outbox, ageSeconds) {
53
+ const outboxStatus = clean(outbox?.status);
54
+ const decision = !outbox
55
+ ? recoveryDecision("order_paid_outbox_missing", "inspect_missing_order_paid_outbox")
56
+ : outboxStatus === "discarded"
57
+ ? recoveryDecision("order_paid_outbox_discarded", "requeue_discarded_order_paid_outbox", "automatic_local_requeue_safe")
58
+ : outboxStatus === "processed"
59
+ ? recoveryDecision("order_paid_outbox_processed_without_fulfillment", "inspect_processed_without_effect")
60
+ : recoveryDecision("paid_order_without_fulfillment_order", "wait_for_outbox", "wait_for_existing_automation");
61
+ return { ...baseCandidate(order, outbox, ageSeconds), ...decision };
62
+ }
63
+ function baseCandidate(order, outbox, ageSeconds) {
64
+ return {
65
+ orderId: order.id,
66
+ orderStatus: clean(order.status),
67
+ orderMode: clean(order.mode) || null,
68
+ fulfillmentOrderId: null,
69
+ providerKind: null,
70
+ dispatchRefId: null,
71
+ dispatchStatus: null,
72
+ outboxEventId: outbox?.id ?? null,
73
+ outboxStatus: clean(outbox?.status) || null,
74
+ outboxAttempts: typeof outbox?.attempts === "number" ? outbox.attempts : null,
75
+ ageSeconds,
76
+ };
77
+ }
78
+ function dispatchRecoveryDecision(input) {
79
+ const { dispatchRef, now, staleSeconds } = input;
80
+ if (!dispatchRef) {
81
+ if (!isAtLeastAgeOrUnknown(input.fulfillmentCreatedAt, now, input.missingRefGraceSeconds))
82
+ return null;
83
+ return recoveryDecision("provider_fulfillment_without_dispatch_ref", "inspect_missing_dispatch_ref");
84
+ }
85
+ const status = clean(dispatchRef.status);
86
+ if (status === "draft") {
87
+ return recoveryDecision("provider_dispatch_in_progress", "monitor_dispatch", "wait_for_existing_automation");
88
+ }
89
+ if (status === "submitting") {
90
+ return isAtLeastAgeOrUnknown(dispatchRef.updated_at ?? dispatchRef.created_at, now, staleSeconds)
91
+ ? recoveryDecision("provider_dispatch_submission_stale", "inspect_stale_dispatch_submission")
92
+ : recoveryDecision("provider_dispatch_in_progress", "monitor_dispatch", "wait_for_existing_automation");
93
+ }
94
+ if (status === "uncertain") {
95
+ return recoveryDecision("provider_dispatch_outcome_uncertain", "inspect_uncertain_dispatch");
96
+ }
97
+ if (status === "failed") {
98
+ return recoveryDecision("provider_dispatch_failed", "inspect_failed_dispatch");
99
+ }
100
+ if (status === "created") {
101
+ return dispatchRef.provider_order_id?.trim()
102
+ ? null
103
+ : recoveryDecision("provider_dispatch_created_without_provider_order_id", "inspect_created_dispatch_without_provider_order_id");
104
+ }
105
+ if (["cancel_requested", "cancelled"].includes(status)) {
106
+ return recoveryDecision("provider_dispatch_terminal_without_progress", "inspect_terminal_dispatch");
107
+ }
108
+ return recoveryDecision("provider_dispatch_status_unknown", "inspect_unknown_dispatch_status");
109
+ }
110
+ function recoveryDecision(reason, recommendedAction, recoveryPosture = "operator_review_required") {
111
+ return { reason, recommendedAction, recoveryPosture };
112
+ }
113
+ function latestBy(rows, key) {
114
+ const result = new Map();
115
+ for (const row of rows) {
116
+ const rowKey = key(row);
117
+ if (!rowKey)
118
+ continue;
119
+ const current = result.get(rowKey);
120
+ if (!current || timestamp(row.updated_at ?? row.created_at) >= timestamp(current.updated_at ?? current.created_at)) {
121
+ result.set(rowKey, row);
122
+ }
123
+ }
124
+ return result;
125
+ }
126
+ function groupBy(rows, key) {
127
+ const groups = new Map();
128
+ for (const row of rows) {
129
+ const rowKey = key(row);
130
+ const group = groups.get(rowKey);
131
+ if (group)
132
+ group.push(row);
133
+ else
134
+ groups.set(rowKey, [row]);
135
+ }
136
+ return groups;
137
+ }
138
+ function clean(value) {
139
+ return value?.trim().toLowerCase() ?? "";
140
+ }
141
+ function timestamp(value) {
142
+ const parsed = value ? Date.parse(value) : 0;
143
+ return Number.isFinite(parsed) ? parsed : 0;
144
+ }
145
+ function secondsSince(value, now) {
146
+ const parsed = Date.parse(value);
147
+ if (!Number.isFinite(parsed))
148
+ return 0;
149
+ return Math.max(0, Math.floor((now.getTime() - parsed) / 1000));
150
+ }
151
+ function isAtLeastAgeOrUnknown(value, now, seconds) {
152
+ const parsed = timestamp(value);
153
+ return parsed <= 0 || now.getTime() - parsed > seconds * 1000;
154
+ }
@@ -0,0 +1,27 @@
1
+ import type { OutboxHandler } from "@openlup/core/outbox";
2
+ import type { OrderPaidFulfillmentPort } from "./paidHandoffPorts.js";
3
+ interface OrderPaidRiskAssessmentPort {
4
+ assessPaidOrder(input: {
5
+ orderUuid: string;
6
+ outboxEventId: string;
7
+ signal: AbortSignal;
8
+ }): Promise<{
9
+ kind: "allow";
10
+ detail?: Record<string, unknown>;
11
+ } | {
12
+ kind: "review" | "block";
13
+ detail?: Record<string, unknown>;
14
+ } | {
15
+ kind: "retryable";
16
+ reason: string;
17
+ } | {
18
+ kind: "fatal";
19
+ reason: string;
20
+ }>;
21
+ }
22
+ export declare function createOutboxOrderPaidFulfillmentHandler(deps: {
23
+ fulfillmentPort: OrderPaidFulfillmentPort;
24
+ riskPort?: OrderPaidRiskAssessmentPort;
25
+ isRiskEnabled?: () => boolean;
26
+ }): OutboxHandler<AbortSignal>;
27
+ export {};
@@ -0,0 +1,86 @@
1
+ import { z } from "zod";
2
+ const COMMERCE_ORDER_PAID_EVENT_TYPE = "commerce.order.paid";
3
+ const HANDLER_TIMEOUT_MS = 15_000;
4
+ const outboxOrderPaidFulfillmentDescriptor = Object.freeze({
5
+ eventType: COMMERCE_ORDER_PAID_EVENT_TYPE, timeoutMs: HANDLER_TIMEOUT_MS,
6
+ });
7
+ // Frozen minimal parse: validate only the orderUuid forwarded to the fulfillment
8
+ // port. This handler owns the subset schema so a producer-side payload change
9
+ // does not send otherwise valid in-flight events to the dead-letter queue.
10
+ const payloadSubsetSchema = z
11
+ .object({
12
+ orderUuid: z.guid(),
13
+ })
14
+ .passthrough();
15
+ export function createOutboxOrderPaidFulfillmentHandler(deps) {
16
+ return {
17
+ ...outboxOrderPaidFulfillmentDescriptor,
18
+ async handle(row, signal) {
19
+ const parsed = parseOutboxPayload(payloadSubsetSchema, row.payload);
20
+ if (parsed.ok === false) {
21
+ return parsed.outcome;
22
+ }
23
+ // Risk gate (flag-OFF by default): assess the paid order before any
24
+ // fulfillment work. review/block → hold (ack without dispatch, the case is
25
+ // persisted for manual review); retryable/fatal map to the worker ladder.
26
+ if (deps.riskPort && deps.isRiskEnabled?.()) {
27
+ const risk = await deps.riskPort.assessPaidOrder({
28
+ orderUuid: parsed.data.orderUuid,
29
+ outboxEventId: row.id,
30
+ signal,
31
+ });
32
+ switch (risk.kind) {
33
+ case "allow":
34
+ break;
35
+ case "review":
36
+ case "block":
37
+ return {
38
+ kind: "processed",
39
+ detail: { skipped: "risk_review_hold", risk: risk.detail ?? {} },
40
+ };
41
+ case "retryable":
42
+ return { kind: "retry", reason: truncateReason(risk.reason) };
43
+ case "fatal":
44
+ return { kind: "discard", reason: truncateReason(risk.reason) };
45
+ }
46
+ }
47
+ const result = await deps.fulfillmentPort.ensureFulfilledFromPaidOrder({
48
+ orderUuid: parsed.data.orderUuid,
49
+ outboxEventId: row.id,
50
+ signal,
51
+ });
52
+ switch (result.kind) {
53
+ case "completed":
54
+ case "skipped":
55
+ return { kind: "processed", detail: result.detail };
56
+ case "manual_review":
57
+ // Terminal but NOT a silent discard: the port already placed the
58
+ // durable observable signal (an active fulfillment_exception hold).
59
+ // Settle the event as processed so it is not parked in the discard/
60
+ // error queue, and record why in the outbox metadata.
61
+ return {
62
+ kind: "processed",
63
+ detail: {
64
+ ...result.detail,
65
+ outcome: "manual_review",
66
+ reason: truncateReason(result.reason),
67
+ },
68
+ };
69
+ case "retryable":
70
+ return { kind: "retry", reason: truncateReason(result.reason) };
71
+ case "snooze":
72
+ return { kind: "snooze", reason: truncateReason(result.reason) };
73
+ case "fatal":
74
+ return { kind: "discard", reason: truncateReason(result.reason) };
75
+ }
76
+ },
77
+ };
78
+ }
79
+ function truncateReason(value) { return value.length <= 300 ? value : `${value.slice(0, 300)}…`; }
80
+ function parseOutboxPayload(schema, payload) {
81
+ const parsed = schema.safeParse(payload);
82
+ if (parsed.success)
83
+ return { ok: true, data: parsed.data };
84
+ const detail = parsed.error.issues.map(issue => `${issue.path.join(".") || "payload"}: ${issue.message}`).join("; ");
85
+ return { ok: false, outcome: { kind: "discard", reason: `contract_parse_failed: ${truncateReason(detail)}` } };
86
+ }
@@ -0,0 +1,24 @@
1
+ export type OrderPaidFulfillmentResult = {
2
+ kind: "completed" | "skipped";
3
+ detail?: Record<string, unknown>;
4
+ } | {
5
+ kind: "retryable";
6
+ reason: string;
7
+ } | {
8
+ kind: "snooze";
9
+ reason: string;
10
+ } | {
11
+ kind: "fatal";
12
+ reason: string;
13
+ } | {
14
+ kind: "manual_review";
15
+ reason: string;
16
+ detail?: Record<string, unknown>;
17
+ };
18
+ export interface OrderPaidFulfillmentPort {
19
+ ensureFulfilledFromPaidOrder(input: {
20
+ orderUuid: string;
21
+ outboxEventId: string;
22
+ signal: AbortSignal;
23
+ }): Promise<OrderPaidFulfillmentResult>;
24
+ }
@@ -0,0 +1,3 @@
1
+ // Neutral port owned by the commerce.order.paid dispatch handler. Concrete
2
+ // persistence and provider adapters belong to the host composition.
3
+ export {};
@@ -0,0 +1,4 @@
1
+ import type { DeliveryAlignmentPort } from './contracts/index.js';
2
+ import { type PgExecutor } from './postgresDispatchStore.js';
3
+ /** Trusted arrival ingestion only. Operator replacement attestation has no caller here. */
4
+ export declare function createPostgresDeliveryAlignmentPort(db: PgExecutor): DeliveryAlignmentPort;
@@ -0,0 +1,12 @@
1
+ import { nativeCall } from './postgresDispatchStore.js';
2
+ import { readDeliveryAlignment } from './deliveryAlignmentReadModel.js';
3
+ /** Trusted arrival ingestion only. Operator replacement attestation has no caller here. */
4
+ export function createPostgresDeliveryAlignmentPort(db) {
5
+ return {
6
+ read: ref => readDeliveryAlignment(db, ref),
7
+ async recordArrival(v) {
8
+ const receipt = await nativeCall(db, 'fulfillment_record_alignment_arrival', [v.requestKey, v.parcelRef, v.deliveredAt, v.evidenceRef]);
9
+ return { ...await readDeliveryAlignment(db, v.parcelRef), replayed: receipt.replayed };
10
+ },
11
+ };
12
+ }
@@ -0,0 +1,16 @@
1
+ import type { FulfillmentDispatchRequest, FulfillmentStorePort } from './contracts/index.js';
2
+ import type { createFulfillmentCommandLedger } from './providerCommandLedger.js';
3
+ /** Caller supplies a driver and its selected host preparation/data boundary. */
4
+ export interface PgExecutor {
5
+ query(text: string, values?: unknown[]): Promise<{
6
+ rows: Record<string, unknown>[];
7
+ }>;
8
+ }
9
+ export declare function nativeCall<T>(db: PgExecutor, name: string, values: unknown[]): Promise<T>;
10
+ export declare function createPostgresFulfillmentDispatchStore(db: PgExecutor, host: {
11
+ /** Synchronize authoritative withholding/contact revision on prepare and every source edit. */
12
+ prepare(fulfillmentRef: string): ReturnType<FulfillmentStorePort['prepare']>;
13
+ readCandidate(fulfillmentRef: string): Promise<FulfillmentDispatchRequest | null>;
14
+ }): FulfillmentStorePort & {
15
+ commandLedger: ReturnType<typeof createFulfillmentCommandLedger>;
16
+ };
@@ -0,0 +1,44 @@
1
+ import { dispatchEvidence, dispatchResult } from './dispatchProjection.js';
2
+ export async function nativeCall(db, name, values) {
3
+ const result = await db.query(`SELECT public.${name}(${values.map((_, index) => `$${index + 1}`).join(',')}) AS response`, values);
4
+ if (!result.rows[0] || result.rows[0].response === undefined)
5
+ throw new Error('fulfillment_native_response_missing');
6
+ return result.rows[0].response;
7
+ }
8
+ export function createPostgresFulfillmentDispatchStore(db, host) {
9
+ return {
10
+ readCandidate: ref => host.readCandidate(ref),
11
+ prepare: ref => host.prepare(ref),
12
+ async read(key) {
13
+ const result = await db.query('SELECT public.fulfillment_dispatch_read(ref) AS response FROM public.fulfillment_dispatch_refs ref WHERE request_key=$1', [key]);
14
+ return result.rows[0]?.response ?? null;
15
+ },
16
+ claim: input => nativeCall(db, 'fulfillment_dispatch_claim', [input.requestKey, input.fulfillmentRef, input.orderRef, input.parcelRef, input.mode, JSON.stringify(dispatchEvidence(input.evidence))]),
17
+ recordProviderAttempt: (key, ref, evidence, mode) => nativeCall(db, 'fulfillment_record_provider_attempt', [key, ref, JSON.stringify(dispatchEvidence(evidence)), mode]),
18
+ begin: input => nativeCall(db, 'fulfillment_dispatch_begin', [input.dispatchRef, input.commandFingerprint]),
19
+ finalize: input => nativeCall(db, 'fulfillment_dispatch_finish', [input.dispatchRef, JSON.stringify(dispatchResult(input.result)), false]),
20
+ acknowledge: input => nativeCall(db, 'fulfillment_dispatch_finish', [input.dispatchRef, JSON.stringify(dispatchResult(input.acceptance)), true]),
21
+ async markStaleSubmissionsUncertain(staleBefore) {
22
+ const result = await db.query("UPDATE public.fulfillment_dispatch_refs SET status='uncertain',updated_at=now() WHERE status='submitting' AND updated_at<$1 RETURNING id", [staleBefore]);
23
+ return result.rows.length;
24
+ },
25
+ commandLedger: commandLedger(db),
26
+ };
27
+ }
28
+ function commandLedger(db) {
29
+ const fence = (v) => [v.commandId, v.claimToken, v.claimGeneration, v.expectedVersion];
30
+ return {
31
+ enqueue: v => nativeCall(db, 'commerce_fulfillment_enqueue_provider_command', [v.fulfillmentRef, v.providerRef, v.commandKind, v.contractVersion, v.idempotencyKey, v.commandKeyFingerprint, v.commandPayloadFingerprint, v.providerIdempotencyKeyFingerprint, v.routingFingerprint, v.configurationFingerprint, v.correlationKeyFingerprint, v.retryBudget]),
32
+ async claim(v) {
33
+ const result = await db.query('SELECT public.commerce_fulfillment_claim_provider_commands($1,$2,$3,$4,$5) AS response', [v.providerRef, v.commandKind, v.limit, v.claimOwnerFingerprint, v.leaseSeconds]);
34
+ return result.rows.map(row => row.response);
35
+ },
36
+ markSubmitting: v => nativeCall(db, 'commerce_fulfillment_mark_command_submitting', [...fence(v), v.providerAttemptRef]),
37
+ applyWriteOutcome: v => nativeCall(db, 'commerce_fulfillment_apply_command_write_outcome', [...fence(v), v.identityFingerprint, v.kind, v.reason, v.kind === 'rejected' ? v.retryNotBefore : null, v.kind === 'accepted' ? v.providerReferenceFingerprint : null, v.providerAttemptRef, v.kind === 'rejected' ? v.proof.kind : null, v.kind === 'rejected' ? v.proof.fingerprint : null, v.kind === 'rejected' ? v.proof.observedAt : null, v.kind === 'rejected' ? v.proof.source : null]),
38
+ confirm: v => nativeCall(db, 'commerce_fulfillment_confirm_provider_command', [...fence(v), v.identityFingerprint, v.providerAttemptRef, v.proof.kind, v.proof.fingerprint, v.proof.observedAt, v.proof.source]),
39
+ reconcile: v => nativeCall(db, 'commerce_fulfillment_reconcile_provider_command', [v.commandId, v.expectedVersion, v.identityFingerprint, v.proof.kind, v.proof.fingerprint, v.proof.observedAt, v.proof.source]),
40
+ resolve: v => nativeCall(db, 'commerce_fulfillment_resolve_uncertain_command', [v.commandId, v.expectedVersion, v.identityFingerprint, v.decision, v.reason, v.proof.kind, v.proof.fingerprint, v.proof.observedAt, v.proof.source, v.decision === 'retry_wait' ? v.retryNotBefore : null]),
41
+ release: v => nativeCall(db, 'commerce_fulfillment_release_or_cancel_command', [...fence(v), v.action, v.reason]),
42
+ recoverExpired: v => nativeCall(db, 'commerce_fulfillment_recover_expired_provider_commands', [v.limit]),
43
+ };
44
+ }
@@ -0,0 +1,25 @@
1
+ import type { PgExecutor as PgQueryExecutor } from './postgresDispatchStore.js';
2
+ interface AdminLowStockEvidenceItem {
3
+ id: string;
4
+ sku: string;
5
+ thresholdKind: string;
6
+ severity: string;
7
+ status: string;
8
+ providerForSaleQuantity: number | null;
9
+ localAvailableQuantity: number | null;
10
+ forecastDays: null;
11
+ firstSeenAt: string | null;
12
+ lastSeenAt: string | null;
13
+ resolvedAt: string | null;
14
+ }
15
+ interface FulfillmentLowStockEvidencePort {
16
+ getLowStockEvidence(input: {
17
+ statusFilter: 'all' | 'open' | 'resolved';
18
+ }): Promise<{
19
+ statusFilter: string;
20
+ openCount: number;
21
+ items: AdminLowStockEvidenceItem[];
22
+ }>;
23
+ }
24
+ export declare function createPostgresFulfillmentLowStockEvidencePort(executor: PgQueryExecutor, sourceKey: string): FulfillmentLowStockEvidencePort;
25
+ export {};
@@ -0,0 +1,45 @@
1
+ const READ = `SELECT id, sku, threshold_kind, severity, status,
2
+ provider_for_sale_quantity, local_available_quantity,
3
+ first_seen_at, last_seen_at, resolved_at
4
+ FROM public.fulfillment_stock_evidence
5
+ WHERE source_key = $1::text AND ($2::text = 'all' OR status = $2::text)
6
+ ORDER BY last_seen_at DESC, id ASC`;
7
+ const COUNT = `SELECT count(*)::integer AS count
8
+ FROM public.fulfillment_stock_evidence
9
+ WHERE source_key = $1::text AND status = 'open'`;
10
+ export function createPostgresFulfillmentLowStockEvidencePort(executor, sourceKey) {
11
+ const key = sourceKey.trim();
12
+ if (!key)
13
+ throw new Error("fulfillment_stock_source_key_required");
14
+ return { async getLowStockEvidence({ statusFilter }) {
15
+ const [rows, count] = await Promise.all([
16
+ executor.query(READ, [key, statusFilter]),
17
+ executor.query(COUNT, [key]),
18
+ ]);
19
+ return {
20
+ statusFilter,
21
+ openCount: integer(count.rows[0]?.count),
22
+ items: rows.rows.map(mapItem),
23
+ };
24
+ } };
25
+ }
26
+ function mapItem(row) {
27
+ return {
28
+ id: String(row.id),
29
+ sku: String(row.sku),
30
+ thresholdKind: row.threshold_kind,
31
+ severity: row.severity,
32
+ status: row.status,
33
+ providerForSaleQuantity: nullableInteger(row.provider_for_sale_quantity),
34
+ localAvailableQuantity: nullableInteger(row.local_available_quantity),
35
+ forecastDays: null,
36
+ firstSeenAt: nullableText(row.first_seen_at),
37
+ lastSeenAt: nullableText(row.last_seen_at),
38
+ resolvedAt: nullableText(row.resolved_at),
39
+ };
40
+ }
41
+ function integer(value) {
42
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
43
+ }
44
+ function nullableInteger(value) { return value === null ? null : integer(value); }
45
+ function nullableText(value) { return value instanceof Date ? value.toISOString() : typeof value === "string" && value ? value : null; }
@@ -0,0 +1,25 @@
1
+ import type { collectPaidFulfillmentRecoveryCandidates } from './paidFulfillmentRecovery.js';
2
+ import type { PgExecutor } from './postgresDispatchStore.js';
3
+ type RecoveryInput = Parameters<typeof collectPaidFulfillmentRecoveryCandidates>[0];
4
+ /** Read the selected native port's local obligations; never infer external absence. */
5
+ export declare function createPostgresPaidFulfillmentRecoveryOpsPort(db: PgExecutor, selection: {
6
+ portKey: string;
7
+ providerRef: string;
8
+ }): {
9
+ readRecoveryInputs(input: {
10
+ minimumAgeSeconds: number;
11
+ limit: number;
12
+ now: Date;
13
+ orderIds?: string[];
14
+ }): Promise<Pick<RecoveryInput, "orders" | "fulfillmentOrders" | "dispatchRefs" | "orderPaidOutboxEvents">>;
15
+ requeueDiscardedOrderPaidOutboxEvents(input: {
16
+ eventIds: string[];
17
+ limit?: number;
18
+ requeuedBy: string;
19
+ reason: string;
20
+ }): Promise<{
21
+ requeuedCount: number;
22
+ eventIds: string[];
23
+ }>;
24
+ };
25
+ export {};
@@ -0,0 +1,26 @@
1
+ /** Read the selected native port's local obligations; never infer external absence. */
2
+ export function createPostgresPaidFulfillmentRecoveryOpsPort(db, selection) {
3
+ return {
4
+ async readRecoveryInputs(input) {
5
+ const ids = [...new Set(input.orderIds ?? [])];
6
+ const orders = (await db.query(`SELECT id,status,metadata->>'mode' AS mode,created_at::text,updated_at::text FROM public.commerce_orders
7
+ WHERE status=ANY($1::text[]) AND updated_at<=$2 AND ($4::uuid[]='{}'::uuid[] OR id=ANY($4::uuid[])) ORDER BY updated_at ASC LIMIT $3`, [['paid', 'fulfillment_pending'], new Date(input.now.getTime() - input.minimumAgeSeconds * 1000), input.limit, ids])).rows;
8
+ const orderIds = orders.map(row => row.id);
9
+ if (!orderIds.length)
10
+ return { orders: [], fulfillmentOrders: [], dispatchRefs: [], orderPaidOutboxEvents: [] };
11
+ const [shipments, refs, events] = await Promise.all([
12
+ db.query('SELECT id,order_id,$3::text AS provider_kind,status,created_at::text,updated_at::text FROM public.fulfillment_shipments WHERE order_id=ANY($1::uuid[]) AND port_key=$2 ORDER BY created_at DESC', [orderIds, selection.portKey, selection.providerRef]),
13
+ db.query('SELECT ref.id,ref.shipment_id AS fulfillment_order_id,ref.external_ref AS provider_order_id,ref.status,ref.updated_at::text FROM public.fulfillment_dispatch_refs ref JOIN public.fulfillment_shipments shipment ON shipment.id=ref.shipment_id WHERE ref.order_id=ANY($1::uuid[]) AND shipment.port_key=$2', [orderIds, selection.portKey]),
14
+ db.query("SELECT id,event_type,status,aggregate_id,created_at::text,available_at::text,attempts,metadata->>'updatedAt' AS updated_at FROM public.outbox_events WHERE event_type=$1 AND aggregate_id=ANY($2::uuid[]) ORDER BY created_at DESC", ['commerce.order.paid', orderIds]),
15
+ ]);
16
+ return { orders, fulfillmentOrders: shipments.rows, dispatchRefs: refs.rows, orderPaidOutboxEvents: events.rows };
17
+ },
18
+ async requeueDiscardedOrderPaidOutboxEvents(input) {
19
+ const ids = [...new Set(input.eventIds.filter(Boolean))];
20
+ if (!ids.length)
21
+ return { requeuedCount: 0, eventIds: [] };
22
+ const result = await db.query('SELECT id FROM public.outbox_requeue_discarded(p_event_ids=>$1::uuid[],p_event_type=>$2,p_limit=>$3,p_requeued_by=>$4,p_reason=>$5)', [ids, 'commerce.order.paid', input.limit ?? ids.length, input.requeuedBy, input.reason]);
23
+ return { requeuedCount: result.rows.length, eventIds: result.rows.map(row => String(row.id)) };
24
+ },
25
+ };
26
+ }
@@ -0,0 +1,4 @@
1
+ import type { FulfillmentPaidHandoffPort } from './contracts/index.js';
2
+ import { type PgExecutor } from './postgresDispatchStore.js';
3
+ /** Select an existing native port explicitly; never route by a private provider default. */
4
+ export declare function createPostgresPaidFulfillmentHandoffStore(db: PgExecutor, portKey: string): FulfillmentPaidHandoffPort;
@@ -0,0 +1,10 @@
1
+ import { nativeCall } from './postgresDispatchStore.js';
2
+ /** Select an existing native port explicitly; never route by a private provider default. */
3
+ export function createPostgresPaidFulfillmentHandoffStore(db, portKey) {
4
+ if (!portKey.trim())
5
+ throw new Error('fulfillment_port_key_required');
6
+ return {
7
+ ensureObligation: v => nativeCall(db, 'fulfillment_ensure_paid_handoff', [v.requestKey, v.orderRef, v.paidFactRef, portKey]),
8
+ acknowledge: v => nativeCall(db, 'fulfillment_ack_paid_handoff', [v.requestKey, v.fulfillmentRef]),
9
+ };
10
+ }
@@ -0,0 +1,63 @@
1
+ import type { PgExecutor as PgQueryExecutor } from './postgresDispatchStore.js';
2
+ interface ShipmentSpineResult {
3
+ shipmentId: string;
4
+ orderId: string;
5
+ status: string;
6
+ replayed: boolean;
7
+ }
8
+ interface ShipmentRequest {
9
+ idempotencyKey: string;
10
+ shipmentId: string;
11
+ metadata?: Record<string, unknown>;
12
+ requestedAt?: string;
13
+ externalRef?: string;
14
+ }
15
+ interface ShipmentSpineMutationPort {
16
+ createShipment(input: {
17
+ idempotencyKey: string;
18
+ orderId: string;
19
+ metadata?: Record<string, unknown>;
20
+ requestedAt?: string;
21
+ }): Promise<ShipmentSpineResult>;
22
+ recordLabel(input: ShipmentRequest): Promise<ShipmentSpineResult>;
23
+ handOff(input: ShipmentRequest): Promise<ShipmentSpineResult>;
24
+ recordTracking(input: ShipmentRequest & {
25
+ status: 'in_transit' | 'delivered';
26
+ }): Promise<ShipmentSpineResult>;
27
+ cancel(input: ShipmentRequest & {
28
+ reason: string;
29
+ }): Promise<ShipmentSpineResult>;
30
+ raiseException(input: ShipmentRequest & {
31
+ reason: string;
32
+ }): Promise<ShipmentSpineResult>;
33
+ }
34
+ export interface PostgresFulfillmentShipmentSpineOptions {
35
+ portKey: string;
36
+ evidenceChannel?: "poll" | "push";
37
+ requiredProviderType?: "simulator";
38
+ }
39
+ /** Direct node-postgres adapter for the provider-neutral public shipment rail. */
40
+ export declare function createPostgresFulfillmentShipmentSpinePort(executor: PgQueryExecutor, options: PostgresFulfillmentShipmentSpineOptions): ShipmentSpineMutationPort & {
41
+ localPersistence: ReturnType<typeof localPersistence>;
42
+ };
43
+ /** G17 native local persistence, composed on the same injected executor. */
44
+ declare function localPersistence(executor: PgQueryExecutor): {
45
+ readLocalFulfillmentState(ref: string): Promise<{
46
+ status: string | null;
47
+ latestStatusOccurredAt: string | null;
48
+ handedOverAt: string | null;
49
+ }>;
50
+ recordObservation(observation: import("./contracts/index.js").FulfillmentObservation): Promise<{
51
+ replayed: boolean;
52
+ }>;
53
+ recordStatusEvidence(ref: {
54
+ fulfillmentRef: string;
55
+ }, observation: import("./contracts/index.js").FulfillmentObservation): Promise<{
56
+ replayed: boolean;
57
+ }>;
58
+ markProcessed(eventKey: string, outcome: {
59
+ status: "processed" | "ignored";
60
+ refusal?: import("./contracts/index.js").FulfillmentRefusal;
61
+ }): Promise<void>;
62
+ };
63
+ export {};