@openlup/platform 0.25.0 → 0.27.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 (524) hide show
  1. package/CHANGELOG.md +156 -440
  2. package/README.md +230 -11
  3. package/dist/commerce/adapters/managed/commerceOmsControlPlane.d.ts +3 -0
  4. package/dist/commerce/adapters/managed/commerceOmsControlPlane.js +71 -0
  5. package/dist/commerce/adapters/managed/commerceOmsMutations.d.ts +10 -0
  6. package/dist/commerce/adapters/managed/commerceOmsMutations.js +119 -0
  7. package/dist/commerce/adapters/managed/commerceOmsPort.d.ts +28 -0
  8. package/dist/commerce/adapters/managed/commerceOmsPort.js +101 -0
  9. package/dist/commerce/adapters/managed/oms/accounting.d.ts +3 -0
  10. package/dist/commerce/adapters/managed/oms/accounting.js +13 -0
  11. package/dist/commerce/adapters/managed/oms/fulfillmentReads.d.ts +17 -0
  12. package/dist/commerce/adapters/managed/oms/fulfillmentReads.js +81 -0
  13. package/dist/commerce/adapters/managed/oms/inboundEvents.d.ts +9 -0
  14. package/dist/commerce/adapters/managed/oms/inboundEvents.js +40 -0
  15. package/dist/commerce/adapters/managed/oms/outboxEvents.d.ts +2 -0
  16. package/dist/commerce/adapters/managed/oms/outboxEvents.js +23 -0
  17. package/dist/commerce/adapters/managed/oms/paymentAttempts.d.ts +3 -0
  18. package/dist/commerce/adapters/managed/oms/paymentAttempts.js +15 -0
  19. package/dist/commerce/adapters/managed/oms/queueSelection.d.ts +12 -0
  20. package/dist/commerce/adapters/managed/oms/queueSelection.js +109 -0
  21. package/dist/commerce/adapters/managed/oms/readProjections.d.ts +18 -0
  22. package/dist/commerce/adapters/managed/oms/readProjections.js +13 -0
  23. package/dist/commerce/adapters/managed/oms/readQueries.d.ts +16 -0
  24. package/dist/commerce/adapters/managed/oms/readQueries.js +276 -0
  25. package/dist/commerce/adapters/managed/oms/types.d.ts +2 -0
  26. package/dist/commerce/adapters/managed/oms/types.js +7 -0
  27. package/dist/commerce/checkoutCommandSchemas.d.ts +89 -0
  28. package/dist/commerce/checkoutCommandSchemas.js +70 -0
  29. package/dist/commerce/checkoutHelpers.d.ts +21 -0
  30. package/dist/commerce/checkoutHelpers.js +29 -0
  31. package/dist/commerce/checkoutResumeSchemas.d.ts +158 -0
  32. package/dist/commerce/checkoutResumeSchemas.js +145 -0
  33. package/dist/commerce/checkoutSchemas.d.ts +158 -0
  34. package/dist/commerce/checkoutSchemas.js +161 -0
  35. package/dist/commerce/commerceReturnsPort.d.ts +97 -0
  36. package/dist/commerce/commerceReturnsPort.js +39 -0
  37. package/dist/commerce/configuratorIntentPersistenceSchemas.d.ts +20 -0
  38. package/dist/commerce/configuratorIntentPersistenceSchemas.js +21 -0
  39. package/dist/commerce/configuratorIntentSchemas.d.ts +63 -0
  40. package/dist/commerce/configuratorIntentSchemas.js +43 -0
  41. package/dist/commerce/contractPrimitives.d.ts +50 -0
  42. package/dist/commerce/contractPrimitives.js +25 -0
  43. package/dist/commerce/contracts/availability.d.ts +23 -0
  44. package/dist/commerce/contracts/availability.js +1 -0
  45. package/dist/commerce/contracts/fulfillmentRecovery.d.ts +25 -0
  46. package/dist/commerce/contracts/fulfillmentRecovery.js +1 -0
  47. package/dist/commerce/contracts/index.d.ts +13 -0
  48. package/dist/commerce/contracts/index.js +1 -0
  49. package/dist/commerce/contracts/intent.d.ts +86 -0
  50. package/dist/commerce/contracts/intent.js +1 -0
  51. package/dist/commerce/contracts/omsTypes.d.ts +1216 -0
  52. package/dist/commerce/contracts/omsTypes.js +1 -0
  53. package/dist/commerce/contracts/order.d.ts +39 -0
  54. package/dist/commerce/contracts/order.js +1 -0
  55. package/dist/commerce/contracts/orderMoney.d.ts +52 -0
  56. package/dist/commerce/contracts/orderMoney.js +1 -0
  57. package/dist/commerce/contracts/ports.d.ts +113 -0
  58. package/dist/commerce/contracts/ports.js +1 -0
  59. package/dist/commerce/contracts/recovery.d.ts +11 -0
  60. package/dist/commerce/contracts/recovery.js +1 -0
  61. package/dist/commerce/contracts/runtimePorts.d.ts +196 -0
  62. package/dist/commerce/contracts/runtimePorts.js +1 -0
  63. package/dist/commerce/contracts/state.d.ts +26 -0
  64. package/dist/commerce/contracts/state.js +43 -0
  65. package/dist/commerce/customerDefaultsSnapshotSchemas.d.ts +51 -0
  66. package/dist/commerce/customerDefaultsSnapshotSchemas.js +106 -0
  67. package/dist/commerce/errors.d.ts +18 -0
  68. package/dist/commerce/errors.js +36 -0
  69. package/dist/commerce/fulfillmentEligibility.d.ts +6 -0
  70. package/dist/commerce/fulfillmentEligibility.js +31 -0
  71. package/dist/commerce/index.d.ts +72 -0
  72. package/dist/commerce/index.js +67 -0
  73. package/dist/commerce/model/customerFulfillmentRecovery.d.ts +40 -0
  74. package/dist/commerce/model/customerFulfillmentRecovery.js +144 -0
  75. package/dist/commerce/model/fulfillmentCancellationEligibility.d.ts +7 -0
  76. package/dist/commerce/model/fulfillmentCancellationEligibility.js +9 -0
  77. package/dist/commerce/model/omsAccountingVisibility.d.ts +12 -0
  78. package/dist/commerce/model/omsAccountingVisibility.js +118 -0
  79. package/dist/commerce/model/omsBillingInvoiceBuyer.d.ts +2 -0
  80. package/dist/commerce/model/omsBillingInvoiceBuyer.js +15 -0
  81. package/dist/commerce/model/omsCurrency.d.ts +4 -0
  82. package/dist/commerce/model/omsCurrency.js +5 -0
  83. package/dist/commerce/model/omsFulfillmentDebug.d.ts +20 -0
  84. package/dist/commerce/model/omsFulfillmentDebug.js +122 -0
  85. package/dist/commerce/model/omsFulfillmentSummary.d.ts +16 -0
  86. package/dist/commerce/model/omsFulfillmentSummary.js +189 -0
  87. package/dist/commerce/model/omsListTotals.d.ts +13 -0
  88. package/dist/commerce/model/omsListTotals.js +32 -0
  89. package/dist/commerce/model/omsOperationalLadder.d.ts +51 -0
  90. package/dist/commerce/model/omsOperationalLadder.js +158 -0
  91. package/dist/commerce/model/omsOrderLineMoney.d.ts +4 -0
  92. package/dist/commerce/model/omsOrderLineMoney.js +25 -0
  93. package/dist/commerce/model/omsPaymentMethodSummary.d.ts +5 -0
  94. package/dist/commerce/model/omsPaymentMethodSummary.js +11 -0
  95. package/dist/commerce/model/omsReadModel.d.ts +43 -0
  96. package/dist/commerce/model/omsReadModel.js +211 -0
  97. package/dist/commerce/model/omsReadModelCommunication.d.ts +3 -0
  98. package/dist/commerce/model/omsReadModelCommunication.js +29 -0
  99. package/dist/commerce/model/omsReadModelHelpers.d.ts +125 -0
  100. package/dist/commerce/model/omsReadModelHelpers.js +212 -0
  101. package/dist/commerce/model/omsReadModelList.d.ts +33 -0
  102. package/dist/commerce/model/omsReadModelList.js +50 -0
  103. package/dist/commerce/model/omsReadModelListSummary.d.ts +3 -0
  104. package/dist/commerce/model/omsReadModelListSummary.js +13 -0
  105. package/dist/commerce/model/omsReadModelPricing.d.ts +5 -0
  106. package/dist/commerce/model/omsReadModelPricing.js +36 -0
  107. package/dist/commerce/model/omsReadModelProjections.d.ts +1 -0
  108. package/dist/commerce/model/omsReadModelProjections.js +1 -0
  109. package/dist/commerce/model/omsReadModelRowCore.d.ts +79 -0
  110. package/dist/commerce/model/omsReadModelRowCore.js +149 -0
  111. package/dist/commerce/model/omsReadModelRows.d.ts +1 -0
  112. package/dist/commerce/model/omsReadModelRows.js +6 -0
  113. package/dist/commerce/offerAvailability.d.ts +18 -0
  114. package/dist/commerce/offerAvailability.js +53 -0
  115. package/dist/commerce/offerAvailabilitySchemas.d.ts +43 -0
  116. package/dist/commerce/offerAvailabilitySchemas.js +42 -0
  117. package/dist/commerce/offerEvidenceSchemas.d.ts +7 -0
  118. package/dist/commerce/offerEvidenceSchemas.js +13 -0
  119. package/dist/commerce/oms/omsContractBase.d.ts +130 -0
  120. package/dist/commerce/oms/omsContractBase.js +86 -0
  121. package/dist/commerce/oms/omsContractReadAuxSchemas.d.ts +222 -0
  122. package/dist/commerce/oms/omsContractReadAuxSchemas.js +123 -0
  123. package/dist/commerce/oms/omsContractReadSchemas.d.ts +2266 -0
  124. package/dist/commerce/oms/omsContractReadSchemas.js +277 -0
  125. package/dist/commerce/oms/omsContractRequests.d.ts +196 -0
  126. package/dist/commerce/oms/omsContractRequests.js +118 -0
  127. package/dist/commerce/oms/omsContracts.d.ts +5 -0
  128. package/dist/commerce/oms/omsContracts.js +4 -0
  129. package/dist/commerce/oms/omsControlPlane.d.ts +275 -0
  130. package/dist/commerce/oms/omsControlPlane.js +72 -0
  131. package/dist/commerce/oms/omsFulfillmentContractSchemas.d.ts +203 -0
  132. package/dist/commerce/oms/omsFulfillmentContractSchemas.js +94 -0
  133. package/dist/commerce/oms/omsFulfillmentDebugSchemas.d.ts +69 -0
  134. package/dist/commerce/oms/omsFulfillmentDebugSchemas.js +33 -0
  135. package/dist/commerce/oms/omsFulfillmentHealthSchemas.d.ts +67 -0
  136. package/dist/commerce/oms/omsFulfillmentHealthSchemas.js +44 -0
  137. package/dist/commerce/oms/omsPorts.d.ts +84 -0
  138. package/dist/commerce/oms/omsPorts.js +148 -0
  139. package/dist/commerce/oms/omsPrimitives.d.ts +5 -0
  140. package/dist/commerce/oms/omsPrimitives.js +3 -0
  141. package/dist/commerce/oms/omsProviderEvidenceSchemas.d.ts +15 -0
  142. package/dist/commerce/oms/omsProviderEvidenceSchemas.js +12 -0
  143. package/dist/commerce/orderDraftErrors.d.ts +13 -0
  144. package/dist/commerce/orderDraftErrors.js +20 -0
  145. package/dist/commerce/orderEmailEligibility.d.ts +54 -0
  146. package/dist/commerce/orderEmailEligibility.js +123 -0
  147. package/dist/commerce/orderEmailLines.d.ts +12 -0
  148. package/dist/commerce/orderEmailLines.js +8 -0
  149. package/dist/commerce/orderFeedbackContracts.d.ts +41 -0
  150. package/dist/commerce/orderFeedbackContracts.js +33 -0
  151. package/dist/commerce/orderMoney.d.ts +6 -0
  152. package/dist/commerce/orderMoney.js +168 -0
  153. package/dist/commerce/orderReviewContracts.d.ts +475 -0
  154. package/dist/commerce/orderReviewContracts.js +94 -0
  155. package/dist/commerce/orderReviewPorts.d.ts +140 -0
  156. package/dist/commerce/orderReviewPorts.js +1 -0
  157. package/dist/commerce/outboxDispatchContracts.d.ts +30 -0
  158. package/dist/commerce/outboxDispatchContracts.js +1 -0
  159. package/dist/commerce/outboxEventSchemas.d.ts +162 -0
  160. package/dist/commerce/outboxEventSchemas.js +164 -0
  161. package/dist/commerce/outboxOrderDraftEmailPorts.d.ts +207 -0
  162. package/dist/commerce/outboxOrderDraftEmailPorts.js +12 -0
  163. package/dist/commerce/paymentContinuation.d.ts +4 -0
  164. package/dist/commerce/paymentContinuation.js +4 -0
  165. package/dist/commerce/ports.d.ts +8 -0
  166. package/dist/commerce/ports.js +1 -0
  167. package/dist/commerce/recoveryDestination.d.ts +3 -0
  168. package/dist/commerce/recoveryDestination.js +17 -0
  169. package/dist/commerce/runtimeErrors.d.ts +8 -0
  170. package/dist/commerce/runtimeErrors.js +16 -0
  171. package/dist/commerce/salesChannelEnvelope.d.ts +20 -0
  172. package/dist/commerce/salesChannelEnvelope.js +7 -0
  173. package/dist/commerce/schemas.d.ts +174 -0
  174. package/dist/commerce/schemas.js +84 -0
  175. package/dist/commerce/server/checkoutCompensation.d.ts +21 -0
  176. package/dist/commerce/server/checkoutCompensation.js +32 -0
  177. package/dist/commerce/server/checkoutConflictClassifiers.d.ts +17 -0
  178. package/dist/commerce/server/checkoutConflictClassifiers.js +38 -0
  179. package/dist/commerce/server/checkoutExpiredRecoveryPolicy.d.ts +38 -0
  180. package/dist/commerce/server/checkoutExpiredRecoveryPolicy.js +85 -0
  181. package/dist/commerce/server/checkoutInvoiceBuyerSnapshot.d.ts +22 -0
  182. package/dist/commerce/server/checkoutInvoiceBuyerSnapshot.js +30 -0
  183. package/dist/commerce/server/checkoutOfferPolicyPort.d.ts +33 -0
  184. package/dist/commerce/server/checkoutOfferPolicyPort.js +49 -0
  185. package/dist/commerce/server/checkoutPaymentContinuationCredential.d.ts +58 -0
  186. package/dist/commerce/server/checkoutPaymentContinuationCredential.js +154 -0
  187. package/dist/commerce/server/checkoutQuoteTypes.d.ts +19 -0
  188. package/dist/commerce/server/checkoutQuoteTypes.js +1 -0
  189. package/dist/commerce/server/checkoutRecoveryOrderPort.d.ts +42 -0
  190. package/dist/commerce/server/checkoutRecoveryOrderPort.js +1 -0
  191. package/dist/commerce/server/checkoutRecoveryToken.d.ts +40 -0
  192. package/dist/commerce/server/checkoutRecoveryToken.js +26 -0
  193. package/dist/commerce/server/checkoutRefusalContinuation.d.ts +24 -0
  194. package/dist/commerce/server/checkoutRefusalContinuation.js +18 -0
  195. package/dist/commerce/server/checkoutRuntimeTypes.d.ts +81 -0
  196. package/dist/commerce/server/checkoutRuntimeTypes.js +1 -0
  197. package/dist/commerce/server/commerceCheckoutCommandExecution.d.ts +60 -0
  198. package/dist/commerce/server/commerceCheckoutCommandExecution.js +136 -0
  199. package/dist/commerce/server/commerceCheckoutCompensation.d.ts +26 -0
  200. package/dist/commerce/server/commerceCheckoutCompensation.js +46 -0
  201. package/dist/commerce/server/commerceCheckoutContinuationTerms.d.ts +50 -0
  202. package/dist/commerce/server/commerceCheckoutContinuationTerms.js +66 -0
  203. package/dist/commerce/server/commerceCheckoutCustomerDefaults.d.ts +18 -0
  204. package/dist/commerce/server/commerceCheckoutCustomerDefaults.js +17 -0
  205. package/dist/commerce/server/commerceCheckoutFailureHandler.d.ts +51 -0
  206. package/dist/commerce/server/commerceCheckoutFailureHandler.js +90 -0
  207. package/dist/commerce/server/commerceCheckoutHandler.d.ts +213 -0
  208. package/dist/commerce/server/commerceCheckoutHandler.js +196 -0
  209. package/dist/commerce/server/commerceCheckoutHandlerAdmission.d.ts +58 -0
  210. package/dist/commerce/server/commerceCheckoutHandlerAdmission.js +94 -0
  211. package/dist/commerce/server/commerceCheckoutHandlerHelpers.d.ts +67 -0
  212. package/dist/commerce/server/commerceCheckoutHandlerHelpers.js +155 -0
  213. package/dist/commerce/server/commerceCheckoutOrchestrationError.d.ts +9 -0
  214. package/dist/commerce/server/commerceCheckoutOrchestrationError.js +14 -0
  215. package/dist/commerce/server/commerceCheckoutPromotionPriceChange.d.ts +47 -0
  216. package/dist/commerce/server/commerceCheckoutPromotionPriceChange.js +43 -0
  217. package/dist/commerce/server/commerceCheckoutProviderPayment.d.ts +34 -0
  218. package/dist/commerce/server/commerceCheckoutProviderPayment.js +37 -0
  219. package/dist/commerce/server/commerceCheckoutQuoteGuard.d.ts +62 -0
  220. package/dist/commerce/server/commerceCheckoutQuoteGuard.js +106 -0
  221. package/dist/commerce/server/commerceCheckoutResume.d.ts +29 -0
  222. package/dist/commerce/server/commerceCheckoutResume.js +81 -0
  223. package/dist/commerce/server/commerceCheckoutResumeGuard.d.ts +54 -0
  224. package/dist/commerce/server/commerceCheckoutResumeGuard.js +138 -0
  225. package/dist/commerce/server/commerceCheckoutSavedPaymentMethod.d.ts +39 -0
  226. package/dist/commerce/server/commerceCheckoutSavedPaymentMethod.js +44 -0
  227. package/dist/commerce/server/commerceCheckoutStartRuntimeFailure.d.ts +7 -0
  228. package/dist/commerce/server/commerceCheckoutStartRuntimeFailure.js +39 -0
  229. package/dist/commerce/server/commerceCheckoutTiming.d.ts +8 -0
  230. package/dist/commerce/server/commerceCheckoutTiming.js +31 -0
  231. package/dist/commerce/server/commerceDiagnostics.d.ts +6 -0
  232. package/dist/commerce/server/commerceDiagnostics.js +31 -0
  233. package/dist/commerce/server/commerceOmsCancelOrderHandler.d.ts +7 -0
  234. package/dist/commerce/server/commerceOmsCancelOrderHandler.js +22 -0
  235. package/dist/commerce/server/commerceOmsControlPlaneHandlers.d.ts +18 -0
  236. package/dist/commerce/server/commerceOmsControlPlaneHandlers.js +60 -0
  237. package/dist/commerce/server/commerceOmsHandlers.d.ts +47 -0
  238. package/dist/commerce/server/commerceOmsHandlers.js +176 -0
  239. package/dist/commerce/server/commerceOmsMarkRefundedHandler.d.ts +7 -0
  240. package/dist/commerce/server/commerceOmsMarkRefundedHandler.js +19 -0
  241. package/dist/commerce/server/commerceOrderDraft.d.ts +24 -0
  242. package/dist/commerce/server/commerceOrderDraft.js +92 -0
  243. package/dist/commerce/server/commercePaidOrderOrchestration.d.ts +131 -0
  244. package/dist/commerce/server/commercePaidOrderOrchestration.js +140 -0
  245. package/dist/commerce/server/commerceProviderAttemptFailure.d.ts +133 -0
  246. package/dist/commerce/server/commerceProviderAttemptFailure.js +175 -0
  247. package/dist/commerce/server/commerceReturnsHandlers.d.ts +41 -0
  248. package/dist/commerce/server/commerceReturnsHandlers.js +100 -0
  249. package/dist/commerce/server/commerceRuntimePort.d.ts +16 -0
  250. package/dist/commerce/server/commerceRuntimePort.js +57 -0
  251. package/dist/commerce/server/commerceRuntimeService.d.ts +98 -0
  252. package/dist/commerce/server/commerceRuntimeService.js +186 -0
  253. package/dist/commerce/server/commerceRuntimeStartResponse.d.ts +37 -0
  254. package/dist/commerce/server/commerceRuntimeStartResponse.js +56 -0
  255. package/dist/commerce/server/commerceStarterOfferGuard.d.ts +55 -0
  256. package/dist/commerce/server/commerceStarterOfferGuard.js +128 -0
  257. package/dist/commerce/server/configuratorIntentPersistence.d.ts +47 -0
  258. package/dist/commerce/server/configuratorIntentPersistence.js +85 -0
  259. package/dist/commerce/server/configuratorIntentPersistenceHandler.d.ts +14 -0
  260. package/dist/commerce/server/configuratorIntentPersistenceHandler.js +42 -0
  261. package/dist/commerce/server/emailRuntime.d.ts +47 -0
  262. package/dist/commerce/server/emailRuntime.js +1 -0
  263. package/dist/commerce/server/handlerSupport.d.ts +68 -0
  264. package/dist/commerce/server/handlerSupport.js +1 -0
  265. package/dist/commerce/server/index.d.ts +178 -0
  266. package/dist/commerce/server/index.js +127 -0
  267. package/dist/commerce/server/offerAvailability.d.ts +21 -0
  268. package/dist/commerce/server/offerAvailability.js +163 -0
  269. package/dist/commerce/server/orderDraftRpcPayload.d.ts +20 -0
  270. package/dist/commerce/server/orderDraftRpcPayload.js +21 -0
  271. package/dist/commerce/server/orderFeedbackSubmit.d.ts +20 -0
  272. package/dist/commerce/server/orderFeedbackSubmit.js +16 -0
  273. package/dist/commerce/server/orderFeedbackTokenCheck.d.ts +17 -0
  274. package/dist/commerce/server/orderFeedbackTokenCheck.js +14 -0
  275. package/dist/commerce/server/orderReviewAdminHandlers.d.ts +47 -0
  276. package/dist/commerce/server/orderReviewAdminHandlers.js +41 -0
  277. package/dist/commerce/server/orderReviewHandlers.d.ts +114 -0
  278. package/dist/commerce/server/orderReviewHandlers.js +42 -0
  279. package/dist/commerce/server/orderReviewLifecycle.d.ts +10 -0
  280. package/dist/commerce/server/orderReviewLifecycle.js +121 -0
  281. package/dist/commerce/server/orderReviewMedia.d.ts +11 -0
  282. package/dist/commerce/server/orderReviewMedia.js +172 -0
  283. package/dist/commerce/server/orderReviewRawUploadHandler.d.ts +40 -0
  284. package/dist/commerce/server/orderReviewRawUploadHandler.js +316 -0
  285. package/dist/commerce/server/outboxCheckoutExpiredEmailHandler.d.ts +14 -0
  286. package/dist/commerce/server/outboxCheckoutExpiredEmailHandler.js +57 -0
  287. package/dist/commerce/server/outboxCheckoutRecoveryEmailHandler.d.ts +13 -0
  288. package/dist/commerce/server/outboxCheckoutRecoveryEmailHandler.js +150 -0
  289. package/dist/commerce/server/outboxDispatchRegistry.d.ts +46 -0
  290. package/dist/commerce/server/outboxDispatchRegistry.js +184 -0
  291. package/dist/commerce/server/outboxDispatchRegistryComposition.d.ts +6 -0
  292. package/dist/commerce/server/outboxDispatchRegistryComposition.js +23 -0
  293. package/dist/commerce/server/outboxOrderDraftEmailHandler.d.ts +14 -0
  294. package/dist/commerce/server/outboxOrderDraftEmailHandler.js +130 -0
  295. package/dist/commerce/server/outboxOrderPaidEmailHandler.d.ts +21 -0
  296. package/dist/commerce/server/outboxOrderPaidEmailHandler.js +93 -0
  297. package/dist/commerce/server/outboxOrderPaidFulfillmentHandler.d.ts +3 -0
  298. package/dist/commerce/server/outboxOrderPaidFulfillmentHandler.js +1 -0
  299. package/dist/commerce/server/outboxOrderPaidFulfillmentPorts.d.ts +3 -0
  300. package/dist/commerce/server/outboxOrderPaidFulfillmentPorts.js +1 -0
  301. package/dist/commerce/server/outboxOrderRefundedEmailHandler.d.ts +13 -0
  302. package/dist/commerce/server/outboxOrderRefundedEmailHandler.js +42 -0
  303. package/dist/commerce/server/outboxPaymentFailedEmailHandler.d.ts +14 -0
  304. package/dist/commerce/server/outboxPaymentFailedEmailHandler.js +65 -0
  305. package/dist/commerce/server/outboxReturnEmailHandlers.d.ts +26 -0
  306. package/dist/commerce/server/outboxReturnEmailHandlers.js +53 -0
  307. package/dist/commerce/server/outboxShipmentDeliveredEmailHandler.d.ts +17 -0
  308. package/dist/commerce/server/outboxShipmentDeliveredEmailHandler.js +52 -0
  309. package/dist/commerce/server/outboxShipmentDispatchedEmailHandler.d.ts +13 -0
  310. package/dist/commerce/server/outboxShipmentDispatchedEmailHandler.js +87 -0
  311. package/dist/commerce/server/outboxShipmentExceptionEmailHandler.d.ts +13 -0
  312. package/dist/commerce/server/outboxShipmentExceptionEmailHandler.js +46 -0
  313. package/dist/commerce/server/referenceCheckoutHandler.d.ts +48 -0
  314. package/dist/commerce/server/referenceCheckoutHandler.js +68 -0
  315. package/dist/commerce/server/reservationSweepPort.d.ts +31 -0
  316. package/dist/commerce/server/reservationSweepPort.js +45 -0
  317. package/dist/commerce/server/starterTermsPort.d.ts +22 -0
  318. package/dist/commerce/server/starterTermsPort.js +1 -0
  319. package/dist/commerce/server/supabaseCommerceReturnsPort.d.ts +13 -0
  320. package/dist/commerce/server/supabaseCommerceReturnsPort.js +56 -0
  321. package/dist/communications/consentPurposeRegistry.d.ts +1 -1
  322. package/dist/communications/newsletterIntegrationContracts.d.ts +5 -5
  323. package/dist/composition/commerceContribution.d.ts +21 -0
  324. package/dist/composition/commerceContribution.js +27 -0
  325. package/dist/composition/index.d.ts +1 -0
  326. package/dist/composition/index.js +1 -0
  327. package/dist/fulfillment/handlerSchemas.d.ts +41 -41
  328. package/dist/fulfillment/index.d.ts +1 -1
  329. package/dist/fulfillment/index.js +1 -1
  330. package/dist/fulfillment/paidHandoff.d.ts +12 -1
  331. package/dist/fulfillment/paidHandoff.js +2 -2
  332. package/dist/fulfillment/providerDispatchWorker.d.ts +4 -4
  333. package/dist/identity/customerContracts.d.ts +2 -2
  334. package/dist/inventory/bindings.d.ts +3 -0
  335. package/dist/inventory/bindings.js +10 -4
  336. package/dist/inventory/index.d.ts +1 -0
  337. package/dist/inventory/index.js +1 -0
  338. package/dist/inventory/managedStockAvailability.d.ts +15 -0
  339. package/dist/inventory/managedStockAvailability.js +16 -0
  340. package/dist/inventory/postgresStockAvailability.js +2 -25
  341. package/dist/inventory/schemas.d.ts +1 -1
  342. package/dist/inventory/stockReadResponse.d.ts +4 -0
  343. package/dist/inventory/stockReadResponse.js +27 -0
  344. package/dist/pricing/browser/index.d.ts +6 -0
  345. package/dist/pricing/browser/index.js +6 -0
  346. package/dist/promotions/adminPromotionsContracts.d.ts +2 -2
  347. package/dist/subscriptions/contracts/renewal.d.ts +2 -0
  348. package/dist/subscriptions/index.d.ts +3 -2
  349. package/dist/subscriptions/index.js +3 -2
  350. package/dist/subscriptions/renewalCycleFailureMechanism.js +3 -2
  351. package/package.json +22 -2
  352. package/release-gates.json +63 -8
  353. package/src/commerce/adapters/managed/commerceOmsControlPlane.ts +80 -0
  354. package/src/commerce/adapters/managed/commerceOmsMutations.ts +145 -0
  355. package/src/commerce/adapters/managed/commerceOmsPort.ts +158 -0
  356. package/src/commerce/adapters/managed/oms/accounting.ts +18 -0
  357. package/src/commerce/adapters/managed/oms/fulfillmentReads.ts +82 -0
  358. package/src/commerce/adapters/managed/oms/inboundEvents.ts +45 -0
  359. package/src/commerce/adapters/managed/oms/outboxEvents.ts +30 -0
  360. package/src/commerce/adapters/managed/oms/paymentAttempts.ts +19 -0
  361. package/src/commerce/adapters/managed/oms/queueSelection.ts +132 -0
  362. package/src/commerce/adapters/managed/oms/readProjections.ts +22 -0
  363. package/src/commerce/adapters/managed/oms/readQueries.ts +292 -0
  364. package/src/commerce/adapters/managed/oms/types.ts +9 -0
  365. package/src/commerce/checkoutCommandSchemas.ts +93 -0
  366. package/src/commerce/checkoutHelpers.ts +47 -0
  367. package/src/commerce/checkoutResumeSchemas.ts +164 -0
  368. package/src/commerce/checkoutSchemas.ts +182 -0
  369. package/src/commerce/commerceReturnsPort.ts +67 -0
  370. package/src/commerce/configuratorIntentPersistenceSchemas.ts +26 -0
  371. package/src/commerce/configuratorIntentSchemas.ts +47 -0
  372. package/src/commerce/contractPrimitives.ts +30 -0
  373. package/src/commerce/contracts/availability.ts +21 -0
  374. package/src/commerce/contracts/fulfillmentRecovery.ts +26 -0
  375. package/src/commerce/contracts/index.ts +17 -0
  376. package/src/commerce/contracts/intent.ts +58 -0
  377. package/src/commerce/contracts/omsTypes.ts +1217 -0
  378. package/src/commerce/contracts/order.ts +44 -0
  379. package/src/commerce/contracts/orderMoney.ts +75 -0
  380. package/src/commerce/contracts/ports.ts +124 -0
  381. package/src/commerce/contracts/recovery.ts +24 -0
  382. package/src/commerce/contracts/runtimePorts.ts +201 -0
  383. package/src/commerce/contracts/state.ts +64 -0
  384. package/src/commerce/customerDefaultsSnapshotSchemas.ts +117 -0
  385. package/src/commerce/errors.ts +53 -0
  386. package/src/commerce/fulfillmentEligibility.ts +32 -0
  387. package/src/commerce/index.ts +82 -0
  388. package/src/commerce/model/customerFulfillmentRecovery.ts +185 -0
  389. package/src/commerce/model/fulfillmentCancellationEligibility.ts +18 -0
  390. package/src/commerce/model/omsAccountingVisibility.ts +135 -0
  391. package/src/commerce/model/omsBillingInvoiceBuyer.ts +20 -0
  392. package/src/commerce/model/omsCurrency.ts +8 -0
  393. package/src/commerce/model/omsFulfillmentDebug.ts +157 -0
  394. package/src/commerce/model/omsFulfillmentSummary.ts +225 -0
  395. package/src/commerce/model/omsListTotals.ts +38 -0
  396. package/src/commerce/model/omsOperationalLadder.ts +181 -0
  397. package/src/commerce/model/omsOrderLineMoney.ts +34 -0
  398. package/src/commerce/model/omsPaymentMethodSummary.ts +19 -0
  399. package/src/commerce/model/omsReadModel.ts +302 -0
  400. package/src/commerce/model/omsReadModelCommunication.ts +32 -0
  401. package/src/commerce/model/omsReadModelHelpers.ts +279 -0
  402. package/src/commerce/model/omsReadModelList.ts +90 -0
  403. package/src/commerce/model/omsReadModelListSummary.ts +19 -0
  404. package/src/commerce/model/omsReadModelPricing.ts +57 -0
  405. package/src/commerce/model/omsReadModelProjections.ts +1 -0
  406. package/src/commerce/model/omsReadModelRowCore.ts +193 -0
  407. package/src/commerce/model/omsReadModelRows.ts +7 -0
  408. package/src/commerce/offerAvailability.ts +75 -0
  409. package/src/commerce/offerAvailabilitySchemas.ts +56 -0
  410. package/src/commerce/offerEvidenceSchemas.ts +17 -0
  411. package/src/commerce/oms/omsContractBase.ts +92 -0
  412. package/src/commerce/oms/omsContractReadAuxSchemas.ts +130 -0
  413. package/src/commerce/oms/omsContractReadSchemas.ts +303 -0
  414. package/src/commerce/oms/omsContractRequests.ts +143 -0
  415. package/src/commerce/oms/omsContracts.ts +6 -0
  416. package/src/commerce/oms/omsControlPlane.ts +85 -0
  417. package/src/commerce/oms/omsFulfillmentContractSchemas.ts +113 -0
  418. package/src/commerce/oms/omsFulfillmentDebugSchemas.ts +38 -0
  419. package/src/commerce/oms/omsFulfillmentHealthSchemas.ts +46 -0
  420. package/src/commerce/oms/omsPorts.ts +165 -0
  421. package/src/commerce/oms/omsPrimitives.ts +3 -0
  422. package/src/commerce/oms/omsProviderEvidenceSchemas.ts +13 -0
  423. package/src/commerce/orderDraftErrors.ts +28 -0
  424. package/src/commerce/orderEmailEligibility.ts +131 -0
  425. package/src/commerce/orderEmailLines.ts +22 -0
  426. package/src/commerce/orderFeedbackContracts.ts +47 -0
  427. package/src/commerce/orderMoney.ts +207 -0
  428. package/src/commerce/orderReviewContracts.ts +124 -0
  429. package/src/commerce/orderReviewPorts.ts +94 -0
  430. package/src/commerce/outboxDispatchContracts.ts +30 -0
  431. package/src/commerce/outboxEventSchemas.ts +230 -0
  432. package/src/commerce/outboxOrderDraftEmailPorts.ts +241 -0
  433. package/src/commerce/paymentContinuation.ts +5 -0
  434. package/src/commerce/ports.ts +7 -0
  435. package/src/commerce/recoveryDestination.ts +23 -0
  436. package/src/commerce/runtimeErrors.ts +19 -0
  437. package/src/commerce/salesChannelEnvelope.ts +28 -0
  438. package/src/commerce/schemas.ts +104 -0
  439. package/src/commerce/server/checkoutCompensation.ts +49 -0
  440. package/src/commerce/server/checkoutConflictClassifiers.ts +53 -0
  441. package/src/commerce/server/checkoutExpiredRecoveryPolicy.ts +107 -0
  442. package/src/commerce/server/checkoutInvoiceBuyerSnapshot.ts +36 -0
  443. package/src/commerce/server/checkoutOfferPolicyPort.ts +60 -0
  444. package/src/commerce/server/checkoutPaymentContinuationCredential.ts +222 -0
  445. package/src/commerce/server/checkoutQuoteTypes.ts +9 -0
  446. package/src/commerce/server/checkoutRecoveryOrderPort.ts +40 -0
  447. package/src/commerce/server/checkoutRecoveryToken.ts +63 -0
  448. package/src/commerce/server/checkoutRefusalContinuation.ts +29 -0
  449. package/src/commerce/server/checkoutRuntimeTypes.ts +26 -0
  450. package/src/commerce/server/commerceCheckoutCommandExecution.ts +188 -0
  451. package/src/commerce/server/commerceCheckoutCompensation.ts +66 -0
  452. package/src/commerce/server/commerceCheckoutContinuationTerms.ts +87 -0
  453. package/src/commerce/server/commerceCheckoutCustomerDefaults.ts +24 -0
  454. package/src/commerce/server/commerceCheckoutFailureHandler.ts +144 -0
  455. package/src/commerce/server/commerceCheckoutHandler.ts +269 -0
  456. package/src/commerce/server/commerceCheckoutHandlerAdmission.ts +157 -0
  457. package/src/commerce/server/commerceCheckoutHandlerHelpers.ts +223 -0
  458. package/src/commerce/server/commerceCheckoutOrchestrationError.ts +15 -0
  459. package/src/commerce/server/commerceCheckoutPromotionPriceChange.ts +83 -0
  460. package/src/commerce/server/commerceCheckoutProviderPayment.ts +45 -0
  461. package/src/commerce/server/commerceCheckoutQuoteGuard.ts +172 -0
  462. package/src/commerce/server/commerceCheckoutResume.ts +132 -0
  463. package/src/commerce/server/commerceCheckoutResumeGuard.ts +195 -0
  464. package/src/commerce/server/commerceCheckoutSavedPaymentMethod.ts +85 -0
  465. package/src/commerce/server/commerceCheckoutStartRuntimeFailure.ts +59 -0
  466. package/src/commerce/server/commerceCheckoutTiming.ts +53 -0
  467. package/src/commerce/server/commerceDiagnostics.ts +37 -0
  468. package/src/commerce/server/commerceOmsCancelOrderHandler.ts +43 -0
  469. package/src/commerce/server/commerceOmsControlPlaneHandlers.ts +71 -0
  470. package/src/commerce/server/commerceOmsHandlers.ts +275 -0
  471. package/src/commerce/server/commerceOmsMarkRefundedHandler.ts +39 -0
  472. package/src/commerce/server/commerceOrderDraft.ts +131 -0
  473. package/src/commerce/server/commercePaidOrderOrchestration.ts +275 -0
  474. package/src/commerce/server/commerceProviderAttemptFailure.ts +257 -0
  475. package/src/commerce/server/commerceReturnsHandlers.ts +143 -0
  476. package/src/commerce/server/commerceRuntimePort.ts +75 -0
  477. package/src/commerce/server/commerceRuntimeService.ts +229 -0
  478. package/src/commerce/server/commerceRuntimeStartResponse.ts +76 -0
  479. package/src/commerce/server/commerceStarterOfferGuard.ts +200 -0
  480. package/src/commerce/server/configuratorIntentPersistence.ts +161 -0
  481. package/src/commerce/server/configuratorIntentPersistenceHandler.ts +54 -0
  482. package/src/commerce/server/emailRuntime.ts +30 -0
  483. package/src/commerce/server/handlerSupport.ts +22 -0
  484. package/src/commerce/server/index.ts +181 -0
  485. package/src/commerce/server/offerAvailability.ts +275 -0
  486. package/src/commerce/server/orderDraftRpcPayload.ts +39 -0
  487. package/src/commerce/server/orderFeedbackSubmit.ts +40 -0
  488. package/src/commerce/server/orderFeedbackTokenCheck.ts +28 -0
  489. package/src/commerce/server/orderReviewAdminHandlers.ts +43 -0
  490. package/src/commerce/server/orderReviewHandlers.ts +57 -0
  491. package/src/commerce/server/orderReviewLifecycle.ts +129 -0
  492. package/src/commerce/server/orderReviewMedia.ts +170 -0
  493. package/src/commerce/server/orderReviewRawUploadHandler.ts +300 -0
  494. package/src/commerce/server/outboxCheckoutExpiredEmailHandler.ts +86 -0
  495. package/src/commerce/server/outboxCheckoutRecoveryEmailHandler.ts +188 -0
  496. package/src/commerce/server/outboxDispatchRegistry.ts +269 -0
  497. package/src/commerce/server/outboxDispatchRegistryComposition.ts +31 -0
  498. package/src/commerce/server/outboxOrderDraftEmailHandler.ts +162 -0
  499. package/src/commerce/server/outboxOrderPaidEmailHandler.ts +147 -0
  500. package/src/commerce/server/outboxOrderPaidFulfillmentHandler.ts +4 -0
  501. package/src/commerce/server/outboxOrderPaidFulfillmentPorts.ts +3 -0
  502. package/src/commerce/server/outboxOrderRefundedEmailHandler.ts +58 -0
  503. package/src/commerce/server/outboxPaymentFailedEmailHandler.ts +99 -0
  504. package/src/commerce/server/outboxReturnEmailHandlers.ts +92 -0
  505. package/src/commerce/server/outboxShipmentDeliveredEmailHandler.ts +94 -0
  506. package/src/commerce/server/outboxShipmentDispatchedEmailHandler.ts +112 -0
  507. package/src/commerce/server/outboxShipmentExceptionEmailHandler.ts +73 -0
  508. package/src/commerce/server/referenceCheckoutHandler.ts +87 -0
  509. package/src/commerce/server/reservationSweepPort.ts +67 -0
  510. package/src/commerce/server/starterTermsPort.ts +22 -0
  511. package/src/commerce/server/supabaseCommerceReturnsPort.ts +81 -0
  512. package/src/composition/commerceContribution.ts +35 -0
  513. package/src/composition/index.ts +1 -0
  514. package/src/fulfillment/index.ts +1 -1
  515. package/src/fulfillment/paidHandoff.ts +2 -2
  516. package/src/inventory/bindings.ts +12 -4
  517. package/src/inventory/index.ts +1 -0
  518. package/src/inventory/managedStockAvailability.ts +23 -0
  519. package/src/inventory/postgresStockAvailability.ts +2 -21
  520. package/src/inventory/stockReadResponse.ts +25 -0
  521. package/src/pricing/browser/index.ts +6 -0
  522. package/src/subscriptions/contracts/renewal.ts +2 -1
  523. package/src/subscriptions/index.ts +3 -2
  524. package/src/subscriptions/renewalCycleFailureMechanism.ts +3 -1
@@ -0,0 +1,184 @@
1
+ import { composeOutboxHandlerDescriptors, assertOutboxRegistryDescriptors } from "./outboxDispatchRegistryComposition.js";
2
+ import { createOutboxOrderDraftEmailHandler, outboxOrderDraftEmailDescriptor } from "./outboxOrderDraftEmailHandler.js";
3
+ import { createOutboxCheckoutRecoveryEmailHandler, outboxCheckoutRecoveryEmailDescriptor } from "./outboxCheckoutRecoveryEmailHandler.js";
4
+ import { createOutboxOrderPaidEmailHandler, outboxOrderPaidEmailDescriptor, } from "./outboxOrderPaidEmailHandler.js";
5
+ import { createOutboxPaymentFailedEmailHandler, outboxPaymentFailedEmailDescriptor } from "./outboxPaymentFailedEmailHandler.js";
6
+ import { createOutboxCheckoutExpiredEmailHandler, outboxCheckoutExpiredEmailDescriptor } from "./outboxCheckoutExpiredEmailHandler.js";
7
+ import { createOutboxOrderRefundedEmailHandler, outboxOrderRefundedEmailDescriptor } from "./outboxOrderRefundedEmailHandler.js";
8
+ import { createOutboxShipmentDispatchedEmailHandler, outboxShipmentDispatchedEmailDescriptor } from "./outboxShipmentDispatchedEmailHandler.js";
9
+ import { createOutboxShipmentDeliveredEmailHandler, outboxShipmentDeliveredEmailDescriptor, } from "./outboxShipmentDeliveredEmailHandler.js";
10
+ import { createOutboxShipmentExceptionEmailHandler, outboxShipmentExceptionEmailDescriptor } from "./outboxShipmentExceptionEmailHandler.js";
11
+ import { createOutboxReturnApprovedEmailHandler, outboxReturnApprovedEmailDescriptor, createOutboxReturnRejectedEmailHandler, outboxReturnRejectedEmailDescriptor, } from "./outboxReturnEmailHandlers.js";
12
+ import { createOutboxOrderPaidFulfillmentHandler, outboxOrderPaidFulfillmentDescriptor, } from "./outboxOrderPaidFulfillmentHandler.js";
13
+ import { platformOwnsBuyerEmail, } from "../salesChannelEnvelope.js";
14
+ function readOrderUuid(payload) {
15
+ const value = payload.orderUuid;
16
+ return typeof value === "string" && value.length > 0 ? value : null;
17
+ }
18
+ /**
19
+ * Wraps ONE buyer-facing email handler so a channel that owns buyer
20
+ * communication does not also get ours.
21
+ *
22
+ * WHY THE WRAPPER IS AT THE HANDLER AND NOT AT THE TRIGGER. The checkout email
23
+ * reconciler (`commerce_reconcile_checkout_email_outbox`) back-fills a `commerce.order.paid.email`
24
+ * row for EVERY order that reads `paid` and has none, keyed only on the order
25
+ * id — it does not look at `source_kind`, and outboxDispatchRuntime runs it
26
+ * inline immediately before the dispatch worker in the same invocation. A
27
+ * trigger-level or emitter-level suppression would therefore be undone on the
28
+ * very next reconcile pass, silently, and the buyer would get the email anyway.
29
+ * The dispatcher is the last place that can still decide.
30
+ *
31
+ * Recorded as `processed` rather than `discard` so the event settles once and
32
+ * never retries. `skipped` is one of the DELIVERY_LIFECYCLE_METADATA_KEYS below,
33
+ * so the email-delivery lifecycle trigger reads the suppression as a skip with a
34
+ * reason instead of leaving a delivery hanging — the same shape the
35
+ * carrier-owned delivered notice already uses.
36
+ */
37
+ function suppressForChannel(handler, reader) {
38
+ if (!reader)
39
+ return handler;
40
+ return {
41
+ eventType: handler.eventType,
42
+ timeoutMs: handler.timeoutMs,
43
+ async handle(row, signal, execution) {
44
+ const orderUuid = readOrderUuid(row.payload);
45
+ // A payload with no usable order id is not a policy question. Hand it to
46
+ // the handler, whose own contract parse produces the right discard rather
47
+ // than this wrapper inventing a second failure mode for the same row.
48
+ if (orderUuid !== null) {
49
+ const policy = await reader.readOrderBuyerCommsPolicy(orderUuid);
50
+ if (!platformOwnsBuyerEmail(policy)) {
51
+ return { kind: "processed", detail: { skipped: "channel_owns_buyer_comms" } };
52
+ }
53
+ }
54
+ return handler.handle(row, signal, execution);
55
+ },
56
+ };
57
+ }
58
+ export function describeCoreOutboxHandlers(selection) {
59
+ return [
60
+ ...(selection.transactionalEmail ? [
61
+ outboxOrderDraftEmailDescriptor, outboxCheckoutRecoveryEmailDescriptor,
62
+ outboxOrderPaidEmailDescriptor, outboxPaymentFailedEmailDescriptor,
63
+ outboxCheckoutExpiredEmailDescriptor, outboxOrderRefundedEmailDescriptor,
64
+ outboxShipmentDispatchedEmailDescriptor, outboxShipmentDeliveredEmailDescriptor,
65
+ outboxShipmentExceptionEmailDescriptor, outboxReturnApprovedEmailDescriptor,
66
+ outboxReturnRejectedEmailDescriptor,
67
+ ] : []),
68
+ ...(selection.fulfillmentEnabled ? [outboxOrderPaidFulfillmentDescriptor] : []),
69
+ ];
70
+ }
71
+ export function createOutboxDispatchRegistry(deps) {
72
+ // Applied to the buyer-facing set below. The four email handlers it is NOT
73
+ // applied to are structurally unreachable for a channel order on the ingest
74
+ // path this repository ships, and each is asserted rather than assumed:
75
+ // - order-draft-created: emitted INSIDE `commerce_create_order_draft`.
76
+ // `commerce_create_channel_order` writes the order header directly and
77
+ // emits `channel.order.ingested`, so no draft event ever exists.
78
+ // - checkout-recovery: minted from an expired-checkout recovery token, which
79
+ // only the checkout-expiry path can create.
80
+ // - checkout-expired and payment-failed: both key off a one-time order
81
+ // reaching status `expired`/`failed`, and the ONLY writer of those statuses
82
+ // for a one-time order is `commerce_payment_apply_result`. The ingest saga
83
+ // calls `applySucceeded` and nothing else — the marketplace collected the
84
+ // money before the order existed here, so there is no decline or session to
85
+ // expire. Nothing sweeps a stale `draft` order to `expired` either.
86
+ // This is an argument about the CURRENT ingest path. A later wave that gives a
87
+ // channel order a decline or expiry rail must revisit this list, not assume it.
88
+ //
89
+ // `commerce.order.canceled` is absent from this enumeration because its email
90
+ // handler (outboxOrderCanceledEmailHandler.ts) is registered by NOTHING — the
91
+ // only claimant of that event type is the accounting reversal handler, which
92
+ // arrives through `extraHandlers` and must keep running for a channel order.
93
+ // Wrapping a handler this registry does not compose would be theatre; if that
94
+ // email is ever wired up, it belongs in the wrapped set.
95
+ const suppress = (handler) => suppressForChannel(handler, deps.transactionalEmail?.buyerCommsPolicyReader);
96
+ const handlers = [
97
+ ...(deps.transactionalEmail
98
+ ? [
99
+ createOutboxOrderDraftEmailHandler({
100
+ runtime: deps.transactionalEmail.runtime,
101
+ emailPort: deps.transactionalEmail.emailPort,
102
+ recipientPort: deps.transactionalEmail.recipientPort,
103
+ lifecyclePort: deps.transactionalEmail.lifecyclePort,
104
+ }),
105
+ createOutboxCheckoutRecoveryEmailHandler({
106
+ runtime: deps.transactionalEmail.runtime,
107
+ emailPort: deps.transactionalEmail.emailPort,
108
+ recipientPort: deps.transactionalEmail.recipientPort,
109
+ lifecyclePort: deps.transactionalEmail.lifecyclePort,
110
+ }),
111
+ suppress(createOutboxOrderPaidEmailHandler({
112
+ runtime: deps.transactionalEmail.runtime,
113
+ emailPort: deps.transactionalEmail.emailPort,
114
+ recipientPort: deps.transactionalEmail.recipientPort,
115
+ linesPort: deps.transactionalEmail.orderPaidLinesPort,
116
+ describeParcel: deps.transactionalEmail.orderPaidParcelNote,
117
+ })),
118
+ createOutboxPaymentFailedEmailHandler({
119
+ runtime: deps.transactionalEmail.runtime,
120
+ emailPort: deps.transactionalEmail.emailPort,
121
+ recipientPort: deps.transactionalEmail.recipientPort,
122
+ lifecyclePort: deps.transactionalEmail.lifecyclePort,
123
+ }),
124
+ createOutboxCheckoutExpiredEmailHandler({
125
+ runtime: deps.transactionalEmail.runtime,
126
+ emailPort: deps.transactionalEmail.emailPort,
127
+ recipientPort: deps.transactionalEmail.recipientPort,
128
+ lifecyclePort: deps.transactionalEmail.lifecyclePort,
129
+ }),
130
+ suppress(createOutboxOrderRefundedEmailHandler({
131
+ runtime: deps.transactionalEmail.runtime,
132
+ emailPort: deps.transactionalEmail.emailPort,
133
+ recipientPort: deps.transactionalEmail.recipientPort,
134
+ })),
135
+ suppress(createOutboxShipmentDispatchedEmailHandler({
136
+ runtime: deps.transactionalEmail.runtime,
137
+ emailPort: deps.transactionalEmail.emailPort,
138
+ recipientPort: deps.transactionalEmail.recipientPort,
139
+ })),
140
+ suppress(createOutboxShipmentDeliveredEmailHandler({
141
+ runtime: deps.transactionalEmail.runtime,
142
+ emailPort: deps.transactionalEmail.emailPort,
143
+ recipientPort: deps.transactionalEmail.recipientPort,
144
+ providerKindReader: deps.transactionalEmail.deliveredProviderKindReader,
145
+ })),
146
+ suppress(createOutboxShipmentExceptionEmailHandler({
147
+ runtime: deps.transactionalEmail.runtime,
148
+ emailPort: deps.transactionalEmail.emailPort,
149
+ recipientPort: deps.transactionalEmail.recipientPort,
150
+ })),
151
+ suppress(createOutboxReturnApprovedEmailHandler({
152
+ runtime: deps.transactionalEmail.runtime,
153
+ emailPort: deps.transactionalEmail.emailPort,
154
+ recipientPort: deps.transactionalEmail.recipientPort,
155
+ })),
156
+ suppress(createOutboxReturnRejectedEmailHandler({
157
+ runtime: deps.transactionalEmail.runtime,
158
+ emailPort: deps.transactionalEmail.emailPort,
159
+ recipientPort: deps.transactionalEmail.recipientPort,
160
+ })),
161
+ ]
162
+ : []),
163
+ ...(deps.fulfillmentEnabled && deps.fulfillmentPort
164
+ ? [
165
+ createOutboxOrderPaidFulfillmentHandler({
166
+ fulfillmentPort: deps.fulfillmentPort,
167
+ riskPort: deps.riskPort,
168
+ isRiskEnabled: () => deps.riskEnabled === true,
169
+ }),
170
+ ]
171
+ : []),
172
+ ...(deps.extraHandlers ?? []),
173
+ ];
174
+ const registry = deps.uniqueRegistry(handlers);
175
+ const expected = deps.expectedDescriptors?.() ?? composeOutboxHandlerDescriptors([
176
+ ...describeCoreOutboxHandlers({
177
+ transactionalEmail: Boolean(deps.transactionalEmail),
178
+ fulfillmentEnabled: deps.fulfillmentEnabled && Boolean(deps.fulfillmentPort),
179
+ }),
180
+ ...(deps.extraHandlers ?? []).map(({ eventType, timeoutMs }) => ({ eventType, timeoutMs })),
181
+ ]);
182
+ assertOutboxRegistryDescriptors(registry, expected);
183
+ return registry;
184
+ }
@@ -0,0 +1,6 @@
1
+ import type { OutboxHandlerDescriptor } from "@openlup/core/outbox";
2
+ import type { OutboxHandlerRegistry } from "../outboxDispatchContracts.js";
3
+ /** Preserve native registration order and the timeout sum of same-event handlers. */
4
+ export declare function composeOutboxHandlerDescriptors(handlers: readonly OutboxHandlerDescriptor[]): OutboxHandlerDescriptor[];
5
+ /** Refuse a different claim surface before a worker can call claimBatch. */
6
+ export declare function assertOutboxRegistryDescriptors(registry: OutboxHandlerRegistry, expected: readonly OutboxHandlerDescriptor[]): void;
@@ -0,0 +1,23 @@
1
+ /** Preserve native registration order and the timeout sum of same-event handlers. */
2
+ export function composeOutboxHandlerDescriptors(handlers) {
3
+ const descriptors = new Map();
4
+ for (const handler of handlers) {
5
+ const existing = descriptors.get(handler.eventType);
6
+ descriptors.set(handler.eventType, {
7
+ eventType: handler.eventType,
8
+ timeoutMs: (existing?.timeoutMs ?? 0) + handler.timeoutMs,
9
+ });
10
+ }
11
+ return [...descriptors.values()];
12
+ }
13
+ /** Refuse a different claim surface before a worker can call claimBatch. */
14
+ export function assertOutboxRegistryDescriptors(registry, expected) {
15
+ const actual = [...registry.entries()];
16
+ if (actual.length !== expected.length || actual.some(([key, handler], index) => {
17
+ const descriptor = expected[index];
18
+ return key !== descriptor.eventType || handler.eventType !== key
19
+ || handler.timeoutMs !== descriptor.timeoutMs
20
+ || !Number.isFinite(handler.timeoutMs) || handler.timeoutMs <= 0;
21
+ }))
22
+ throw new Error("outbox_registry_descriptor_mismatch");
23
+ }
@@ -0,0 +1,14 @@
1
+ import type { CommerceEmailRuntime } from "./emailRuntime.js";
2
+ import type { OutboxHandler } from "../outboxDispatchContracts.js";
3
+ import { OUTBOX_ORDER_CONFIRMATION_TEMPLATE_SLUG, type OrderPaymentLifecyclePort, type OrderRecipientPort, type TransactionalEmailPort } from "../outboxOrderDraftEmailPorts.js";
4
+ export { OUTBOX_ORDER_CONFIRMATION_TEMPLATE_SLUG };
5
+ export declare const outboxOrderDraftEmailDescriptor: Readonly<{
6
+ eventType: "commerce.order_draft.created";
7
+ timeoutMs: 10000;
8
+ }>;
9
+ export declare function createOutboxOrderDraftEmailHandler<Locale extends string>(deps: {
10
+ runtime: Pick<CommerceEmailRuntime<Locale>, "formatMoney" | "genericItemLabel" | "mapSendOutcome" | "parseOutboxPayload" | "resolveLocale">;
11
+ emailPort: TransactionalEmailPort<Locale>;
12
+ recipientPort: OrderRecipientPort;
13
+ lifecyclePort: OrderPaymentLifecyclePort;
14
+ }): OutboxHandler;
@@ -0,0 +1,130 @@
1
+ import { z } from "zod";
2
+ import { COMMERCE_ORDER_DRAFT_CREATED_EVENT_TYPE } from "../outboxEventSchemas.js";
3
+ import { OUTBOX_ORDER_CONFIRMATION_TEMPLATE_SLUG, } from "../outboxOrderDraftEmailPorts.js";
4
+ import { buildItems } from "../orderEmailLines.js";
5
+ import { shouldSkipOrderDraftConfirmation } from "../orderEmailEligibility.js";
6
+ export { OUTBOX_ORDER_CONFIRMATION_TEMPLATE_SLUG };
7
+ const HANDLER_TIMEOUT_MS = 10_000;
8
+ export const outboxOrderDraftEmailDescriptor = Object.freeze({
9
+ eventType: COMMERCE_ORDER_DRAFT_CREATED_EVENT_TYPE, timeoutMs: HANDLER_TIMEOUT_MS,
10
+ });
11
+ // Frozen minimal parse (challenge R-m5): validate ONLY the fields this handler
12
+ // consumes, with schemas owned HERE — never the live quote/order-draft zod
13
+ // schemas. A producer-side schema deploy must not retro-DLQ in-flight events.
14
+ // Everything except orderUuid/orderId is optional-tolerant: malformed lines or
15
+ // totals degrade the email content, they never fail the event.
16
+ const payloadSubsetSchema = z
17
+ .object({
18
+ orderUuid: z.guid(),
19
+ orderId: z.string().min(1),
20
+ orderDraftSnapshot: z.unknown().optional(),
21
+ })
22
+ .passthrough();
23
+ const moneySubsetSchema = z
24
+ .object({
25
+ amountMinor: z.number().int().nonnegative(),
26
+ currency: z.string().trim().min(1),
27
+ })
28
+ .passthrough();
29
+ const lineSubsetSchema = z
30
+ .object({
31
+ quantity: z.number().int().positive(),
32
+ productSlug: z.string().trim().min(1).optional(),
33
+ sku: z.string().trim().min(1).optional(),
34
+ lineSubtotalGross: moneySubsetSchema.optional(),
35
+ })
36
+ .passthrough();
37
+ const snapshotSubsetSchema = z
38
+ .object({
39
+ lines: z.array(z.unknown()).optional(),
40
+ totals: z
41
+ .object({
42
+ subtotalGross: z.unknown().optional(),
43
+ discountTotalGross: z.unknown().optional(),
44
+ totalGross: z.unknown().optional(),
45
+ })
46
+ .passthrough()
47
+ .optional(),
48
+ })
49
+ .passthrough();
50
+ function extractLines(snapshot) {
51
+ const parsed = snapshotSubsetSchema.safeParse(snapshot);
52
+ if (!parsed.success || parsed.data.lines === undefined)
53
+ return [];
54
+ const lines = [];
55
+ for (const candidate of parsed.data.lines) {
56
+ const line = lineSubsetSchema.safeParse(candidate);
57
+ if (!line.success)
58
+ continue;
59
+ if (line.data.productSlug === undefined && line.data.sku === undefined)
60
+ continue;
61
+ lines.push({
62
+ label: null,
63
+ quantity: line.data.quantity,
64
+ lineSubtotalMinor: line.data.lineSubtotalGross?.amountMinor ?? null,
65
+ currency: line.data.lineSubtotalGross?.currency ?? null,
66
+ });
67
+ }
68
+ return lines;
69
+ }
70
+ function buildTotals(snapshot, runtime) {
71
+ const parsed = snapshotSubsetSchema.safeParse(snapshot);
72
+ if (!parsed.success || parsed.data.totals === undefined)
73
+ return null;
74
+ const total = moneySubsetSchema.safeParse(parsed.data.totals.totalGross);
75
+ if (!total.success)
76
+ return null;
77
+ const subtotal = moneySubsetSchema.safeParse(parsed.data.totals.subtotalGross);
78
+ const discount = moneySubsetSchema.safeParse(parsed.data.totals.discountTotalGross);
79
+ const currency = total.data.currency;
80
+ return {
81
+ // Omit the subtotal row when it cannot be parsed — do NOT fall back to the
82
+ // grand total, which would render "Subtotal = Total" alongside a separate
83
+ // discount line that no longer reconciles.
84
+ subtotalLabel: subtotal.success
85
+ ? runtime.formatMoney(subtotal.data.amountMinor, subtotal.data.currency)
86
+ : null,
87
+ discountLabel: discount.success && discount.data.amountMinor > 0
88
+ ? `-${runtime.formatMoney(discount.data.amountMinor, discount.data.currency)}`
89
+ : null,
90
+ totalLabel: runtime.formatMoney(total.data.amountMinor, currency),
91
+ };
92
+ }
93
+ export function createOutboxOrderDraftEmailHandler(deps) {
94
+ return {
95
+ ...outboxOrderDraftEmailDescriptor,
96
+ async handle(row, signal) {
97
+ const parsed = deps.runtime.parseOutboxPayload(payloadSubsetSchema, row.payload);
98
+ if (parsed.ok === false) {
99
+ return parsed.outcome;
100
+ }
101
+ const lifecycle = await deps.lifecyclePort.read(parsed.data.orderUuid, signal);
102
+ const skipReason = shouldSkipOrderDraftConfirmation(lifecycle);
103
+ if (skipReason) {
104
+ return { kind: "processed", detail: { skipped: skipReason } };
105
+ }
106
+ const recipient = await deps.recipientPort.resolve(parsed.data.orderUuid, signal);
107
+ if (recipient === null) {
108
+ return { kind: "processed", detail: { skipped: "recipient_unresolved" } };
109
+ }
110
+ const alreadySent = await deps.emailPort.findExistingSend(OUTBOX_ORDER_CONFIRMATION_TEMPLATE_SLUG, row.id);
111
+ if (alreadySent) {
112
+ return { kind: "processed", detail: { dedupe: "email_already_sent" } };
113
+ }
114
+ const lines = extractLines(parsed.data.orderDraftSnapshot);
115
+ const locale = deps.runtime.resolveLocale(recipient.country ?? null);
116
+ const outcome = await deps.emailPort.sendOrderConfirmation({
117
+ to: recipient.email,
118
+ firstName: recipient.firstName,
119
+ contextName: recipient.contextName ?? null,
120
+ orderId: parsed.data.orderId,
121
+ outboxEventId: row.id,
122
+ items: buildItems(lines, locale, deps.runtime),
123
+ totals: buildTotals(parsed.data.orderDraftSnapshot, deps.runtime),
124
+ locale,
125
+ signal,
126
+ });
127
+ return deps.runtime.mapSendOutcome(outcome);
128
+ },
129
+ };
130
+ }
@@ -0,0 +1,21 @@
1
+ import type { CommerceEmailRuntime } from "./emailRuntime.js";
2
+ import type { OutboxHandler } from "../outboxDispatchContracts.js";
3
+ import { OUTBOX_ORDER_PAID_TEMPLATE_SLUG, type OrderPaidLinesPort, type OrderRecipientPort, type TransactionalEmailPort } from "../outboxOrderDraftEmailPorts.js";
4
+ export { OUTBOX_ORDER_PAID_TEMPLATE_SLUG };
5
+ export declare const outboxOrderPaidEmailDescriptor: Readonly<{
6
+ eventType: "commerce.order.paid.email";
7
+ timeoutMs: 10000;
8
+ }>;
9
+ /**
10
+ * An adopter's note about the paid order's parcel, already localized, or null
11
+ * for none. Best-effort and inside this handler's timeout: a failure is logged
12
+ * and the receipt is sent without the note.
13
+ */
14
+ export type OrderPaidParcelNoteReader<Locale extends string = string> = (orderUuid: string, locale: Locale, signal: AbortSignal) => Promise<string | null>;
15
+ export declare function createOutboxOrderPaidEmailHandler<Locale extends string>(deps: {
16
+ runtime: Pick<CommerceEmailRuntime<Locale>, "formatMoney" | "genericItemLabel" | "mapSendOutcome" | "parseOutboxPayload" | "presentPaidOrder" | "resolveLocale">;
17
+ emailPort: TransactionalEmailPort<Locale>;
18
+ recipientPort: OrderRecipientPort;
19
+ linesPort: OrderPaidLinesPort;
20
+ describeParcel?: OrderPaidParcelNoteReader<Locale>;
21
+ }): OutboxHandler;
@@ -0,0 +1,93 @@
1
+ import { z } from "zod";
2
+ import { COMMERCE_ORDER_PAID_EMAIL_EVENT_TYPE } from "../outboxEventSchemas.js";
3
+ import { OUTBOX_ORDER_PAID_TEMPLATE_SLUG, } from "../outboxOrderDraftEmailPorts.js";
4
+ import { buildItems } from "../orderEmailLines.js";
5
+ export { OUTBOX_ORDER_PAID_TEMPLATE_SLUG };
6
+ const HANDLER_TIMEOUT_MS = 10_000;
7
+ export const outboxOrderPaidEmailDescriptor = Object.freeze({
8
+ eventType: COMMERCE_ORDER_PAID_EMAIL_EVENT_TYPE, timeoutMs: HANDLER_TIMEOUT_MS,
9
+ });
10
+ // Frozen minimal parse (mirror the order-draft handler): validate ONLY what this
11
+ // handler consumes; a producer schema change must never retro-DLQ in-flight rows.
12
+ const payloadSubsetSchema = z
13
+ .object({
14
+ orderUuid: z.guid(),
15
+ orderId: z.string().min(1),
16
+ mode: z.string().min(1).optional(),
17
+ })
18
+ .passthrough();
19
+ function totalsFrom(data, runtime) {
20
+ return {
21
+ subtotalLabel: runtime.formatMoney(data.subtotalMinor, data.currency),
22
+ discountLabel: data.discountMinor > 0 ? `−${runtime.formatMoney(data.discountMinor, data.currency)}` : null,
23
+ totalLabel: runtime.formatMoney(data.totalMinor, data.currency),
24
+ };
25
+ }
26
+ export function createOutboxOrderPaidEmailHandler(deps) {
27
+ return {
28
+ ...outboxOrderPaidEmailDescriptor,
29
+ async handle(row, signal) {
30
+ const parsed = deps.runtime.parseOutboxPayload(payloadSubsetSchema, row.payload);
31
+ if (parsed.ok === false) {
32
+ return parsed.outcome;
33
+ }
34
+ // Dedupe FIRST (cheap, recipient-independent): an already-sent event must not
35
+ // burn the recipient + lines reads (4 queries) on every reprocess/retry/preview
36
+ // drain — those passes were pure waste on the dupe path.
37
+ const alreadySent = await deps.emailPort.findExistingSend(OUTBOX_ORDER_PAID_TEMPLATE_SLUG, row.id);
38
+ if (alreadySent) {
39
+ return { kind: "processed", detail: { dedupe: "email_already_sent" } };
40
+ }
41
+ const recipient = await deps.recipientPort.resolve(parsed.data.orderUuid, signal);
42
+ if (recipient === null) {
43
+ return { kind: "processed", detail: { skipped: "recipient_unresolved" } };
44
+ }
45
+ // Items + totals from the DB. A genuine read error throws → worker retries.
46
+ // A missing order row means the paid order is not yet readable (replication
47
+ // lag): retry rather than send a contentless "receipt" with no items/totals.
48
+ const data = await deps.linesPort.read(parsed.data.orderUuid, signal);
49
+ if (data === null) {
50
+ return { kind: "retry", reason: "order_paid_data_unavailable" };
51
+ }
52
+ const presentation = deps.runtime.presentPaidOrder(data);
53
+ const rawLines = (data.lines ?? []).map((line) => ({
54
+ label: line.label,
55
+ quantity: line.quantity,
56
+ lineSubtotalMinor: presentation ? null : line.lineTotalMinor,
57
+ currency: data.currency,
58
+ }));
59
+ const locale = deps.runtime.resolveLocale(recipient.country ?? null);
60
+ const parcelNote = await readParcelNote(deps.describeParcel, parsed.data.orderUuid, locale, signal, row.id);
61
+ const outcome = await deps.emailPort.sendOrderPaidConfirmation({
62
+ to: recipient.email,
63
+ firstName: recipient.firstName,
64
+ contextName: recipient.contextName ?? null,
65
+ orderId: parsed.data.orderId,
66
+ mode: parsed.data.mode ?? "one_time",
67
+ outboxEventId: row.id,
68
+ items: buildItems(rawLines, locale, deps.runtime),
69
+ totals: presentation ?? totalsFrom(data, deps.runtime),
70
+ ...(parcelNote ? { parcelNote } : {}),
71
+ locale,
72
+ signal,
73
+ });
74
+ return deps.runtime.mapSendOutcome(outcome);
75
+ },
76
+ };
77
+ }
78
+ /**
79
+ * Asks the composed reader, if any, for the receipt's parcel note. A missing
80
+ * reader, an empty answer or a failure all mean no note: a failure is logged
81
+ * with the event id only, and the receipt is sent without the note.
82
+ */
83
+ async function readParcelNote(describeParcel, orderUuid, locale, signal, eventId) {
84
+ if (!describeParcel)
85
+ return null;
86
+ try {
87
+ return (await describeParcel(orderUuid, locale, signal)) || null;
88
+ }
89
+ catch {
90
+ console.warn("[outbox-dispatch] order_paid_parcel_note_unavailable", eventId);
91
+ return null;
92
+ }
93
+ }
@@ -0,0 +1,3 @@
1
+ import { createOutboxOrderPaidFulfillmentHandler } from "../../fulfillment/index.js";
2
+ export { createOutboxOrderPaidFulfillmentHandler, outboxOrderPaidFulfillmentDescriptor } from "../../fulfillment/index.js";
3
+ export type OrderPaidRiskAssessmentPort = NonNullable<Parameters<typeof createOutboxOrderPaidFulfillmentHandler>[0]["riskPort"]>;
@@ -0,0 +1 @@
1
+ export { createOutboxOrderPaidFulfillmentHandler, outboxOrderPaidFulfillmentDescriptor } from "../../fulfillment/index.js";
@@ -0,0 +1,3 @@
1
+ import type { createOutboxOrderPaidFulfillmentHandler } from "../../fulfillment/index.js";
2
+ export type OrderPaidFulfillmentPort = Parameters<typeof createOutboxOrderPaidFulfillmentHandler>[0]["fulfillmentPort"];
3
+ export type OrderPaidFulfillmentResult = Awaited<ReturnType<OrderPaidFulfillmentPort["ensureFulfilledFromPaidOrder"]>>;
@@ -0,0 +1,13 @@
1
+ import type { CommerceEmailRuntime } from "./emailRuntime.js";
2
+ import type { OutboxHandler } from "../outboxDispatchContracts.js";
3
+ import { OUTBOX_ORDER_REFUNDED_TEMPLATE_SLUG, type OrderRecipientPort, type TransactionalEmailPort } from "../outboxOrderDraftEmailPorts.js";
4
+ export { OUTBOX_ORDER_REFUNDED_TEMPLATE_SLUG };
5
+ export declare const outboxOrderRefundedEmailDescriptor: Readonly<{
6
+ eventType: "commerce.order.refunded";
7
+ timeoutMs: 10000;
8
+ }>;
9
+ export declare function createOutboxOrderRefundedEmailHandler<Locale extends string>(deps: {
10
+ runtime: Pick<CommerceEmailRuntime<Locale>, "createTransactionalEmailHandler" | "formatMoney" | "resolveLocale">;
11
+ emailPort: TransactionalEmailPort<Locale>;
12
+ recipientPort: OrderRecipientPort;
13
+ }): OutboxHandler;
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ import { COMMERCE_ORDER_REFUNDED_EVENT_TYPE } from "../outboxEventSchemas.js";
3
+ import { OUTBOX_ORDER_REFUNDED_TEMPLATE_SLUG, } from "../outboxOrderDraftEmailPorts.js";
4
+ export { OUTBOX_ORDER_REFUNDED_TEMPLATE_SLUG };
5
+ const HANDLER_TIMEOUT_MS = 10_000;
6
+ export const outboxOrderRefundedEmailDescriptor = Object.freeze({
7
+ eventType: COMMERCE_ORDER_REFUNDED_EVENT_TYPE, timeoutMs: HANDLER_TIMEOUT_MS,
8
+ });
9
+ const payloadSubsetSchema = z
10
+ .object({
11
+ orderUuid: z.guid(),
12
+ orderId: z.string().min(1),
13
+ refundCents: z.number().int().nonnegative().optional(),
14
+ refundEvidenceVersion: z.string().optional(),
15
+ currency: z.string().trim().min(1).optional(),
16
+ })
17
+ .passthrough();
18
+ export function createOutboxOrderRefundedEmailHandler(deps) {
19
+ return deps.runtime.createTransactionalEmailHandler({
20
+ ...outboxOrderRefundedEmailDescriptor,
21
+ templateSlug: OUTBOX_ORDER_REFUNDED_TEMPLATE_SLUG,
22
+ schema: payloadSubsetSchema,
23
+ resolveKey: (payload) => payload.orderUuid,
24
+ recipientPort: deps.recipientPort,
25
+ findExistingSend: (slug, id) => deps.emailPort.findExistingSend(slug, id),
26
+ send: ({ payload, recipient, row, signal }) => {
27
+ const amountCents = payload.refundEvidenceVersion === "provider-refund.v2" ? payload.refundCents : undefined;
28
+ const amountLabel = amountCents !== undefined && payload.currency !== undefined
29
+ ? deps.runtime.formatMoney(amountCents, payload.currency)
30
+ : null;
31
+ return deps.emailPort.sendOrderRefundedNotice({
32
+ to: recipient.email,
33
+ firstName: recipient.firstName,
34
+ orderId: payload.orderId,
35
+ amountLabel,
36
+ outboxEventId: row.id,
37
+ locale: deps.runtime.resolveLocale(recipient.country ?? null),
38
+ signal,
39
+ });
40
+ },
41
+ });
42
+ }
@@ -0,0 +1,14 @@
1
+ import type { CommerceEmailRuntime } from "./emailRuntime.js";
2
+ import type { OutboxHandler } from "../outboxDispatchContracts.js";
3
+ import { OUTBOX_PAYMENT_FAILED_TEMPLATE_SLUG, type OrderPaymentLifecyclePort, type OrderRecipientPort, type TransactionalEmailPort } from "../outboxOrderDraftEmailPorts.js";
4
+ export { OUTBOX_PAYMENT_FAILED_TEMPLATE_SLUG };
5
+ export declare const outboxPaymentFailedEmailDescriptor: Readonly<{
6
+ eventType: "commerce.payment.failed";
7
+ timeoutMs: 10000;
8
+ }>;
9
+ export declare function createOutboxPaymentFailedEmailHandler<Locale extends string>(deps: {
10
+ runtime: Pick<CommerceEmailRuntime<Locale>, "formatMoney" | "mapSendOutcome" | "parseOutboxPayload" | "resolveLocale">;
11
+ emailPort: TransactionalEmailPort<Locale>;
12
+ recipientPort: OrderRecipientPort;
13
+ lifecyclePort: OrderPaymentLifecyclePort;
14
+ }): OutboxHandler;
@@ -0,0 +1,65 @@
1
+ import { z } from "zod";
2
+ import { COMMERCE_PAYMENT_FAILED_EVENT_TYPE } from "../outboxEventSchemas.js";
3
+ import { OUTBOX_PAYMENT_FAILED_TEMPLATE_SLUG, } from "../outboxOrderDraftEmailPorts.js";
4
+ import { shouldSkipPaymentFailedNotice } from "../orderEmailEligibility.js";
5
+ export { OUTBOX_PAYMENT_FAILED_TEMPLATE_SLUG };
6
+ const HANDLER_TIMEOUT_MS = 10_000;
7
+ export const outboxPaymentFailedEmailDescriptor = Object.freeze({
8
+ eventType: COMMERCE_PAYMENT_FAILED_EVENT_TYPE, timeoutMs: HANDLER_TIMEOUT_MS,
9
+ });
10
+ // Frozen minimal parse: only orderUuid/orderId are required; the amount fields
11
+ // degrade the copy (no amount line) but never fail the event.
12
+ const payloadSubsetSchema = z
13
+ .object({
14
+ orderUuid: z.guid(),
15
+ orderId: z.string().min(1),
16
+ recoveryToken: z.string().trim().min(1),
17
+ mode: z.string().optional(),
18
+ totalCents: z.number().int().nonnegative().optional(),
19
+ currency: z.string().trim().min(1).optional(),
20
+ })
21
+ .passthrough();
22
+ export function createOutboxPaymentFailedEmailHandler(deps) {
23
+ return {
24
+ ...outboxPaymentFailedEmailDescriptor,
25
+ async handle(row, signal, execution) {
26
+ const parsed = deps.runtime.parseOutboxPayload(payloadSubsetSchema, row.payload);
27
+ if (parsed.ok === false) {
28
+ return parsed.outcome;
29
+ }
30
+ execution?.setPhase("lifecycle");
31
+ const lifecycle = await deps.lifecyclePort.read(parsed.data.orderUuid, signal);
32
+ const skipReason = shouldSkipPaymentFailedNotice(lifecycle);
33
+ if (skipReason) {
34
+ return { kind: "processed", detail: { skipped: skipReason } };
35
+ }
36
+ execution?.setPhase("recipient");
37
+ const recipient = await deps.recipientPort.resolve(parsed.data.orderUuid, signal);
38
+ if (recipient === null) {
39
+ return { kind: "processed", detail: { skipped: "recipient_unresolved" } };
40
+ }
41
+ execution?.setPhase("dedupe");
42
+ const alreadySent = await deps.emailPort.findExistingSend(OUTBOX_PAYMENT_FAILED_TEMPLATE_SLUG, row.id);
43
+ if (alreadySent) {
44
+ return { kind: "processed", detail: { dedupe: "email_already_sent" } };
45
+ }
46
+ const payload = parsed.data;
47
+ const amountLabel = payload.totalCents !== undefined && payload.currency !== undefined
48
+ ? deps.runtime.formatMoney(payload.totalCents, payload.currency)
49
+ : null;
50
+ execution?.setPhase("email_send");
51
+ const outcome = await deps.emailPort.sendPaymentFailedNotice({
52
+ to: recipient.email,
53
+ firstName: recipient.firstName,
54
+ orderId: payload.orderId,
55
+ amountLabel,
56
+ recoveryToken: payload.recoveryToken,
57
+ mode: payload.mode ?? "one_time",
58
+ outboxEventId: row.id,
59
+ locale: deps.runtime.resolveLocale(recipient.country ?? null),
60
+ signal,
61
+ });
62
+ return deps.runtime.mapSendOutcome(outcome);
63
+ },
64
+ };
65
+ }