@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
@@ -0,0 +1,5 @@
1
+ /** Adapters translate structured provider failures into the port result before returning.
2
+ * An unclassified throw after invoking dispatch can follow a successful POST. */
3
+ export function unknownDispatchFailure() {
4
+ return { kind: "unknown", effectMayHaveSucceeded: true, refusal: { reason: "io_failure", phase: "dispatch", retryable: true } };
5
+ }
@@ -0,0 +1,44 @@
1
+ import type { DispatchRecord, FulfillmentDispatchPort, FulfillmentDispatchRequest, FulfillmentStorePort } from "./contracts/index.js";
2
+ export declare function runFulfillmentDispatchWorker(input: {
3
+ store: FulfillmentStorePort;
4
+ provider: FulfillmentDispatchPort | null;
5
+ listCandidates(limit: number): Promise<readonly FulfillmentDispatchRequest[]>;
6
+ /** Return the original host key bytes, without a new package prefix. */
7
+ keys: {
8
+ request(candidate: FulfillmentDispatchRequest): string;
9
+ mappedAttempt(requestKey: string, mappedAttemptIndex: number): string;
10
+ acceptance(fulfillmentRef: string): {
11
+ providerAttemptKey: string;
12
+ labelKey: string;
13
+ };
14
+ };
15
+ config: {
16
+ mode: DispatchRecord["mode"];
17
+ batchLimit: number;
18
+ };
19
+ now?: () => Date;
20
+ }): Promise<{
21
+ redactedFieldCount: number;
22
+ ok: boolean;
23
+ skipped: boolean;
24
+ checked: number;
25
+ updated: number;
26
+ failures: number;
27
+ mode: "shadow" | "stage" | "live";
28
+ replayed: number;
29
+ providerCalls: number;
30
+ readBacks: number;
31
+ reason: string | undefined;
32
+ } | {
33
+ redactedFieldCount?: undefined;
34
+ ok: boolean;
35
+ skipped: boolean;
36
+ checked: number;
37
+ updated: number;
38
+ failures: number;
39
+ mode: "shadow" | "stage" | "live";
40
+ replayed: number;
41
+ providerCalls: number;
42
+ readBacks: number;
43
+ reason: string | undefined;
44
+ }>;
@@ -0,0 +1,199 @@
1
+ import { durableStrings, acceptedProviderProof, dispatchEvidence, dispatchResult, localFailureReason, shadowDispatchEvidence } from "./dispatchProjection.js";
2
+ import { acknowledgeAcceptedDispatch, recoverDispatchAcceptanceWrite } from "./providerDispatchAcceptance.js";
3
+ import { unknownDispatchFailure } from "./providerDispatchError.js";
4
+ export async function runFulfillmentDispatchWorker(input) {
5
+ const privacy = durableStrings();
6
+ const failure = (stage, error) => localFailureReason(stage, error, privacy);
7
+ const diagnostics = () => privacy.redactedFieldCount ? { redactedFieldCount: privacy.redactedFieldCount } : {};
8
+ const result = { ok: true, skipped: false, checked: 0, updated: 0, failures: 0,
9
+ mode: input.config.mode, replayed: 0, providerCalls: 0, readBacks: 0, reason: undefined };
10
+ if (input.config.mode !== "shadow") {
11
+ try {
12
+ await input.store.markStaleSubmissionsUncertain(new Date((input.now?.() ?? new Date()).getTime() - 5 * 60_000).toISOString());
13
+ }
14
+ catch (error) {
15
+ return { ...result, ok: false, failures: 1, reason: failure("dispatch_stale_submission_sweep_failed", error), ...diagnostics() };
16
+ }
17
+ }
18
+ const candidates = await input.listCandidates(input.config.batchLimit);
19
+ result.checked = candidates.length;
20
+ candidateLoop: for (const candidate of candidates) {
21
+ const requestKey = input.keys.request(candidate);
22
+ let stage = "dispatch_read_failed";
23
+ try {
24
+ let readBack = await input.store.read(requestKey);
25
+ if (readBack)
26
+ result.readBacks += 1;
27
+ if (acceptedProviderProof(readBack)) {
28
+ const ack = await acknowledgeAcceptedDispatch({ store: input.store, record: readBack, keys: input.keys.acceptance(candidate.fulfillmentRef) });
29
+ if (ack.replayed)
30
+ result.replayed += 1;
31
+ result.updated += ack.replayed ? 0 : 1;
32
+ continue;
33
+ }
34
+ stage = "dispatch_prepare_failed";
35
+ const preparation = await input.store.prepare(candidate.fulfillmentRef);
36
+ if (preparation.disposition === "withheld")
37
+ continue;
38
+ stage = "dispatch_candidate_read_failed";
39
+ const preparedCandidate = await input.store.readCandidate(candidate.fulfillmentRef);
40
+ if (!preparedCandidate)
41
+ throw new Error("dispatch_prepared_candidate_missing");
42
+ if (input.config.mode !== "shadow" && !input.provider) {
43
+ result.ok = false;
44
+ result.failures += 1;
45
+ result.reason ??= "provider_not_configured";
46
+ continue;
47
+ }
48
+ let mappedCandidate = preparedCandidate;
49
+ let dispatchRef;
50
+ let evidence;
51
+ let providerEvidence;
52
+ let mappedAttemptCount = 0;
53
+ for (let remapCount = 0;; remapCount += 1) {
54
+ const request = { ...mappedCandidate, requestKey };
55
+ stage = "dispatch_command_prepare_failed";
56
+ const prepared = input.config.mode === "shadow"
57
+ ? { kind: "prepared", evidence: shadowDispatchEvidence(request) }
58
+ : await input.provider.prepare(request);
59
+ if (prepared.kind === "refused") {
60
+ result.ok = false;
61
+ result.failures += 1;
62
+ result.reason ??= privacy.token(prepared.refusal.reason) ?? "redacted";
63
+ continue candidateLoop;
64
+ }
65
+ providerEvidence = dispatchEvidence(prepared.evidence);
66
+ evidence = { ...providerEvidence, mapping: { source: "dispatch_worker", mode: input.config.mode, shadowMode: input.config.mode === "shadow" } };
67
+ // Native claims count any JSON change as a remap; attempts compare
68
+ // the whole JSON. Enrichment must not rewrite an existing identity.
69
+ if (readBack && sameCommandIdentity(readBack.evidence, evidence))
70
+ evidence = dispatchEvidence(readBack.evidence);
71
+ stage = "dispatch_claim_failed";
72
+ const claim = await input.store.claim({ requestKey, fulfillmentRef: mappedCandidate.fulfillmentRef,
73
+ orderRef: mappedCandidate.orderRef, parcelRef: mappedCandidate.parcelRef, mode: input.config.mode, evidence });
74
+ if (claim.kind === "refused") {
75
+ if (remapCount === 0 && claim.refusal.reason === "contact_stale") {
76
+ const refreshed = await input.store.readCandidate(candidate.fulfillmentRef);
77
+ if (!refreshed)
78
+ throw new Error("dispatch_contact_remap_candidate_missing");
79
+ mappedCandidate = refreshed;
80
+ continue;
81
+ }
82
+ result.ok = false;
83
+ result.failures += 1;
84
+ result.reason ??= privacy.token(claim.refusal.reason) ?? "redacted";
85
+ continue candidateLoop;
86
+ }
87
+ dispatchRef = claim.record;
88
+ if (dispatchRef.replayed)
89
+ result.replayed += 1;
90
+ // Re-claim may refresh a correctable draft atomically; readback is authoritative.
91
+ stage = "dispatch_readback_failed";
92
+ readBack = await input.store.read(requestKey);
93
+ if (readBack)
94
+ result.readBacks += 1;
95
+ if (!readBack || readBack.fulfillmentRef !== mappedCandidate.fulfillmentRef)
96
+ throw new Error("dispatch_readback_failed");
97
+ stage = "dispatch_attempt_write_failed";
98
+ await input.store.recordProviderAttempt(input.keys.mappedAttempt(requestKey, mappedAttemptCount), mappedCandidate.fulfillmentRef, evidence, input.config.mode, "recorded");
99
+ mappedAttemptCount += 1;
100
+ if (input.config.mode === "shadow") {
101
+ result.updated += dispatchRef.replayed ? 0 : 1;
102
+ continue candidateLoop;
103
+ }
104
+ if (readBack.status !== "draft") {
105
+ result.ok = false;
106
+ result.failures += 1;
107
+ result.reason ??= `dispatch_not_safe_to_submit:${readBack.status}`;
108
+ continue candidateLoop;
109
+ }
110
+ stage = "dispatch_begin_failed";
111
+ const submission = await input.store.begin({ dispatchRef: dispatchRef.dispatchRef, commandFingerprint: evidence.commandFingerprint });
112
+ if (submission.kind === "refused") {
113
+ if (remapCount === 0 && submission.refusal.reason === "contact_stale") {
114
+ const refreshed = await input.store.readCandidate(candidate.fulfillmentRef);
115
+ if (!refreshed)
116
+ throw new Error("dispatch_contact_remap_candidate_missing");
117
+ mappedCandidate = refreshed;
118
+ continue;
119
+ }
120
+ result.ok = false;
121
+ result.failures += 1;
122
+ result.reason ??= privacy.token(submission.refusal.reason) ?? "redacted";
123
+ continue candidateLoop;
124
+ }
125
+ if (!submission.begun) {
126
+ stage = "dispatch_concurrent_read_failed";
127
+ const concurrent = await input.store.read(requestKey);
128
+ if (concurrent)
129
+ result.readBacks += 1;
130
+ if (acceptedProviderProof(concurrent)) {
131
+ const ack = await acknowledgeAcceptedDispatch({ store: input.store, record: concurrent, keys: input.keys.acceptance(mappedCandidate.fulfillmentRef) });
132
+ if (ack.replayed)
133
+ result.replayed += 1;
134
+ result.updated += ack.replayed ? 0 : 1;
135
+ }
136
+ else {
137
+ result.replayed += 1;
138
+ }
139
+ continue candidateLoop;
140
+ }
141
+ if (submission.record.status !== "submitting")
142
+ throw new Error("dispatch_submission_state_invalid");
143
+ break;
144
+ }
145
+ result.providerCalls += 1;
146
+ let response;
147
+ try {
148
+ response = dispatchResult(await input.provider.dispatch({ ...mappedCandidate, requestKey }, providerEvidence));
149
+ }
150
+ catch {
151
+ response = unknownDispatchFailure();
152
+ }
153
+ if (response.kind === "accepted" && JSON.stringify(response.evidence) !== JSON.stringify(providerEvidence)) {
154
+ response = { kind: "unknown", effectMayHaveSucceeded: true, refusal: { reason: "malformed", phase: "acknowledge", retryable: false },
155
+ error: { code: "dispatch_acceptance_evidence_mismatch", status: null, retryable: false, mayHaveSucceeded: true } };
156
+ }
157
+ if (response.kind !== "accepted") {
158
+ stage = "dispatch_finalize_failed";
159
+ await input.store.finalize({ dispatchRef: dispatchRef.dispatchRef, result: response });
160
+ result.ok = false;
161
+ result.failures += 1;
162
+ result.reason ??= response.error?.code ?? response.refusal.reason;
163
+ continue;
164
+ }
165
+ // All ACK paths use the original host keys, ignoring adapter key fields.
166
+ const acceptance = { ...response, evidence, ...input.keys.acceptance(mappedCandidate.fulfillmentRef) };
167
+ try {
168
+ const ack = await input.store.acknowledge({ dispatchRef: dispatchRef.dispatchRef, acceptance });
169
+ if (ack.replayed)
170
+ result.replayed += 1;
171
+ }
172
+ catch (error) {
173
+ const recovery = await recoverDispatchAcceptanceWrite({ store: input.store, requestKey, dispatchRef: dispatchRef.dispatchRef, acceptance, error });
174
+ result.readBacks += recovery.readBacks;
175
+ if (recovery.committed) {
176
+ result.updated += 1;
177
+ continue;
178
+ }
179
+ result.ok = false;
180
+ result.failures += 1;
181
+ result.reason ??= "dispatch_proof_write_failed_after_provider_acceptance";
182
+ break;
183
+ }
184
+ result.updated += 1;
185
+ }
186
+ catch (error) {
187
+ result.ok = false;
188
+ result.failures += 1;
189
+ result.reason ??= failure(stage, error);
190
+ }
191
+ }
192
+ return { ...result, ...diagnostics() };
193
+ }
194
+ function sameCommandIdentity(a, b) {
195
+ return a.commandFingerprint === b.commandFingerprint && a.providerRef === b.providerRef
196
+ && a.carrierRef === b.carrierRef && a.serviceRef === b.serviceRef
197
+ && a.contactRevision.schemaVersion === b.contactRevision.schemaVersion
198
+ && a.contactRevision.source === b.contactRevision.source && a.contactRevision.revision === b.contactRevision.revision;
199
+ }
@@ -0,0 +1,28 @@
1
+ import type { FulfillmentProductSyncPort, FulfillmentProductSyncProvider } from "./contracts/index.js";
2
+ type ReconciliationConflict = Parameters<FulfillmentProductSyncPort["recordReconciliationEvidence"]>[0]["conflictKind"];
3
+ type SyncIdentity = Parameters<FulfillmentProductSyncPort["recordReconciliationEvidence"]>[0]["identity"];
4
+ interface ProductSyncResult {
5
+ ok: boolean;
6
+ pushedProducts: number;
7
+ pushedPacks: number;
8
+ skippedProducts: number;
9
+ pulledSkus: number;
10
+ ingestedPacks: number;
11
+ reconciliations: number;
12
+ replayed: number;
13
+ failures: number;
14
+ providerCalls: number;
15
+ syncRunId: string;
16
+ reason?: string;
17
+ }
18
+ export declare function runFulfillmentProductSyncWorker(input: {
19
+ port: FulfillmentProductSyncPort;
20
+ provider: FulfillmentProductSyncProvider;
21
+ mode?: "push" | "pull" | "both";
22
+ now?: () => Date;
23
+ compatibility: {
24
+ identity(now: Date): SyncIdentity;
25
+ evidenceKey(sku: string, ean: string, kind: ReconciliationConflict): string;
26
+ };
27
+ }): Promise<ProductSyncResult>;
28
+ export {};
@@ -0,0 +1,122 @@
1
+ function packKindForQuantity(quantity) {
2
+ return quantity > 1 ? "collective" : "unit";
3
+ }
4
+ function reconciliationKindFor(conflict) {
5
+ switch (conflict) {
6
+ case "sku_not_found":
7
+ return "unknown_sku";
8
+ case "ean_owned_by_other_sku":
9
+ return "ean_conflict";
10
+ case "local_locked_mismatch":
11
+ return "kind_quantity_conflict";
12
+ default:
13
+ return null;
14
+ }
15
+ }
16
+ export async function runFulfillmentProductSyncWorker(input) {
17
+ const now = input.now?.() ?? new Date();
18
+ const mode = input.mode ?? "both";
19
+ const identity = input.compatibility.identity(now);
20
+ const syncRunId = identity.syncRunId;
21
+ const result = {
22
+ ok: true,
23
+ pushedProducts: 0,
24
+ pushedPacks: 0,
25
+ skippedProducts: 0,
26
+ pulledSkus: 0,
27
+ ingestedPacks: 0,
28
+ reconciliations: 0,
29
+ replayed: 0,
30
+ failures: 0,
31
+ providerCalls: 0,
32
+ syncRunId,
33
+ };
34
+ if (mode === "push" || mode === "both")
35
+ await runPush(input, result);
36
+ if (mode === "pull" || mode === "both")
37
+ await runPull(input, result, identity);
38
+ return result;
39
+ }
40
+ async function runPush(input, result) {
41
+ const localProducts = await input.port.listLocalProductPacks();
42
+ for (const product of localProducts) {
43
+ try {
44
+ const ensured = await input.provider.ensureProduct(product.sku);
45
+ result.providerCalls += 1;
46
+ if (ensured === null) {
47
+ result.skippedProducts += 1;
48
+ continue;
49
+ }
50
+ result.pushedProducts += ensured.replayed ? 0 : 1;
51
+ if (ensured.replayed)
52
+ result.replayed += 1;
53
+ const existingEans = new Set((await input.provider.getProductPacks(product.sku)).map((pack) => pack.ean));
54
+ result.providerCalls += 1;
55
+ for (const pack of product.packs) {
56
+ if (existingEans.has(pack.ean))
57
+ continue;
58
+ await input.provider.addProductPack(product.sku, { ean: pack.ean, quantity: pack.quantity });
59
+ result.providerCalls += 1;
60
+ await input.port.markPackSynced({ sku: product.sku, ean: pack.ean });
61
+ result.pushedPacks += 1;
62
+ }
63
+ }
64
+ catch (error) {
65
+ result.ok = false;
66
+ result.failures += 1;
67
+ result.reason = result.reason ?? "product_sync_operation_failed";
68
+ }
69
+ }
70
+ }
71
+ async function runPull(input, result, identity) {
72
+ const syncRunId = identity.syncRunId;
73
+ const skus = await input.provider.listStockedSkus();
74
+ result.providerCalls += 1;
75
+ for (const sku of skus.filter((value) => value.trim())) {
76
+ try {
77
+ const providerPacks = await input.provider.getProductPacks(sku);
78
+ result.providerCalls += 1;
79
+ result.pulledSkus += 1;
80
+ const activeConflicts = new Set();
81
+ for (const pack of providerPacks.filter((entry) => entry.ean.trim())) {
82
+ const upsert = await input.port.upsertPulledPack({
83
+ sku,
84
+ ean: pack.ean,
85
+ quantity: pack.quantity,
86
+ kind: packKindForQuantity(pack.quantity),
87
+ });
88
+ const conflictKind = reconciliationKindFor(upsert.conflict);
89
+ if (conflictKind === null) {
90
+ if (!upsert.replayed)
91
+ result.ingestedPacks += 1;
92
+ else
93
+ result.replayed += 1;
94
+ continue;
95
+ }
96
+ activeConflicts.add(conflictKind);
97
+ const evidence = await input.port.recordReconciliationEvidence({
98
+ requestKey: input.compatibility.evidenceKey(sku, pack.ean, conflictKind),
99
+ sku,
100
+ ean: pack.ean,
101
+ conflictKind,
102
+ providerQuantity: pack.quantity,
103
+ identity, refusal: null,
104
+ });
105
+ if (evidence.replayed)
106
+ result.replayed += 1;
107
+ else
108
+ result.reconciliations += 1;
109
+ }
110
+ await input.port.resolveReconciliationEvidence({
111
+ sku,
112
+ activeConflictKinds: [...activeConflicts],
113
+ syncRunId,
114
+ });
115
+ }
116
+ catch (error) {
117
+ result.ok = false;
118
+ result.failures += 1;
119
+ result.reason = result.reason ?? "product_sync_operation_failed";
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,9 @@
1
+ import type { FulfillmentObservation } from "./contracts/index.js";
2
+ /** Host decoding supplies known domain reasons, never a raw provider error message. */
3
+ export declare function quarantineReconciliationStateConflict(error: unknown, observation: FulfillmentObservation, classify: (error: unknown) => "fulfillment_not_found" | "stock_consumed_requires_label" | null, record: (observation: FulfillmentObservation, reason: "state_conflict", detail: "fulfillment_not_found" | "stock_consumed_requires_label") => Promise<{
4
+ replayed: boolean;
5
+ }>, result: {
6
+ quarantined: number;
7
+ replayed: number;
8
+ stateConflicts: number;
9
+ }): Promise<unknown | null>;
@@ -0,0 +1,17 @@
1
+ /** Host decoding supplies known domain reasons, never a raw provider error message. */
2
+ export async function quarantineReconciliationStateConflict(error, observation, classify, record, result) {
3
+ const reason = classify(error);
4
+ if (!reason)
5
+ return error;
6
+ try {
7
+ const quarantine = await record(observation, "state_conflict", reason);
8
+ if (quarantine.replayed)
9
+ result.replayed += 1;
10
+ result.quarantined += quarantine.replayed ? 0 : 1;
11
+ result.stateConflicts += 1;
12
+ return null;
13
+ }
14
+ catch (quarantineError) {
15
+ return quarantineError;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ /** Off-track rows still write evidence; acceptance and all effects must skip. */
2
+ export declare function isOffTrackFulfillmentStatus(status: string | null | undefined): boolean;
@@ -0,0 +1,6 @@
1
+ import { FULFILLMENT_STATUS_MAP } from "./statusMap.js";
2
+ const OFF_TRACK_FULFILLMENT_STATUSES = new Set(FULFILLMENT_STATUS_MAP.stages.filter(stage => !stage.onTrack).flatMap(stage => stage.omsFulfillmentStatus));
3
+ /** Off-track rows still write evidence; acceptance and all effects must skip. */
4
+ export function isOffTrackFulfillmentStatus(status) {
5
+ return status !== null && status !== undefined && OFF_TRACK_FULFILLMENT_STATUSES.has(status);
6
+ }
@@ -0,0 +1 @@
1
+ export declare function normalizeReconciliationTimestamp(value: string | null | undefined): string | null;
@@ -0,0 +1,27 @@
1
+ const ISO_TIMESTAMP_WITH_EXPLICIT_ZONE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):?(\d{2}))$/;
2
+ export function normalizeReconciliationTimestamp(value) {
3
+ const occurredAt = value?.trim();
4
+ if (!occurredAt)
5
+ return null;
6
+ const match = ISO_TIMESTAMP_WITH_EXPLICIT_ZONE.exec(occurredAt);
7
+ if (!match || !Number.isFinite(Date.parse(occurredAt)))
8
+ return null;
9
+ const year = Number(match[1]);
10
+ const month = Number(match[2]);
11
+ const day = Number(match[3]);
12
+ const hour = Number(match[4]);
13
+ const minute = Number(match[5]);
14
+ const second = Number(match[6]);
15
+ const offsetHour = match[7] === undefined ? 0 : Number(match[7]);
16
+ const offsetMinute = match[8] === undefined ? 0 : Number(match[8]);
17
+ const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
18
+ const daysInMonth = month === 2
19
+ ? leapYear ? 29 : 28
20
+ : [4, 6, 9, 11].includes(month) ? 30 : 31;
21
+ if (month < 1 || month > 12
22
+ || day < 1 || day > daysInMonth
23
+ || hour > 23 || minute > 59 || second > 59
24
+ || offsetHour > 23 || offsetMinute > 59)
25
+ return null;
26
+ return occurredAt;
27
+ }
@@ -0,0 +1,90 @@
1
+ import type { FulfillmentObservation, FulfillmentObservationPagePort, FulfillmentReconciliationObservation, FulfillmentOperationError } from "./contracts/index.js";
2
+ import { enrichTrackingReference } from "./providerTrackingReferences.js";
3
+ type Ingress = Parameters<typeof import("./verifiedIngress.js").verifyAndNormalizeFulfillmentObservation>[0];
4
+ type DispatchRef = NonNullable<Awaited<ReturnType<Ingress["lifecycle"]["findDispatchRef"]>>>;
5
+ type PollEvidence = Pick<FulfillmentObservation, "correlation" | "eventKey" | "providerStatus" | "diagnostics"> | FulfillmentObservation;
6
+ export interface ReconciliationResult {
7
+ ok: boolean;
8
+ checked: number;
9
+ updated: number;
10
+ trackingRefs: number;
11
+ quarantined: number;
12
+ stateConflicts: number;
13
+ exceptions: number;
14
+ stale: number;
15
+ offTrackSkips: number;
16
+ replayed: number;
17
+ redactedFieldCount?: number;
18
+ failures: number;
19
+ invoiceIssueFailures: number;
20
+ invoiceIssueRefused: number;
21
+ invoiceIssueRefusals: {
22
+ fulfillmentRef: string;
23
+ identifier: string | null;
24
+ sqlstate: string;
25
+ benign: boolean;
26
+ }[];
27
+ providerCalls: number;
28
+ readBacks: number;
29
+ skipped: boolean;
30
+ reason?: string;
31
+ providerError?: FulfillmentOperationError;
32
+ }
33
+ export declare function reconcileFulfillmentObservations(input: {
34
+ /** Adapter/host maps the private page into typed readback, preserving unknowns. */
35
+ readPage(input: {
36
+ page: number;
37
+ size: number;
38
+ }): Promise<readonly FulfillmentReconciliationObservation[]>;
39
+ batchSize: number;
40
+ page?: number;
41
+ localPersistence: {
42
+ /** G17: local persisted chronology, never inferred from dispatch or provider state. */
43
+ readLocalFulfillmentStatus(ref: string): Promise<string | null>;
44
+ latestStatusOccurredAt(ref: string): Promise<string | null>;
45
+ readHandedOverAt(ref: string): Promise<string | null>;
46
+ };
47
+ lifecycle: Pick<Ingress["lifecycle"], "recordStatusEvidence" | "effects" | "keys"> & {
48
+ findDispatchRef(evidence: PollEvidence): Promise<DispatchRef | null>;
49
+ acknowledgeDispatchAcceptance(ref: DispatchRef, evidence: PollEvidence): Promise<void>;
50
+ recordQuarantine(observation: PollEvidence | null, reason: "missing_correlation" | "missing_external_ref" | "unknown_status" | "state_conflict", detail?: "fulfillment_not_found" | "stock_consumed_requires_label"): Promise<{
51
+ replayed: boolean;
52
+ }>;
53
+ recordProviderException(ref: DispatchRef, observation: FulfillmentObservation): Promise<{
54
+ replayed: boolean;
55
+ }>;
56
+ readDeliveryCarrier(ref: string): Promise<{
57
+ carrierRef: string | null;
58
+ serviceRef: string | null;
59
+ } | null>;
60
+ trackingCodecs: Parameters<typeof enrichTrackingReference>[2];
61
+ issueAccountingInvoice?(ref: string): Promise<void>;
62
+ /** Private RPC decoding retains permanent/benign distinction and safe refusal identity. */
63
+ invoiceFailure(error: unknown): {
64
+ permanent: boolean;
65
+ identifier: string | null;
66
+ sqlstate: string | null;
67
+ benign: boolean;
68
+ };
69
+ classifyStateConflict(error: unknown): "fulfillment_not_found" | "stock_consumed_requires_label" | null;
70
+ };
71
+ }): Promise<ReconciliationResult>;
72
+ /** Host owns scheduling, HTTP and durable job-ledger writes. This operation only projects them. */
73
+ export declare function runFulfillmentReconciliationPage(input: Omit<Parameters<typeof reconcileFulfillmentObservations>[0], "readPage" | "batchSize" | "page"> & {
74
+ provider: FulfillmentObservationPagePort;
75
+ pageSize: number;
76
+ checkpoint: unknown;
77
+ }): Promise<{
78
+ status: 200 | 502;
79
+ ledgerStatus: "failed" | "succeeded";
80
+ result: ReconciliationResult;
81
+ metadata: {
82
+ reconciliationPagination: {
83
+ version: number;
84
+ page: number;
85
+ pageSize: number;
86
+ nextPage: number;
87
+ };
88
+ };
89
+ }>;
90
+ export {};