@openlup/platform 0.16.0 → 0.18.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 (773) hide show
  1. package/CHANGELOG.md +180 -0
  2. package/README.md +564 -6
  3. package/dist/catalog/activeSkuSelection.d.ts +2 -0
  4. package/dist/catalog/activeSkuSelection.js +20 -0
  5. package/dist/catalog/adminBindings.d.ts +72 -0
  6. package/dist/catalog/adminBindings.js +1 -0
  7. package/dist/catalog/adminBundleHandler.d.ts +26 -0
  8. package/dist/catalog/adminBundleHandler.js +111 -0
  9. package/dist/catalog/adminBundleReadHandler.d.ts +20 -0
  10. package/dist/catalog/adminBundleReadHandler.js +185 -0
  11. package/dist/catalog/adminBundleWritePort.d.ts +85 -0
  12. package/dist/catalog/adminBundleWritePort.js +1 -0
  13. package/dist/catalog/bundleAvailability.d.ts +63 -0
  14. package/dist/catalog/bundleAvailability.js +78 -0
  15. package/dist/catalog/bundleAvailabilityService.d.ts +65 -0
  16. package/dist/catalog/bundleAvailabilityService.js +89 -0
  17. package/dist/catalog/bundleBindings.d.ts +33 -0
  18. package/dist/catalog/bundleBindings.js +1 -0
  19. package/dist/catalog/bundleCatalogQueries.d.ts +28 -0
  20. package/dist/catalog/bundleCatalogQueries.js +84 -0
  21. package/dist/catalog/bundleCatalogReadPort.d.ts +166 -0
  22. package/dist/catalog/bundleCatalogReadPort.js +36 -0
  23. package/dist/catalog/bundleCatalogStore.d.ts +3 -0
  24. package/dist/catalog/bundleCatalogStore.js +152 -0
  25. package/dist/catalog/bundleRuleCodes.d.ts +41 -0
  26. package/dist/catalog/bundleRuleCodes.js +110 -0
  27. package/dist/catalog/bundleRules.d.ts +69 -0
  28. package/dist/catalog/bundleRules.js +102 -0
  29. package/dist/catalog/catalogDraftStore.d.ts +4 -0
  30. package/dist/catalog/catalogDraftStore.js +63 -0
  31. package/dist/catalog/catalogSkuEnvelope.d.ts +7 -0
  32. package/dist/catalog/catalogSkuEnvelope.js +142 -0
  33. package/dist/catalog/catalogSkuEnvelopeMapper.d.ts +38 -0
  34. package/dist/catalog/catalogSkuEnvelopeMapper.js +88 -0
  35. package/dist/catalog/contracts/bundleAdmin.d.ts +143 -0
  36. package/dist/catalog/contracts/bundleAdmin.js +1 -0
  37. package/dist/catalog/contracts/bundleAvailability.d.ts +61 -0
  38. package/dist/catalog/contracts/bundleAvailability.js +1 -0
  39. package/dist/catalog/contracts/bundleRead.d.ts +223 -0
  40. package/dist/catalog/contracts/bundleRead.js +1 -0
  41. package/dist/catalog/contracts/draft.d.ts +79 -0
  42. package/dist/catalog/contracts/draft.js +47 -0
  43. package/dist/catalog/contracts/foundation.d.ts +78 -0
  44. package/dist/catalog/contracts/foundation.js +53 -0
  45. package/dist/catalog/contracts/index.d.ts +14 -0
  46. package/dist/catalog/contracts/index.js +6 -0
  47. package/dist/catalog/contracts/lifecycle.d.ts +77 -0
  48. package/dist/catalog/contracts/lifecycle.js +1 -0
  49. package/dist/catalog/contracts/productMediaContracts.d.ts +77 -0
  50. package/dist/catalog/contracts/productMediaContracts.js +149 -0
  51. package/dist/catalog/contracts/productTypes.d.ts +54 -0
  52. package/dist/catalog/contracts/productTypes.js +16 -0
  53. package/dist/catalog/contracts/resolveProductMedia.d.ts +3 -0
  54. package/dist/catalog/contracts/resolveProductMedia.js +78 -0
  55. package/dist/catalog/contracts/sellable.d.ts +23 -0
  56. package/dist/catalog/contracts/sellable.js +1 -0
  57. package/dist/catalog/draftHandler.d.ts +25 -0
  58. package/dist/catalog/draftHandler.js +118 -0
  59. package/dist/catalog/draftPorts.d.ts +18 -0
  60. package/dist/catalog/draftPorts.js +8 -0
  61. package/dist/catalog/draftSchemas.d.ts +423 -0
  62. package/dist/catalog/draftSchemas.js +89 -0
  63. package/dist/catalog/draftValidation.d.ts +21 -0
  64. package/dist/catalog/draftValidation.js +125 -0
  65. package/dist/catalog/foundationSchemas.d.ts +98 -0
  66. package/dist/catalog/foundationSchemas.js +110 -0
  67. package/dist/catalog/index.d.ts +43 -0
  68. package/dist/catalog/index.js +25 -0
  69. package/dist/catalog/mediaSourcePack.d.ts +51 -0
  70. package/dist/catalog/mediaSourcePack.js +247 -0
  71. package/dist/catalog/productTypeSchemas.d.ts +46 -0
  72. package/dist/catalog/productTypeSchemas.js +72 -0
  73. package/dist/catalog/publicationPorts.d.ts +42 -0
  74. package/dist/catalog/publicationPorts.js +1 -0
  75. package/dist/catalog/readPorts.d.ts +51 -0
  76. package/dist/catalog/readPorts.js +1 -0
  77. package/dist/catalog/referenceCatalogHandler.d.ts +7 -0
  78. package/dist/catalog/referenceCatalogHandler.js +27 -0
  79. package/dist/catalog/resolvedSkuProjection.d.ts +88 -0
  80. package/dist/catalog/resolvedSkuProjection.js +60 -0
  81. package/dist/catalog/sellableBundleHandler.d.ts +46 -0
  82. package/dist/catalog/sellableBundleHandler.js +84 -0
  83. package/dist/catalog/sellableSchemas.d.ts +46 -0
  84. package/dist/catalog/sellableSchemas.js +27 -0
  85. package/dist/catalog/sql.d.ts +46 -0
  86. package/dist/catalog/sql.js +13 -0
  87. package/dist/catalog/validation.d.ts +2 -0
  88. package/dist/catalog/validation.js +3 -0
  89. package/dist/communications/accountingDocumentDelivery.d.ts +35 -0
  90. package/dist/communications/accountingDocumentDelivery.js +33 -0
  91. package/dist/communications/authEmailError.d.ts +5 -0
  92. package/dist/communications/authEmailError.js +8 -0
  93. package/dist/communications/authEmailPorts.d.ts +2 -0
  94. package/dist/communications/authEmailPorts.js +1 -0
  95. package/dist/communications/authSendEmailHook.d.ts +35 -0
  96. package/dist/communications/authSendEmailHook.js +250 -0
  97. package/dist/communications/capturedTransactionalDelivery.d.ts +13 -0
  98. package/dist/communications/capturedTransactionalDelivery.js +14 -0
  99. package/dist/communications/communicationSync.d.ts +11 -0
  100. package/dist/communications/communicationSync.js +79 -0
  101. package/dist/communications/communicationSyncWorker.d.ts +68 -0
  102. package/dist/communications/communicationSyncWorker.js +218 -0
  103. package/dist/communications/consentPolicy.d.ts +19 -0
  104. package/dist/communications/consentPolicy.js +43 -0
  105. package/dist/communications/consentPurposeRegistry.d.ts +4 -0
  106. package/dist/communications/consentPurposeRegistry.js +24 -0
  107. package/dist/communications/contracts/abandonedCart.d.ts +27 -0
  108. package/dist/communications/contracts/abandonedCart.js +25 -0
  109. package/dist/communications/contracts/authEmail.d.ts +62 -0
  110. package/dist/communications/contracts/authEmail.js +1 -0
  111. package/dist/communications/contracts/backInStock.d.ts +28 -0
  112. package/dist/communications/contracts/backInStock.js +28 -0
  113. package/dist/communications/contracts/blocks.d.ts +24 -0
  114. package/dist/communications/contracts/blocks.js +23 -0
  115. package/dist/communications/contracts/checkoutExpired.d.ts +22 -0
  116. package/dist/communications/contracts/checkoutExpired.js +25 -0
  117. package/dist/communications/contracts/checkoutRecovery.d.ts +26 -0
  118. package/dist/communications/contracts/checkoutRecovery.js +37 -0
  119. package/dist/communications/contracts/commerceEmailContent.d.ts +176 -0
  120. package/dist/communications/contracts/commerceEmailContent.js +1 -0
  121. package/dist/communications/contracts/commerceEngagementEmailContent.d.ts +95 -0
  122. package/dist/communications/contracts/commerceEngagementEmailContent.js +1 -0
  123. package/dist/communications/contracts/consent.d.ts +12 -0
  124. package/dist/communications/contracts/consent.js +1 -0
  125. package/dist/communications/contracts/email.d.ts +182 -0
  126. package/dist/communications/contracts/email.js +1 -0
  127. package/dist/communications/contracts/guideCard.d.ts +3 -0
  128. package/dist/communications/contracts/guideCard.js +26 -0
  129. package/dist/communications/contracts/index.d.ts +52 -0
  130. package/dist/communications/contracts/index.js +42 -0
  131. package/dist/communications/contracts/inquiryContent.d.ts +32 -0
  132. package/dist/communications/contracts/inquiryContent.js +33 -0
  133. package/dist/communications/contracts/invoiceDocumentContent.d.ts +26 -0
  134. package/dist/communications/contracts/invoiceDocumentContent.js +36 -0
  135. package/dist/communications/contracts/marketingAutomation.d.ts +52 -0
  136. package/dist/communications/contracts/marketingAutomation.js +1 -0
  137. package/dist/communications/contracts/marketingSync.d.ts +194 -0
  138. package/dist/communications/contracts/marketingSync.js +1 -0
  139. package/dist/communications/contracts/newsletter.d.ts +63 -0
  140. package/dist/communications/contracts/newsletter.js +1 -0
  141. package/dist/communications/contracts/newsletterWebhook.d.ts +26 -0
  142. package/dist/communications/contracts/newsletterWebhook.js +1 -0
  143. package/dist/communications/contracts/optOutContent.d.ts +11 -0
  144. package/dist/communications/contracts/optOutContent.js +17 -0
  145. package/dist/communications/contracts/orderCanceled.d.ts +25 -0
  146. package/dist/communications/contracts/orderCanceled.js +27 -0
  147. package/dist/communications/contracts/orderDraft.d.ts +46 -0
  148. package/dist/communications/contracts/orderDraft.js +46 -0
  149. package/dist/communications/contracts/orderPaid.d.ts +53 -0
  150. package/dist/communications/contracts/orderPaid.js +71 -0
  151. package/dist/communications/contracts/orderRefunded.d.ts +24 -0
  152. package/dist/communications/contracts/orderRefunded.js +27 -0
  153. package/dist/communications/contracts/paymentFailed.d.ts +24 -0
  154. package/dist/communications/contracts/paymentFailed.js +24 -0
  155. package/dist/communications/contracts/publicIntake.d.ts +49 -0
  156. package/dist/communications/contracts/publicIntake.js +1 -0
  157. package/dist/communications/contracts/render.d.ts +2 -0
  158. package/dist/communications/contracts/render.js +229 -0
  159. package/dist/communications/contracts/reorderReminder.d.ts +24 -0
  160. package/dist/communications/contracts/reorderReminder.js +24 -0
  161. package/dist/communications/contracts/returnEmails.d.ts +25 -0
  162. package/dist/communications/contracts/returnEmails.js +62 -0
  163. package/dist/communications/contracts/reviewEffects.d.ts +26 -0
  164. package/dist/communications/contracts/reviewEffects.js +25 -0
  165. package/dist/communications/contracts/reviewRequest.d.ts +26 -0
  166. package/dist/communications/contracts/reviewRequest.js +24 -0
  167. package/dist/communications/contracts/roleNotificationContent.d.ts +25 -0
  168. package/dist/communications/contracts/roleNotificationContent.js +46 -0
  169. package/dist/communications/contracts/shipmentDelivered.d.ts +23 -0
  170. package/dist/communications/contracts/shipmentDelivered.js +24 -0
  171. package/dist/communications/contracts/shipmentDispatched.d.ts +27 -0
  172. package/dist/communications/contracts/shipmentDispatched.js +35 -0
  173. package/dist/communications/contracts/shipmentException.d.ts +21 -0
  174. package/dist/communications/contracts/shipmentException.js +26 -0
  175. package/dist/communications/contracts/subscriptionActivationActionRequired.d.ts +17 -0
  176. package/dist/communications/contracts/subscriptionActivationActionRequired.js +22 -0
  177. package/dist/communications/contracts/subscriptionAddressChanged.d.ts +19 -0
  178. package/dist/communications/contracts/subscriptionAddressChanged.js +25 -0
  179. package/dist/communications/contracts/subscriptionCancelled.d.ts +19 -0
  180. package/dist/communications/contracts/subscriptionCancelled.js +25 -0
  181. package/dist/communications/contracts/subscriptionCycleSkipped.d.ts +25 -0
  182. package/dist/communications/contracts/subscriptionCycleSkipped.js +40 -0
  183. package/dist/communications/contracts/subscriptionDeliveryRescheduled.d.ts +25 -0
  184. package/dist/communications/contracts/subscriptionDeliveryRescheduled.js +39 -0
  185. package/dist/communications/contracts/subscriptionEmailContent.d.ts +145 -0
  186. package/dist/communications/contracts/subscriptionEmailContent.js +1 -0
  187. package/dist/communications/contracts/subscriptionPackageChanged.d.ts +20 -0
  188. package/dist/communications/contracts/subscriptionPackageChanged.js +26 -0
  189. package/dist/communications/contracts/subscriptionPauseReminder.d.ts +23 -0
  190. package/dist/communications/contracts/subscriptionPauseReminder.js +29 -0
  191. package/dist/communications/contracts/subscriptionPaused.d.ts +21 -0
  192. package/dist/communications/contracts/subscriptionPaused.js +25 -0
  193. package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +34 -0
  194. package/dist/communications/contracts/subscriptionPaymentExpired.js +37 -0
  195. package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +49 -0
  196. package/dist/communications/contracts/subscriptionPaymentFailed.js +56 -0
  197. package/dist/communications/contracts/subscriptionPaymentRecovered.d.ts +19 -0
  198. package/dist/communications/contracts/subscriptionPaymentRecovered.js +22 -0
  199. package/dist/communications/contracts/subscriptionRenewalAtRisk.d.ts +36 -0
  200. package/dist/communications/contracts/subscriptionRenewalAtRisk.js +36 -0
  201. package/dist/communications/contracts/subscriptionRenewalUpcoming.d.ts +49 -0
  202. package/dist/communications/contracts/subscriptionRenewalUpcoming.js +43 -0
  203. package/dist/communications/contracts/subscriptionResumed.d.ts +23 -0
  204. package/dist/communications/contracts/subscriptionResumed.js +25 -0
  205. package/dist/communications/contracts/subscriptionWelcome.d.ts +44 -0
  206. package/dist/communications/contracts/subscriptionWelcome.js +45 -0
  207. package/dist/communications/contracts/subscriptionWinback.d.ts +21 -0
  208. package/dist/communications/contracts/subscriptionWinback.js +28 -0
  209. package/dist/communications/contracts/transactionalDelivery.d.ts +42 -0
  210. package/dist/communications/contracts/transactionalDelivery.js +1 -0
  211. package/dist/communications/contracts/types.d.ts +46 -0
  212. package/dist/communications/contracts/types.js +1 -0
  213. package/dist/communications/contribution.d.ts +10 -0
  214. package/dist/communications/contribution.js +24 -0
  215. package/dist/communications/deliveryReconciliation.d.ts +64 -0
  216. package/dist/communications/deliveryReconciliation.js +60 -0
  217. package/dist/communications/emailEgress.d.ts +38 -0
  218. package/dist/communications/emailEgress.js +100 -0
  219. package/dist/communications/emailHealthAssessment.d.ts +39 -0
  220. package/dist/communications/emailHealthAssessment.js +59 -0
  221. package/dist/communications/emailHealthMetricsPort.d.ts +17 -0
  222. package/dist/communications/emailHealthMetricsPort.js +1 -0
  223. package/dist/communications/emailNotificationControl.d.ts +27 -0
  224. package/dist/communications/emailNotificationControl.js +10 -0
  225. package/dist/communications/emailObservation.d.ts +28 -0
  226. package/dist/communications/emailObservation.js +23 -0
  227. package/dist/communications/emailTransport.d.ts +82 -0
  228. package/dist/communications/emailTransport.js +95 -0
  229. package/dist/communications/errors.d.ts +15 -0
  230. package/dist/communications/errors.js +30 -0
  231. package/dist/communications/index.d.ts +47 -0
  232. package/dist/communications/index.js +38 -0
  233. package/dist/communications/integrationEventSignature.d.ts +15 -0
  234. package/dist/communications/integrationEventSignature.js +37 -0
  235. package/dist/communications/klaviyo/consentPush.d.ts +51 -0
  236. package/dist/communications/klaviyo/consentPush.js +19 -0
  237. package/dist/communications/klaviyo/index.d.ts +110 -0
  238. package/dist/communications/klaviyo/index.js +860 -0
  239. package/dist/communications/managedTransactionalDeliveryStore.d.ts +12 -0
  240. package/dist/communications/managedTransactionalDeliveryStore.js +49 -0
  241. package/dist/communications/nativeOperations.d.ts +79 -0
  242. package/dist/communications/nativeOperations.js +3 -0
  243. package/dist/communications/newsletterIntegrationContracts.d.ts +130 -0
  244. package/dist/communications/newsletterIntegrationContracts.js +128 -0
  245. package/dist/communications/newsletterWebhookPort.d.ts +11 -0
  246. package/dist/communications/newsletterWebhookPort.js +84 -0
  247. package/dist/communications/newsletterWebhookProcessing.d.ts +17 -0
  248. package/dist/communications/newsletterWebhookProcessing.js +71 -0
  249. package/dist/communications/originPolicy.d.ts +40 -0
  250. package/dist/communications/originPolicy.js +100 -0
  251. package/dist/communications/postgresCommunicationSync.d.ts +79 -0
  252. package/dist/communications/postgresCommunicationSync.js +111 -0
  253. package/dist/communications/postgresConsentEvaluator.d.ts +19 -0
  254. package/dist/communications/postgresConsentEvaluator.js +43 -0
  255. package/dist/communications/postgresDeliveryReconciliation.d.ts +3 -0
  256. package/dist/communications/postgresDeliveryReconciliation.js +113 -0
  257. package/dist/communications/postgresNativeOperations.d.ts +13 -0
  258. package/dist/communications/postgresNativeOperations.js +63 -0
  259. package/dist/communications/postgresNotificationRecipients.d.ts +37 -0
  260. package/dist/communications/postgresNotificationRecipients.js +60 -0
  261. package/dist/communications/postgresTransactionalDeliveryStore.d.ts +7 -0
  262. package/dist/communications/postgresTransactionalDeliveryStore.js +55 -0
  263. package/dist/communications/preferencesToken.d.ts +10 -0
  264. package/dist/communications/preferencesToken.js +40 -0
  265. package/dist/communications/publicPreferenceToken.d.ts +24 -0
  266. package/dist/communications/publicPreferenceToken.js +53 -0
  267. package/dist/communications/resend/index.d.ts +40 -0
  268. package/dist/communications/resend/index.js +310 -0
  269. package/dist/communications/shipmentNotifications.d.ts +34 -0
  270. package/dist/communications/shipmentNotifications.js +61 -0
  271. package/dist/communications/sql.d.ts +26 -0
  272. package/dist/communications/sql.js +7 -0
  273. package/dist/communications/standardWebhooks.d.ts +14 -0
  274. package/dist/communications/standardWebhooks.js +73 -0
  275. package/dist/communications/status.d.ts +11 -0
  276. package/dist/communications/status.js +36 -0
  277. package/dist/communications/transactionalDelivery.d.ts +19 -0
  278. package/dist/communications/transactionalDelivery.js +96 -0
  279. package/dist/communications/transactionalDeliveryIdentifier.d.ts +3 -0
  280. package/dist/communications/transactionalDeliveryIdentifier.js +6 -0
  281. package/dist/communications/unsubscribeToken.d.ts +77 -0
  282. package/dist/communications/unsubscribeToken.js +150 -0
  283. package/dist/communications/validation.d.ts +2 -0
  284. package/dist/communications/validation.js +3 -0
  285. package/dist/composition/catalogContribution.d.ts +18 -0
  286. package/dist/composition/catalogContribution.js +21 -0
  287. package/dist/composition/index.d.ts +1 -0
  288. package/dist/composition/index.js +1 -0
  289. package/dist/http/index.d.ts +1 -0
  290. package/dist/http/index.js +1 -0
  291. package/dist/http/webhookSignature.d.ts +42 -0
  292. package/dist/http/webhookSignature.js +86 -0
  293. package/dist/identity/customerContracts.d.ts +2 -2
  294. package/dist/inventory/adminInventory.d.ts +13 -0
  295. package/dist/inventory/adminInventory.js +214 -0
  296. package/dist/inventory/contracts/forecast.d.ts +86 -0
  297. package/dist/inventory/contracts/forecast.js +1 -0
  298. package/dist/inventory/contracts/index.d.ts +4 -0
  299. package/dist/inventory/contracts/index.js +1 -0
  300. package/dist/inventory/contracts/inventory.d.ts +157 -0
  301. package/dist/inventory/contracts/inventory.js +1 -0
  302. package/dist/inventory/contracts/newPurchaseStock.d.ts +20 -0
  303. package/dist/inventory/contracts/newPurchaseStock.js +1 -0
  304. package/dist/inventory/contracts/reservation.d.ts +18 -0
  305. package/dist/inventory/contracts/reservation.js +1 -0
  306. package/dist/inventory/forecast.d.ts +24 -0
  307. package/dist/inventory/forecast.js +200 -0
  308. package/dist/inventory/index.d.ts +13 -0
  309. package/dist/inventory/index.js +10 -0
  310. package/dist/inventory/inventoryHandlers.d.ts +53 -0
  311. package/dist/inventory/inventoryHandlers.js +151 -0
  312. package/dist/inventory/newPurchaseStockAvailability.d.ts +47 -0
  313. package/dist/inventory/newPurchaseStockAvailability.js +75 -0
  314. package/dist/inventory/ports.d.ts +21 -0
  315. package/dist/inventory/ports.js +16 -0
  316. package/dist/inventory/renewalReservation.d.ts +27 -0
  317. package/dist/inventory/renewalReservation.js +61 -0
  318. package/dist/inventory/reservationPolicy.d.ts +6 -0
  319. package/dist/inventory/reservationPolicy.js +19 -0
  320. package/dist/inventory/schemas.d.ts +137 -0
  321. package/dist/inventory/schemas.js +112 -0
  322. package/dist/inventory/sql.d.ts +14 -0
  323. package/dist/inventory/sql.js +5 -0
  324. package/dist/inventory/subscriptionForecastCalculation.d.ts +4 -0
  325. package/dist/inventory/subscriptionForecastCalculation.js +133 -0
  326. package/dist/pricing/acquisitionFinancialPolicy.d.ts +26 -0
  327. package/dist/pricing/acquisitionFinancialPolicy.js +1 -0
  328. package/dist/pricing/acquisitionOfferPricing.d.ts +27 -0
  329. package/dist/pricing/acquisitionOfferPricing.js +25 -0
  330. package/dist/pricing/acquisitionOfferPricingHandler.d.ts +20 -0
  331. package/dist/pricing/acquisitionOfferPricingHandler.js +105 -0
  332. package/dist/pricing/acquisitionOfferPricingSchemas.d.ts +31 -0
  333. package/dist/pricing/acquisitionOfferPricingSchemas.js +33 -0
  334. package/dist/pricing/acquisitionQuoteBinding.d.ts +12 -0
  335. package/dist/pricing/acquisitionQuoteBinding.js +12 -0
  336. package/dist/pricing/acquisitionReadiness.d.ts +31 -0
  337. package/dist/pricing/acquisitionReadiness.js +117 -0
  338. package/dist/pricing/acquisitionTerms.d.ts +19 -0
  339. package/dist/pricing/acquisitionTerms.js +126 -0
  340. package/dist/pricing/acquisitionTermsSchemas.d.ts +59 -0
  341. package/dist/pricing/acquisitionTermsSchemas.js +42 -0
  342. package/dist/pricing/catalogFactsProvenance.d.ts +33 -0
  343. package/dist/pricing/catalogFactsProvenance.js +64 -0
  344. package/dist/pricing/catalogFactsSchemas.d.ts +45 -0
  345. package/dist/pricing/catalogFactsSchemas.js +58 -0
  346. package/dist/pricing/commerceOfferPricing.d.ts +25 -0
  347. package/dist/pricing/commerceOfferPricing.js +139 -0
  348. package/dist/pricing/commerceOfferPricingCache.d.ts +10 -0
  349. package/dist/pricing/commerceOfferPricingCache.js +44 -0
  350. package/dist/pricing/commerceOfferPricingHandler.d.ts +21 -0
  351. package/dist/pricing/commerceOfferPricingHandler.js +78 -0
  352. package/dist/pricing/commercePriceAuthority.d.ts +26 -0
  353. package/dist/pricing/commercePriceAuthority.js +79 -0
  354. package/dist/pricing/commercePricingPolicyErrors.d.ts +40 -0
  355. package/dist/pricing/commercePricingPolicyErrors.js +67 -0
  356. package/dist/pricing/commerceQuoteBatchHandler.d.ts +37 -0
  357. package/dist/pricing/commerceQuoteBatchHandler.js +83 -0
  358. package/dist/pricing/commerceQuoteCatalogReadPort.d.ts +27 -0
  359. package/dist/pricing/commerceQuoteCatalogReadPort.js +8 -0
  360. package/dist/pricing/commerceQuoteHandler.d.ts +31 -0
  361. package/dist/pricing/commerceQuoteHandler.js +110 -0
  362. package/dist/pricing/commerceQuoteSnapshotExpect.d.ts +9 -0
  363. package/dist/pricing/commerceQuoteSnapshotExpect.js +22 -0
  364. package/dist/pricing/contracts/acquisitionTerms.d.ts +32 -0
  365. package/dist/pricing/contracts/acquisitionTerms.js +2 -0
  366. package/dist/pricing/contracts/authority.d.ts +27 -0
  367. package/dist/pricing/contracts/authority.js +1 -0
  368. package/dist/pricing/contracts/evidence.d.ts +33 -0
  369. package/dist/pricing/contracts/evidence.js +1 -0
  370. package/dist/pricing/contracts/index.d.ts +17 -0
  371. package/dist/pricing/contracts/index.js +7 -0
  372. package/dist/pricing/contracts/money.d.ts +27 -0
  373. package/dist/pricing/contracts/money.js +1 -0
  374. package/dist/pricing/contracts/offer.d.ts +52 -0
  375. package/dist/pricing/contracts/offer.js +4 -0
  376. package/dist/pricing/contracts/offerPolicy.d.ts +16 -0
  377. package/dist/pricing/contracts/offerPolicy.js +5 -0
  378. package/dist/pricing/contracts/policy.d.ts +22 -0
  379. package/dist/pricing/contracts/policy.js +3 -0
  380. package/dist/pricing/contracts/provenance.d.ts +24 -0
  381. package/dist/pricing/contracts/provenance.js +2 -0
  382. package/dist/pricing/contracts/quote.d.ts +94 -0
  383. package/dist/pricing/contracts/quote.js +1 -0
  384. package/dist/pricing/dbBackedCommerceQuoteHelpers.d.ts +78 -0
  385. package/dist/pricing/dbBackedCommerceQuoteHelpers.js +146 -0
  386. package/dist/pricing/dbBackedCommerceQuotePort.d.ts +66 -0
  387. package/dist/pricing/dbBackedCommerceQuotePort.js +206 -0
  388. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
  389. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
  390. package/dist/pricing/index.d.ts +51 -0
  391. package/dist/pricing/index.js +36 -0
  392. package/dist/pricing/offerPolicyReadiness.d.ts +21 -0
  393. package/dist/pricing/offerPolicyReadiness.js +79 -0
  394. package/dist/pricing/offerPolicySchemas.d.ts +25 -0
  395. package/dist/pricing/offerPolicySchemas.js +15 -0
  396. package/dist/pricing/offerPricingSchemas.d.ts +315 -0
  397. package/dist/pricing/offerPricingSchemas.js +65 -0
  398. package/dist/pricing/ports.d.ts +13 -0
  399. package/dist/pricing/ports.js +9 -0
  400. package/dist/pricing/pricingPolicyToken.d.ts +39 -0
  401. package/dist/pricing/pricingPolicyToken.js +84 -0
  402. package/dist/pricing/quoteAcquisitionTerms.d.ts +2 -0
  403. package/dist/pricing/quoteAcquisitionTerms.js +4 -0
  404. package/dist/pricing/quoteCodeRejectionDetails.d.ts +20 -0
  405. package/dist/pricing/quoteCodeRejectionDetails.js +22 -0
  406. package/dist/pricing/quotePorts.d.ts +30 -0
  407. package/dist/pricing/quotePorts.js +20 -0
  408. package/dist/pricing/quotePrimitives.d.ts +13 -0
  409. package/dist/pricing/quotePrimitives.js +18 -0
  410. package/dist/pricing/quotePromotionEvidence.d.ts +39 -0
  411. package/dist/pricing/quotePromotionEvidence.js +73 -0
  412. package/dist/pricing/quoteSchemas.d.ts +1176 -0
  413. package/dist/pricing/quoteSchemas.js +196 -0
  414. package/dist/pricing/subscriptionPricePolicy.d.ts +52 -0
  415. package/dist/pricing/subscriptionPricePolicy.js +96 -0
  416. package/dist/pricing/taxProfileGuard.d.ts +2 -0
  417. package/dist/pricing/taxProfileGuard.js +24 -0
  418. package/dist/pricing/validation.d.ts +2 -0
  419. package/dist/pricing/validation.js +3 -0
  420. package/dist/promotions/adminBindings.d.ts +72 -0
  421. package/dist/promotions/adminBindings.js +1 -0
  422. package/dist/promotions/adminPromotionCodesContracts.d.ts +498 -0
  423. package/dist/promotions/adminPromotionCodesContracts.js +211 -0
  424. package/dist/promotions/adminPromotionCodesDataPort.d.ts +47 -0
  425. package/dist/promotions/adminPromotionCodesDataPort.js +1 -0
  426. package/dist/promotions/adminPromotionCodesHandler.d.ts +14 -0
  427. package/dist/promotions/adminPromotionCodesHandler.js +194 -0
  428. package/dist/promotions/adminPromotionsContracts.d.ts +235 -0
  429. package/dist/promotions/adminPromotionsContracts.js +99 -0
  430. package/dist/promotions/adminPromotionsDataPort.d.ts +42 -0
  431. package/dist/promotions/adminPromotionsDataPort.js +1 -0
  432. package/dist/promotions/adminPromotionsHandler.d.ts +16 -0
  433. package/dist/promotions/adminPromotionsHandler.js +47 -0
  434. package/dist/promotions/contracts/index.d.ts +387 -0
  435. package/dist/promotions/contracts/index.js +1 -0
  436. package/dist/promotions/index.d.ts +22 -0
  437. package/dist/promotions/index.js +21 -0
  438. package/dist/promotions/promoDataPort.d.ts +47 -0
  439. package/dist/promotions/promoDataPort.js +14 -0
  440. package/dist/promotions/promotionAcceptanceTelemetry.d.ts +29 -0
  441. package/dist/promotions/promotionAcceptanceTelemetry.js +45 -0
  442. package/dist/promotions/promotionBenefitDefinition.d.ts +37 -0
  443. package/dist/promotions/promotionBenefitDefinition.js +33 -0
  444. package/dist/promotions/promotionClaimSweepPort.d.ts +14 -0
  445. package/dist/promotions/promotionClaimSweepPort.js +8 -0
  446. package/dist/promotions/promotionClaims.d.ts +5 -0
  447. package/dist/promotions/promotionClaims.js +57 -0
  448. package/dist/promotions/promotionCodePreview.d.ts +11 -0
  449. package/dist/promotions/promotionCodePreview.js +154 -0
  450. package/dist/promotions/promotionCodeQuotePort.d.ts +25 -0
  451. package/dist/promotions/promotionCodeQuotePort.js +1 -0
  452. package/dist/promotions/promotionQuoteAcceptance.d.ts +65 -0
  453. package/dist/promotions/promotionQuoteAcceptance.js +202 -0
  454. package/dist/promotions/promotionQuoteBinding.d.ts +71 -0
  455. package/dist/promotions/promotionQuoteBinding.js +85 -0
  456. package/dist/promotions/quoteAutomaticPromotions.d.ts +24 -0
  457. package/dist/promotions/quoteAutomaticPromotions.js +36 -0
  458. package/dist/promotions/quotePromoDiscounts.d.ts +32 -0
  459. package/dist/promotions/quotePromoDiscounts.js +140 -0
  460. package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
  461. package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
  462. package/dist/promotions/quotePromotionV2.d.ts +29 -0
  463. package/dist/promotions/quotePromotionV2.js +174 -0
  464. package/dist/promotions/sql.d.ts +14 -0
  465. package/dist/promotions/sql.js +5 -0
  466. package/dist/promotions/validation.d.ts +2 -0
  467. package/dist/promotions/validation.js +3 -0
  468. package/dist/shipping/addressCanonLookupHandler.d.ts +7 -0
  469. package/dist/shipping/addressCanonLookupHandler.js +105 -0
  470. package/dist/shipping/addressCanonical.d.ts +2 -0
  471. package/dist/shipping/addressCanonical.js +26 -0
  472. package/dist/shipping/addressPorts.d.ts +39 -0
  473. package/dist/shipping/addressPorts.js +1 -0
  474. package/dist/shipping/addressSchemas.d.ts +30 -0
  475. package/dist/shipping/addressSchemas.js +1 -0
  476. package/dist/shipping/adminShippingRateHandler.d.ts +4 -0
  477. package/dist/shipping/adminShippingRateHandler.js +64 -0
  478. package/dist/shipping/contracts/address.d.ts +144 -0
  479. package/dist/shipping/contracts/address.js +1 -0
  480. package/dist/shipping/contracts/delivery.d.ts +110 -0
  481. package/dist/shipping/contracts/delivery.js +1 -0
  482. package/dist/shipping/contracts/index.d.ts +3 -0
  483. package/dist/shipping/contracts/index.js +1 -0
  484. package/dist/shipping/contracts/shippingRate.d.ts +11 -0
  485. package/dist/shipping/contracts/shippingRate.js +1 -0
  486. package/dist/shipping/customerAddressesHandler.d.ts +5 -0
  487. package/dist/shipping/customerAddressesHandler.js +80 -0
  488. package/dist/shipping/customerSelfServiceAddressModels.d.ts +27 -0
  489. package/dist/shipping/customerSelfServiceAddressModels.js +101 -0
  490. package/dist/shipping/deliverySelectionHandler.d.ts +10 -0
  491. package/dist/shipping/deliverySelectionHandler.js +77 -0
  492. package/dist/shipping/deliverySelectionPort.d.ts +8 -0
  493. package/dist/shipping/deliverySelectionPort.js +1 -0
  494. package/dist/shipping/deliverySelectionSummary.d.ts +2 -0
  495. package/dist/shipping/deliverySelectionSummary.js +53 -0
  496. package/dist/shipping/handlerSchemas.d.ts +21 -0
  497. package/dist/shipping/handlerSchemas.js +1 -0
  498. package/dist/shipping/index.d.ts +17 -0
  499. package/dist/shipping/index.js +8 -0
  500. package/dist/shipping/pickupPointSearchPort.d.ts +4 -0
  501. package/dist/shipping/pickupPointSearchPort.js +1 -0
  502. package/dist/shipping/readDeliverySelectionEvidence.d.ts +2 -0
  503. package/dist/shipping/readDeliverySelectionEvidence.js +44 -0
  504. package/dist/shipping/shippingRatePorts.d.ts +52 -0
  505. package/dist/shipping/shippingRatePorts.js +1 -0
  506. package/package.json +72 -2
  507. package/release-gates.json +249 -8
  508. package/sql/20260807140000_read_parity_catalog.sql +94 -0
  509. package/sql/20260807190000_comms_outbox_rail.sql +329 -0
  510. package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
  511. package/sql/20260810120001_transactional_delivery_receipts.sql +209 -0
  512. package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
  513. package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
  514. package/sql/20260813120000_communications_control_plane.sql +568 -0
  515. package/sql/20260814000000_fulfillment_stock_evidence.sql +239 -0
  516. package/sql/20260815120000_automatic_subscription_renewal.sql +1083 -0
  517. package/sql/20260817180000_promotion_claim_lifecycle.sql +591 -0
  518. package/sql/20260817180100_promotion_claim_lifecycle_validation.sql +23 -0
  519. package/sql/20260827220000_catalog_document_revision_foundation.sql +226 -0
  520. package/sql/20260827220001_catalog_document_revision_foundation_validate.sql +10 -0
  521. package/sql/20260908100000_catalog_draft_foundation.sql +217 -0
  522. package/sql/20261019200000_communications_native_operations.sql +68 -0
  523. package/src/catalog/activeSkuSelection.ts +20 -0
  524. package/src/catalog/adminBindings.ts +59 -0
  525. package/src/catalog/adminBundleHandler.ts +165 -0
  526. package/src/catalog/adminBundleReadHandler.ts +261 -0
  527. package/src/catalog/adminBundleWritePort.ts +102 -0
  528. package/src/catalog/bundleAvailability.ts +129 -0
  529. package/src/catalog/bundleAvailabilityService.ts +171 -0
  530. package/src/catalog/bundleBindings.ts +29 -0
  531. package/src/catalog/bundleCatalogQueries.ts +98 -0
  532. package/src/catalog/bundleCatalogReadPort.ts +177 -0
  533. package/src/catalog/bundleCatalogStore.ts +269 -0
  534. package/src/catalog/bundleRuleCodes.ts +134 -0
  535. package/src/catalog/bundleRules.ts +153 -0
  536. package/src/catalog/catalogDraftStore.ts +71 -0
  537. package/src/catalog/catalogSkuEnvelope.ts +214 -0
  538. package/src/catalog/catalogSkuEnvelopeMapper.ts +160 -0
  539. package/src/catalog/contracts/bundleAdmin.ts +20 -0
  540. package/src/catalog/contracts/bundleAvailability.ts +5 -0
  541. package/src/catalog/contracts/bundleRead.ts +13 -0
  542. package/src/catalog/contracts/draft.ts +69 -0
  543. package/src/catalog/contracts/foundation.ts +104 -0
  544. package/src/catalog/contracts/index.ts +14 -0
  545. package/src/catalog/contracts/lifecycle.ts +74 -0
  546. package/src/catalog/contracts/productMediaContracts.ts +170 -0
  547. package/src/catalog/contracts/productTypes.ts +35 -0
  548. package/src/catalog/contracts/resolveProductMedia.ts +85 -0
  549. package/src/catalog/contracts/sellable.ts +12 -0
  550. package/src/catalog/draftHandler.ts +105 -0
  551. package/src/catalog/draftPorts.ts +18 -0
  552. package/src/catalog/draftSchemas.ts +88 -0
  553. package/src/catalog/draftValidation.ts +100 -0
  554. package/src/catalog/foundationSchemas.ts +123 -0
  555. package/src/catalog/index.ts +43 -0
  556. package/src/catalog/mediaSourcePack.ts +219 -0
  557. package/src/catalog/productTypeSchemas.ts +70 -0
  558. package/src/catalog/publicationPorts.ts +44 -0
  559. package/src/catalog/readPorts.ts +61 -0
  560. package/src/catalog/referenceCatalogHandler.ts +39 -0
  561. package/src/catalog/resolvedSkuProjection.ts +76 -0
  562. package/src/catalog/sellableBundleHandler.ts +133 -0
  563. package/src/catalog/sellableSchemas.ts +33 -0
  564. package/src/catalog/sql.ts +14 -0
  565. package/src/catalog/validation.ts +3 -0
  566. package/src/communications/accountingDocumentDelivery.ts +63 -0
  567. package/src/communications/authEmailError.ts +10 -0
  568. package/src/communications/authEmailPorts.ts +2 -0
  569. package/src/communications/authSendEmailHook.ts +310 -0
  570. package/src/communications/capturedTransactionalDelivery.ts +29 -0
  571. package/src/communications/communicationSync.ts +96 -0
  572. package/src/communications/communicationSyncWorker.ts +302 -0
  573. package/src/communications/consentPolicy.ts +82 -0
  574. package/src/communications/consentPurposeRegistry.ts +31 -0
  575. package/src/communications/contracts/abandonedCart.ts +64 -0
  576. package/src/communications/contracts/authEmail.ts +73 -0
  577. package/src/communications/contracts/backInStock.ts +69 -0
  578. package/src/communications/contracts/blocks.ts +47 -0
  579. package/src/communications/contracts/checkoutExpired.ts +62 -0
  580. package/src/communications/contracts/checkoutRecovery.ts +68 -0
  581. package/src/communications/contracts/commerceEmailContent.ts +189 -0
  582. package/src/communications/contracts/commerceEngagementEmailContent.ts +106 -0
  583. package/src/communications/contracts/consent.ts +13 -0
  584. package/src/communications/contracts/email.ts +210 -0
  585. package/src/communications/contracts/guideCard.ts +34 -0
  586. package/src/communications/contracts/index.ts +52 -0
  587. package/src/communications/contracts/inquiryContent.ts +53 -0
  588. package/src/communications/contracts/invoiceDocumentContent.ts +57 -0
  589. package/src/communications/contracts/marketingAutomation.ts +45 -0
  590. package/src/communications/contracts/marketingSync.ts +109 -0
  591. package/src/communications/contracts/newsletter.ts +78 -0
  592. package/src/communications/contracts/newsletterWebhook.ts +23 -0
  593. package/src/communications/contracts/optOutContent.ts +23 -0
  594. package/src/communications/contracts/orderCanceled.ts +64 -0
  595. package/src/communications/contracts/orderDraft.ts +112 -0
  596. package/src/communications/contracts/orderPaid.ts +147 -0
  597. package/src/communications/contracts/orderRefunded.ts +63 -0
  598. package/src/communications/contracts/paymentFailed.ts +59 -0
  599. package/src/communications/contracts/publicIntake.ts +53 -0
  600. package/src/communications/contracts/render.ts +271 -0
  601. package/src/communications/contracts/reorderReminder.ts +59 -0
  602. package/src/communications/contracts/returnEmails.ts +113 -0
  603. package/src/communications/contracts/reviewEffects.ts +60 -0
  604. package/src/communications/contracts/reviewRequest.ts +59 -0
  605. package/src/communications/contracts/roleNotificationContent.ts +65 -0
  606. package/src/communications/contracts/shipmentDelivered.ts +59 -0
  607. package/src/communications/contracts/shipmentDispatched.ts +77 -0
  608. package/src/communications/contracts/shipmentException.ts +62 -0
  609. package/src/communications/contracts/subscriptionActivationActionRequired.ts +37 -0
  610. package/src/communications/contracts/subscriptionAddressChanged.ts +56 -0
  611. package/src/communications/contracts/subscriptionCancelled.ts +57 -0
  612. package/src/communications/contracts/subscriptionCycleSkipped.ts +80 -0
  613. package/src/communications/contracts/subscriptionDeliveryRescheduled.ts +79 -0
  614. package/src/communications/contracts/subscriptionEmailContent.ts +163 -0
  615. package/src/communications/contracts/subscriptionPackageChanged.ts +59 -0
  616. package/src/communications/contracts/subscriptionPauseReminder.ts +63 -0
  617. package/src/communications/contracts/subscriptionPaused.ts +58 -0
  618. package/src/communications/contracts/subscriptionPaymentExpired.ts +83 -0
  619. package/src/communications/contracts/subscriptionPaymentFailed.ts +117 -0
  620. package/src/communications/contracts/subscriptionPaymentRecovered.ts +50 -0
  621. package/src/communications/contracts/subscriptionRenewalAtRisk.ts +85 -0
  622. package/src/communications/contracts/subscriptionRenewalUpcoming.ts +103 -0
  623. package/src/communications/contracts/subscriptionResumed.ts +60 -0
  624. package/src/communications/contracts/subscriptionWelcome.ts +102 -0
  625. package/src/communications/contracts/subscriptionWinback.ts +62 -0
  626. package/src/communications/contracts/transactionalDelivery.ts +43 -0
  627. package/src/communications/contracts/types.ts +58 -0
  628. package/src/communications/contribution.ts +33 -0
  629. package/src/communications/deliveryReconciliation.ts +108 -0
  630. package/src/communications/emailEgress.ts +111 -0
  631. package/src/communications/emailHealthAssessment.ts +106 -0
  632. package/src/communications/emailHealthMetricsPort.ts +17 -0
  633. package/src/communications/emailNotificationControl.ts +28 -0
  634. package/src/communications/emailObservation.ts +43 -0
  635. package/src/communications/emailTransport.ts +167 -0
  636. package/src/communications/errors.ts +34 -0
  637. package/src/communications/index.ts +47 -0
  638. package/src/communications/integrationEventSignature.ts +49 -0
  639. package/src/communications/klaviyo/consentPush.ts +19 -0
  640. package/src/communications/klaviyo/index.ts +649 -0
  641. package/src/communications/managedTransactionalDeliveryStore.ts +59 -0
  642. package/src/communications/nativeOperations.ts +40 -0
  643. package/src/communications/newsletterIntegrationContracts.ts +154 -0
  644. package/src/communications/newsletterWebhookPort.ts +104 -0
  645. package/src/communications/newsletterWebhookProcessing.ts +102 -0
  646. package/src/communications/originPolicy.ts +151 -0
  647. package/src/communications/postgresCommunicationSync.ts +127 -0
  648. package/src/communications/postgresConsentEvaluator.ts +49 -0
  649. package/src/communications/postgresDeliveryReconciliation.ts +101 -0
  650. package/src/communications/postgresNativeOperations.ts +55 -0
  651. package/src/communications/postgresNotificationRecipients.ts +57 -0
  652. package/src/communications/postgresTransactionalDeliveryStore.ts +79 -0
  653. package/src/communications/preferencesToken.ts +62 -0
  654. package/src/communications/publicPreferenceToken.ts +68 -0
  655. package/src/communications/resend/index.ts +350 -0
  656. package/src/communications/shipmentNotifications.ts +78 -0
  657. package/src/communications/sql.ts +7 -0
  658. package/src/communications/standardWebhooks.ts +84 -0
  659. package/src/communications/status.ts +51 -0
  660. package/src/communications/transactionalDelivery.ts +114 -0
  661. package/src/communications/transactionalDeliveryIdentifier.ts +9 -0
  662. package/src/communications/unsubscribeToken.ts +186 -0
  663. package/src/communications/validation.ts +3 -0
  664. package/src/composition/catalogContribution.ts +32 -0
  665. package/src/composition/index.ts +1 -0
  666. package/src/http/index.ts +1 -0
  667. package/src/http/webhookSignature.ts +96 -0
  668. package/src/inventory/adminInventory.ts +251 -0
  669. package/src/inventory/contracts/forecast.ts +96 -0
  670. package/src/inventory/contracts/index.ts +18 -0
  671. package/src/inventory/contracts/inventory.ts +14 -0
  672. package/src/inventory/contracts/newPurchaseStock.ts +23 -0
  673. package/src/inventory/contracts/reservation.ts +20 -0
  674. package/src/inventory/forecast.ts +239 -0
  675. package/src/inventory/index.ts +21 -0
  676. package/src/inventory/inventoryHandlers.ts +215 -0
  677. package/src/inventory/newPurchaseStockAvailability.ts +120 -0
  678. package/src/inventory/ports.ts +46 -0
  679. package/src/inventory/renewalReservation.ts +88 -0
  680. package/src/inventory/reservationPolicy.ts +27 -0
  681. package/src/inventory/schemas.ts +128 -0
  682. package/src/inventory/sql.ts +5 -0
  683. package/src/inventory/subscriptionForecastCalculation.ts +157 -0
  684. package/src/pricing/acquisitionFinancialPolicy.ts +26 -0
  685. package/src/pricing/acquisitionOfferPricing.ts +38 -0
  686. package/src/pricing/acquisitionOfferPricingHandler.ts +157 -0
  687. package/src/pricing/acquisitionOfferPricingSchemas.ts +35 -0
  688. package/src/pricing/acquisitionQuoteBinding.ts +12 -0
  689. package/src/pricing/acquisitionReadiness.ts +148 -0
  690. package/src/pricing/acquisitionTerms.ts +125 -0
  691. package/src/pricing/acquisitionTermsSchemas.ts +52 -0
  692. package/src/pricing/catalogFactsProvenance.ts +102 -0
  693. package/src/pricing/catalogFactsSchemas.ts +69 -0
  694. package/src/pricing/commerceOfferPricing.ts +224 -0
  695. package/src/pricing/commerceOfferPricingCache.ts +53 -0
  696. package/src/pricing/commerceOfferPricingHandler.ts +137 -0
  697. package/src/pricing/commercePriceAuthority.ts +104 -0
  698. package/src/pricing/commercePricingPolicyErrors.ts +88 -0
  699. package/src/pricing/commerceQuoteBatchHandler.ts +129 -0
  700. package/src/pricing/commerceQuoteCatalogReadPort.ts +42 -0
  701. package/src/pricing/commerceQuoteHandler.ts +184 -0
  702. package/src/pricing/commerceQuoteSnapshotExpect.ts +48 -0
  703. package/src/pricing/contracts/acquisitionTerms.ts +26 -0
  704. package/src/pricing/contracts/authority.ts +44 -0
  705. package/src/pricing/contracts/evidence.ts +25 -0
  706. package/src/pricing/contracts/index.ts +17 -0
  707. package/src/pricing/contracts/money.ts +32 -0
  708. package/src/pricing/contracts/offer.ts +42 -0
  709. package/src/pricing/contracts/offerPolicy.ts +17 -0
  710. package/src/pricing/contracts/policy.ts +26 -0
  711. package/src/pricing/contracts/provenance.ts +19 -0
  712. package/src/pricing/contracts/quote.ts +106 -0
  713. package/src/pricing/dbBackedCommerceQuoteHelpers.ts +256 -0
  714. package/src/pricing/dbBackedCommerceQuotePort.ts +260 -0
  715. package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
  716. package/src/pricing/index.ts +52 -0
  717. package/src/pricing/offerPolicyReadiness.ts +110 -0
  718. package/src/pricing/offerPolicySchemas.ts +23 -0
  719. package/src/pricing/offerPricingSchemas.ts +92 -0
  720. package/src/pricing/ports.ts +17 -0
  721. package/src/pricing/pricingPolicyToken.ts +119 -0
  722. package/src/pricing/quoteAcquisitionTerms.ts +10 -0
  723. package/src/pricing/quoteCodeRejectionDetails.ts +23 -0
  724. package/src/pricing/quotePorts.ts +58 -0
  725. package/src/pricing/quotePrimitives.ts +21 -0
  726. package/src/pricing/quotePromotionEvidence.ts +82 -0
  727. package/src/pricing/quoteSchemas.ts +230 -0
  728. package/src/pricing/subscriptionPricePolicy.ts +113 -0
  729. package/src/pricing/taxProfileGuard.ts +33 -0
  730. package/src/pricing/validation.ts +3 -0
  731. package/src/promotions/adminBindings.ts +53 -0
  732. package/src/promotions/adminPromotionCodesContracts.ts +244 -0
  733. package/src/promotions/adminPromotionCodesDataPort.ts +56 -0
  734. package/src/promotions/adminPromotionCodesHandler.ts +254 -0
  735. package/src/promotions/adminPromotionsContracts.ts +121 -0
  736. package/src/promotions/adminPromotionsDataPort.ts +48 -0
  737. package/src/promotions/adminPromotionsHandler.ts +72 -0
  738. package/src/promotions/contracts/index.ts +387 -0
  739. package/src/promotions/index.ts +22 -0
  740. package/src/promotions/promoDataPort.ts +65 -0
  741. package/src/promotions/promotionAcceptanceTelemetry.ts +73 -0
  742. package/src/promotions/promotionBenefitDefinition.ts +48 -0
  743. package/src/promotions/promotionClaimSweepPort.ts +23 -0
  744. package/src/promotions/promotionClaims.ts +70 -0
  745. package/src/promotions/promotionCodePreview.ts +183 -0
  746. package/src/promotions/promotionCodeQuotePort.ts +35 -0
  747. package/src/promotions/promotionQuoteAcceptance.ts +284 -0
  748. package/src/promotions/promotionQuoteBinding.ts +158 -0
  749. package/src/promotions/quoteAutomaticPromotions.ts +58 -0
  750. package/src/promotions/quotePromoDiscounts.ts +185 -0
  751. package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
  752. package/src/promotions/quotePromotionV2.ts +223 -0
  753. package/src/promotions/sql.ts +5 -0
  754. package/src/promotions/validation.ts +3 -0
  755. package/src/shipping/addressCanonLookupHandler.ts +114 -0
  756. package/src/shipping/addressCanonical.ts +31 -0
  757. package/src/shipping/addressPorts.ts +48 -0
  758. package/src/shipping/addressSchemas.ts +28 -0
  759. package/src/shipping/adminShippingRateHandler.ts +72 -0
  760. package/src/shipping/contracts/address.ts +71 -0
  761. package/src/shipping/contracts/delivery.ts +114 -0
  762. package/src/shipping/contracts/index.ts +18 -0
  763. package/src/shipping/contracts/shippingRate.ts +7 -0
  764. package/src/shipping/customerAddressesHandler.ts +100 -0
  765. package/src/shipping/customerSelfServiceAddressModels.ts +124 -0
  766. package/src/shipping/deliverySelectionHandler.ts +94 -0
  767. package/src/shipping/deliverySelectionPort.ts +10 -0
  768. package/src/shipping/deliverySelectionSummary.ts +56 -0
  769. package/src/shipping/handlerSchemas.ts +19 -0
  770. package/src/shipping/index.ts +23 -0
  771. package/src/shipping/pickupPointSearchPort.ts +8 -0
  772. package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
  773. package/src/shipping/shippingRatePorts.ts +36 -0
@@ -0,0 +1,33 @@
1
+ import type { Contribution, RequiredSchema } from "@openlup/core/readiness";
2
+
3
+ /** Host-selected schema inventory: managed and direct installations have different objects. */
4
+ export function createCommunicationsContribution(options: {
5
+ version: string;
6
+ requiredSchema: RequiredSchema;
7
+ routes?: Contribution["routes"];
8
+ handlers?: Contribution["handlers"];
9
+ schedules?: Contribution["schedules"];
10
+ requiredPorts?: readonly string[];
11
+ }): Contribution {
12
+ const routes = options.routes ?? [];
13
+ const handlers = options.handlers ?? [];
14
+ const schedules = options.schedules ?? [];
15
+ return {
16
+ manifest: {
17
+ name: "@openlup/platform", version: options.version, kind: "rail",
18
+ module: {
19
+ id: "communications", kind: "capability", provides: ["./communications", "./communications/contracts"],
20
+ dependsOn: [
21
+ { module: "data", entries: ["./data"] },
22
+ { module: "identity", entries: ["./identity"] },
23
+ { module: "http", entries: ["./http"] },
24
+ ],
25
+ },
26
+ requiredSchema: options.requiredSchema,
27
+ emits: [], handles: handlers.map((handler) => handler.eventType),
28
+ schedules: schedules.map(({ id, cadenceSeconds }) => ({ id, cadenceSeconds })), routes: routes.map((route) => route.id),
29
+ requiredPorts: [...new Set(options.requiredPorts ?? [])], env: [],
30
+ },
31
+ handlers, schedules, routes,
32
+ };
33
+ }
@@ -0,0 +1,108 @@
1
+ export interface DeliveryPollCandidate {
2
+ id: string;
3
+ messageId: string;
4
+ }
5
+
6
+ export interface DeliveryStatusRead {
7
+ ok: boolean;
8
+ httpStatus: number;
9
+ recipientEmail: string | null;
10
+ }
11
+
12
+ /** The host maps its protocol to an opaque event type and terminal classification. */
13
+ export interface DeliveryPollObservation {
14
+ eventType: string;
15
+ terminal: boolean;
16
+ }
17
+
18
+ export interface DeliveryReconciliationPort {
19
+ findFrozenSends(input: { now: string; graceMinutes: number; limit: number }): Promise<DeliveryPollCandidate[]>;
20
+ applyPolledEvent(input: {
21
+ sendId: string;
22
+ messageId: string;
23
+ eventType: string;
24
+ eventAt: string;
25
+ recipientEmail: string | null;
26
+ }): Promise<void>;
27
+ recordPollAttempt(input: { sendId: string; attemptedAt: string }): Promise<void>;
28
+ recordSendNotFound(input: { sendId: string; threshold: number }): Promise<{ abandoned: boolean }>;
29
+ }
30
+
31
+ export const DELIVERY_POLL_ABANDON_AFTER_NOT_FOUND = 3;
32
+
33
+ export interface DeliveryReadFailureBreakdown {
34
+ notFound: number;
35
+ authFailed: number;
36
+ network: number;
37
+ providerError: number;
38
+ other: number;
39
+ }
40
+
41
+ export interface DeliveryReconciliationResult {
42
+ checked: number;
43
+ reconciled: number;
44
+ stillPending: number;
45
+ terminalPolled: number;
46
+ failures: number;
47
+ abandoned: number;
48
+ failureBreakdown: DeliveryReadFailureBreakdown;
49
+ }
50
+
51
+ function classifyReadFailure(breakdown: DeliveryReadFailureBreakdown, httpStatus: number): void {
52
+ if (httpStatus === 404) breakdown.notFound += 1;
53
+ else if (httpStatus === 401 || httpStatus === 403) breakdown.authFailed += 1;
54
+ else if (httpStatus === 0) breakdown.network += 1;
55
+ else if (httpStatus >= 500 && httpStatus <= 599) breakdown.providerError += 1;
56
+ else breakdown.other += 1;
57
+ }
58
+
59
+ /** Sequential bounded polling around one host-owned atomic convergence writer. */
60
+ export async function runDeliveryReconciliation<Read extends DeliveryStatusRead>(input: {
61
+ port: DeliveryReconciliationPort;
62
+ readEmail: (messageId: string) => Promise<Read>;
63
+ observationFor: (read: Read) => DeliveryPollObservation | null;
64
+ now: string;
65
+ graceMinutes: number;
66
+ limit: number;
67
+ }): Promise<DeliveryReconciliationResult> {
68
+ const result: DeliveryReconciliationResult = {
69
+ checked: 0, reconciled: 0, stillPending: 0, terminalPolled: 0, failures: 0, abandoned: 0,
70
+ failureBreakdown: { notFound: 0, authFailed: 0, network: 0, providerError: 0, other: 0 },
71
+ };
72
+ const frozen = await input.port.findFrozenSends({ now: input.now, graceMinutes: input.graceMinutes, limit: input.limit });
73
+ for (const send of frozen) {
74
+ result.checked += 1;
75
+ const read = await input.readEmail(send.messageId);
76
+ if (read.httpStatus !== 404) {
77
+ try {
78
+ await input.port.recordPollAttempt({ sendId: send.id, attemptedAt: input.now });
79
+ } catch {
80
+ // Fairness bookkeeping failure must not discard observed delivery truth.
81
+ result.failures += 1;
82
+ }
83
+ }
84
+ if (!read.ok) {
85
+ result.failures += 1;
86
+ classifyReadFailure(result.failureBreakdown, read.httpStatus);
87
+ if (read.httpStatus === 404) {
88
+ const { abandoned } = await input.port.recordSendNotFound({ sendId: send.id, threshold: DELIVERY_POLL_ABANDON_AFTER_NOT_FOUND });
89
+ if (abandoned) result.abandoned += 1;
90
+ }
91
+ continue;
92
+ }
93
+ const observation = input.observationFor(read);
94
+ if (!observation) {
95
+ result.stillPending += 1;
96
+ continue;
97
+ }
98
+ try {
99
+ await input.port.applyPolledEvent({ sendId: send.id, messageId: send.messageId,
100
+ eventType: observation.eventType, eventAt: input.now, recipientEmail: read.recipientEmail });
101
+ result.reconciled += 1;
102
+ if (observation.terminal) result.terminalPolled += 1;
103
+ } catch {
104
+ result.failures += 1;
105
+ }
106
+ }
107
+ return result;
108
+ }
@@ -0,0 +1,111 @@
1
+ import type { AuthEmailTransportPort, AuthEmailTransportResult } from "./contracts/authEmail.js";
2
+ import type { EmailMessage, EmailSendResult, EmailTransport } from "./emailTransport.js";
3
+
4
+ export interface EmailEgressContext {
5
+ mode: "production" | "sandbox_direct" | "sandbox_sink";
6
+ reason: string;
7
+ intendedRecipient: string;
8
+ recipient: string;
9
+ /** Selected by the host; consumed only by its concrete sender, never logged. */
10
+ credential: string;
11
+ environmentTag: "production" | "non_production";
12
+ }
13
+
14
+ export type EmailEgressDecision = EmailEgressContext | { mode: "drop"; reason: string } | { mode: "blocked"; reason: string };
15
+ export type EmailEgressPolicy = (intendedRecipient: string) => EmailEgressDecision | Promise<EmailEgressDecision>;
16
+
17
+ const admitted = new WeakSet<EmailTransport>();
18
+ const admittedAuth = new WeakSet<AuthEmailTransportPort>();
19
+
20
+ /**
21
+ * Host composition bridge for an implementation that already enforces egress
22
+ * internally. This is a trust boundary: its sender must itself refuse unknown
23
+ * policy before effects. New network adapters should use createGuardedEmailTransport.
24
+ * Neither a provider name nor an object property establishes admission.
25
+ */
26
+ export function admitPolicyEnforcedEmailTransport<T extends EmailTransport>(transport: T): T {
27
+ admitted.add(transport);
28
+ return transport;
29
+ }
30
+
31
+ /** Mandatory boundary for supported injected transports; raw objects fail closed. */
32
+ export function guardEmailTransport(transport: EmailTransport): EmailTransport {
33
+ if (admitted.has(transport)) return transport;
34
+ return { providerKind: transport.providerKind, send: async () => refused("email_egress_unadmitted") };
35
+ }
36
+
37
+ /** Construct a network adapter whose sender sees only a validated host decision. */
38
+ export function createGuardedEmailTransport(input: {
39
+ providerKind: string;
40
+ policy: EmailEgressPolicy;
41
+ send: (message: EmailMessage, context: Readonly<EmailEgressContext>) => Promise<EmailSendResult>;
42
+ }): EmailTransport {
43
+ return admitPolicyEnforcedEmailTransport({
44
+ providerKind: input.providerKind,
45
+ async send(message) {
46
+ let decision: unknown;
47
+ try { decision = await input.policy(message.to); }
48
+ catch { return refused("email_egress_policy_unavailable"); }
49
+ if (!validDecision(decision, message.to)) return refused("email_egress_policy_invalid");
50
+ if (decision.mode === "blocked") return refused("email_egress_blocked", decision.reason);
51
+ if (decision.mode === "drop") return {
52
+ outcome: { ok: true, resendId: null, httpStatus: 0, providerError: null, aborted: false,
53
+ suppressed: "drop", egressMode: "drop", egressReason: decision.reason },
54
+ providerResponse: { suppressed: "drop", egress_reason: decision.reason },
55
+ };
56
+ const context = Object.freeze({ ...decision });
57
+ const result = await input.send({ ...message, to: context.recipient }, context);
58
+ return { ...result, outcome: { ...result.outcome, egressMode: context.mode, egressReason: context.reason } };
59
+ },
60
+ });
61
+ }
62
+
63
+ function validDecision(value: unknown, intended: string): value is EmailEgressDecision {
64
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
65
+ const d = value as Record<string, unknown>;
66
+ // Policy diagnostics are bounded codes, never arbitrary exception/secret text.
67
+ if (typeof d.reason !== "string" || !/^[a-z][a-z0-9_]{0,79}$/.test(d.reason)) return false;
68
+ if (d.mode === "drop" || d.mode === "blocked") return Object.keys(d).every((key) => key === "mode" || key === "reason");
69
+ if (d.mode !== "production" && d.mode !== "sandbox_direct" && d.mode !== "sandbox_sink") return false;
70
+ if (!Object.keys(d).every((key) => ["mode", "reason", "intendedRecipient", "recipient", "credential", "environmentTag"].includes(key))) return false;
71
+ if (!mailbox(intended) || d.intendedRecipient !== intended || !mailbox(d.recipient)) return false;
72
+ if (d.mode !== "sandbox_sink" && d.recipient !== intended) return false;
73
+ if (typeof d.credential !== "string" || !d.credential.trim()) return false;
74
+ return d.environmentTag === (d.mode === "production" ? "production" : "non_production");
75
+ }
76
+
77
+ function mailbox(value: unknown): value is string {
78
+ return typeof value === "string" && /^[^\s@,;<>]+@[^\s@,;<>]+\.[^\s@,;<>]+$/.test(value);
79
+ }
80
+
81
+ function refused(code: string, reason?: string): EmailSendResult {
82
+ return { outcome: { ok: false, resendId: null, httpStatus: 0, providerError: code, aborted: false,
83
+ ...(reason ? { egressReason: reason } : {}) }, providerResponse: { egress_reason: code } };
84
+ }
85
+
86
+ /** Preserve the Auth envelope/result mapping while retaining package admission. */
87
+ export function createAuthEmailTransport(transport: EmailTransport): AuthEmailTransportPort {
88
+ const guarded = guardEmailTransport(transport);
89
+ const auth: AuthEmailTransportPort = {
90
+ providerKind: transport.providerKind,
91
+ async send(message) {
92
+ const result = await guarded.send({ from: message.sender, to: message.recipient,
93
+ subject: message.subject, html: message.html, text: message.text });
94
+ return { outcome: { ...result.outcome, messageId: result.outcome.resendId }, providerResponse: result.providerResponse };
95
+ },
96
+ };
97
+ admittedAuth.add(auth);
98
+ return auth;
99
+ }
100
+
101
+ /** Raw Auth closures must compose through the admitted email transport bridge. */
102
+ export function guardAuthEmailTransport(transport: AuthEmailTransportPort): AuthEmailTransportPort {
103
+ if (admittedAuth.has(transport)) return transport;
104
+ return {
105
+ providerKind: transport.providerKind,
106
+ async send(): Promise<AuthEmailTransportResult> {
107
+ const result = refused("email_egress_unadmitted");
108
+ return { outcome: { ...result.outcome, messageId: null }, providerResponse: result.providerResponse };
109
+ },
110
+ };
111
+ }
@@ -0,0 +1,106 @@
1
+ import type { EmailHealthMetrics } from "./emailHealthMetricsPort.js";
2
+
3
+ /**
4
+ * Pure email-health assessment layer: env-derived thresholds plus the
5
+ * healthy/unhealthy verdict over the delivery metrics. Extracted from
6
+ * `api/_cron/emailHealthWatchdogJob.ts` (which sat at the 300-LOC source cap)
7
+ * so the incident-driven `permanent_delivery_failure` breach could land here
8
+ * with unit coverage and no database in the loop.
9
+ */
10
+
11
+ type Env = Record<string, string | undefined>;
12
+
13
+ export interface EmailHealthThresholds {
14
+ windowMinutes: number;
15
+ stuckMinutes: number;
16
+ minAttemptsForRatio: number;
17
+ maxFailureRatio: number;
18
+ maxStuck: number;
19
+ /**
20
+ * Absolute ceiling on in-window deliveries that ended `status='failed'`
21
+ * (handler-final loss of a customer notification: outbox discard,
22
+ * max-attempts exhaustion). Default 0 — a single lost email breaches.
23
+ * Bounces/complaints are separate statuses and stay ratio-only.
24
+ */
25
+ maxPermanentFailures: number;
26
+ }
27
+
28
+ export interface EmailHealthBreach {
29
+ code: string;
30
+ detail: string;
31
+ }
32
+
33
+ export interface EmailHealthAssessment {
34
+ healthy: boolean;
35
+ failureRatio: number;
36
+ breaches: EmailHealthBreach[];
37
+ }
38
+
39
+ export function readEmailHealthThresholds(env: Env): EmailHealthThresholds {
40
+ return {
41
+ windowMinutes: positiveInt(env.EMAIL_HEALTH_WINDOW_MINUTES, 60),
42
+ stuckMinutes: positiveInt(env.EMAIL_HEALTH_STUCK_MINUTES, 30),
43
+ minAttemptsForRatio: positiveInt(env.EMAIL_HEALTH_MIN_ATTEMPTS_FOR_RATIO, 5),
44
+ maxFailureRatio: clampRatio(env.EMAIL_HEALTH_MAX_FAILURE_RATIO, 0.5),
45
+ maxStuck: nonNegativeInt(env.EMAIL_HEALTH_MAX_STUCK, 0),
46
+ maxPermanentFailures: nonNegativeInt(env.EMAIL_HEALTH_MAX_PERMANENT_FAILURES, 0),
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Pure decision: turn raw counts into a healthy/unhealthy verdict. Kept side
52
+ * effect-free so the thresholds logic is unit-tested without a database.
53
+ */
54
+ export function evaluateEmailHealth(
55
+ metrics: EmailHealthMetrics,
56
+ thresholds: EmailHealthThresholds,
57
+ ): EmailHealthAssessment {
58
+ const failureRatio = metrics.attempted > 0 ? metrics.failed / metrics.attempted : 0;
59
+ const breaches: EmailHealthBreach[] = [];
60
+
61
+ if (metrics.attempted >= thresholds.minAttemptsForRatio && failureRatio > thresholds.maxFailureRatio) {
62
+ breaches.push({
63
+ code: "failure_ratio",
64
+ detail: `${metrics.failed}/${metrics.attempted} (${(failureRatio * 100).toFixed(1)}%) > ${(thresholds.maxFailureRatio * 100).toFixed(1)}%`,
65
+ });
66
+ }
67
+ // Absolute, ratio-independent: one terminally-failed delivery is one
68
+ // customer notification we finally did not send. Incident 2026-07-24: a
69
+ // single discarded payment-recovery email stayed invisible because the
70
+ // ratio breach needs minAttemptsForRatio sends in the window.
71
+ if (metrics.permanentFailures > thresholds.maxPermanentFailures) {
72
+ breaches.push({
73
+ code: "permanent_delivery_failure",
74
+ detail: `${metrics.permanentFailures} delivery(ies) terminally failed > ${thresholds.maxPermanentFailures}`,
75
+ });
76
+ }
77
+ if (metrics.stuckProcessing > thresholds.maxStuck) {
78
+ breaches.push({
79
+ code: "stuck_processing",
80
+ detail: `${metrics.stuckProcessing} email(s) stuck in 'processing' > ${thresholds.stuckMinutes}m`,
81
+ });
82
+ }
83
+ if (metrics.stuckScheduled > thresholds.maxStuck) {
84
+ breaches.push({
85
+ code: "stuck_scheduled",
86
+ detail: `${metrics.stuckScheduled} scheduled email(s) overdue and undispatched`,
87
+ });
88
+ }
89
+
90
+ return { healthy: breaches.length === 0, failureRatio, breaches };
91
+ }
92
+
93
+ function positiveInt(raw: string | undefined, fallback: number): number {
94
+ const n = Number(raw);
95
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
96
+ }
97
+
98
+ function nonNegativeInt(raw: string | undefined, fallback: number): number {
99
+ const n = Number(raw);
100
+ return Number.isFinite(n) && n >= 0 ? Math.floor(n) : fallback;
101
+ }
102
+
103
+ function clampRatio(raw: string | undefined, fallback: number): number {
104
+ const n = Number(raw);
105
+ return Number.isFinite(n) && n >= 0 && n <= 1 ? n : fallback;
106
+ }
@@ -0,0 +1,17 @@
1
+ export interface EmailHealthMetrics {
2
+ attempted: number;
3
+ sent: number;
4
+ failed: number;
5
+ delayed: number;
6
+ /**
7
+ * In-window rows that ended `status='failed'` — handler-final loss of a
8
+ * customer notification (outbox discard / max-attempts). Distinct from
9
+ * `failed` above, which also counts bounces/complaints/missed for the
10
+ * ratio signal.
11
+ */
12
+ permanentFailures: number;
13
+ /** `processing` rows whose last transition is older than the stuck threshold. */
14
+ stuckProcessing: number;
15
+ /** `planned`/`queued` rows past their `expected_send_at` but still not sent. */
16
+ stuckScheduled: number;
17
+ }
@@ -0,0 +1,28 @@
1
+ export interface EmailNotificationControlPort {
2
+ isEnabled(slug: string, signal: AbortSignal): Promise<boolean>;
3
+ }
4
+
5
+ export interface EmailNotificationControlClient {
6
+ from(table: string): EmailNotificationControlQueryBuilder;
7
+ }
8
+
9
+ interface EmailNotificationControlQueryBuilder {
10
+ select(columns: string): EmailNotificationControlQueryBuilder;
11
+ eq(column: string, value: unknown): EmailNotificationControlQueryBuilder;
12
+ maybeSingle(): PromiseLike<{ data: unknown; error: { code?: string; message?: string } | null }>;
13
+ }
14
+
15
+ export function createEmailNotificationControlPort(
16
+ client: EmailNotificationControlClient,
17
+ createPolicy: (client: EmailNotificationControlClient) => { shouldDeliver(input: { slug: string; signal: AbortSignal }): Promise<{ allow: boolean }> },
18
+ ): EmailNotificationControlPort {
19
+ const policy = createPolicy(client);
20
+ return {
21
+ isEnabled(slug: string, signal: AbortSignal): Promise<boolean> {
22
+ return policy.shouldDeliver({ slug, signal }).then((decision) => decision.allow);
23
+ },
24
+ };
25
+ }
26
+
27
+ // Compatibility alias for the pre-neutralization lifecycle consumer.
28
+ export const createSupabaseEmailNotificationControlPort = createEmailNotificationControlPort;
@@ -0,0 +1,43 @@
1
+ /** An authenticated, decoded, environment-admitted observation. Evidence is opaque. */
2
+ export interface EmailObservation {
3
+ eventType: string;
4
+ eventAt: string;
5
+ metadata: Record<string, unknown>;
6
+ }
7
+
8
+ export interface EmailObservationPort {
9
+ findSend(messageId: string): Promise<{ id: string } | null>;
10
+ applyObservation(observation: EmailObservation & { sendId: string; messageId: string }): Promise<void>;
11
+ recordAttempt(attempt: EmailObservationDisposition): Promise<void>;
12
+ }
13
+
14
+ export type EmailObservationDisposition =
15
+ | { outcome: "send_not_found" }
16
+ | { outcome: "processed"; sendId: string };
17
+
18
+ /** Lookup/apply failures propagate; attempt telemetry cannot overturn authoritative success. */
19
+ export async function processEmailObservation(input: {
20
+ port: EmailObservationPort;
21
+ messageId: string;
22
+ // Construct evidence only after a local send is found (including clock reads).
23
+ observation: () => EmailObservation;
24
+ }): Promise<EmailObservationDisposition> {
25
+ const send = await input.port.findSend(input.messageId);
26
+ let disposition: EmailObservationDisposition;
27
+ if (!send) {
28
+ disposition = { outcome: "send_not_found" };
29
+ } else {
30
+ await input.port.applyObservation({
31
+ sendId: send.id,
32
+ messageId: input.messageId,
33
+ ...input.observation(),
34
+ });
35
+ disposition = { outcome: "processed", sendId: send.id };
36
+ }
37
+ try {
38
+ await input.port.recordAttempt(disposition);
39
+ } catch {
40
+ // Best-effort telemetry is separate from durable convergence.
41
+ }
42
+ return disposition;
43
+ }
@@ -0,0 +1,167 @@
1
+ import { admitPolicyEnforcedEmailTransport } from "./emailEgress.js";
2
+ /** Provider-agnostic transport contract, outcome projection and capture transport. */
3
+ export interface EmailMessage {
4
+ from: string;
5
+ to: string;
6
+ subject: string;
7
+ html: string;
8
+ /** Optional plain-text alternative; omitted from the outbound payload when absent. */
9
+ text?: string;
10
+ /** Optional reply mailbox; omitted entirely when the caller does not set it. */
11
+ replyTo?: string;
12
+ /** Stable outbound request key retained by the concrete transport for a limited window. */
13
+ idempotencyKey?: string;
14
+ /** Base64 content only; remote URLs and filesystem paths are not supported. */
15
+ attachments?: ReadonlyArray<{ filename: string; content: string }>;
16
+ /** Cancels the in-flight send when the worker's per-row timeout fires. */
17
+ signal?: AbortSignal;
18
+ }
19
+
20
+ /** Transport results preserve existing reference wire shapes. */
21
+ export interface EmailSendOutcome {
22
+ ok: boolean;
23
+ /** Legacy identifier retained for reference result compatibility. */
24
+ resendId: string | null;
25
+ httpStatus: number;
26
+ providerError: string | null;
27
+ providerErrorCode?: string | null;
28
+ aborted: boolean;
29
+ suppressed?: "drop" | null;
30
+ egressMode?: "production" | "sandbox_direct" | "sandbox_sink" | "drop";
31
+ egressReason?: string;
32
+ }
33
+ export interface EmailSendResult {
34
+ outcome: EmailSendOutcome;
35
+ providerResponse: Record<string, unknown>;
36
+ }
37
+
38
+ export type EmailSendSkipReason = "admin_disabled" | "egress_suppressed";
39
+
40
+ export interface EmailSendOutcomeLike {
41
+ ok: boolean;
42
+ resendId: string | null;
43
+ providerError: string | null;
44
+ aborted?: boolean;
45
+ adminDisabled?: boolean;
46
+ suppressed?: "drop" | null;
47
+ skipReason?: EmailSendSkipReason | null;
48
+ }
49
+
50
+ /** Converts the transport's legacy identifier field at the transport boundary. */
51
+ export function emailTransportMessageId(outcome: EmailSendOutcomeLike): string | null {
52
+ return outcome.resendId;
53
+ }
54
+
55
+ /** Maps the neutral message identifier onto the deployed ledger's legacy field. */
56
+ export function emailTransportLedgerIdentifier(messageId: string | null): Record<string, string | null> {
57
+ return { resend_id: messageId };
58
+ }
59
+
60
+ /** Synthesizes the canonical terminal transport shape when `send` throws. */
61
+ export function failedEmailTransportResult(): EmailSendResult {
62
+ return {
63
+ outcome: { ok: false, resendId: null, httpStatus: 0, providerError: "provider_transport_threw", aborted: false },
64
+ providerResponse: { exception: true },
65
+ };
66
+ }
67
+
68
+ export interface EmailSendOutcomeProjection {
69
+ skipReason: EmailSendSkipReason | null;
70
+ timelineStatus: "sent" | "skipped" | "delivery_delayed" | "failed";
71
+ ledgerStatus: "sent" | "skipped" | "failed";
72
+ sentAtEligible: boolean;
73
+ lastErrorCode: string | null;
74
+ }
75
+
76
+ /** One truth projection for every Node email ledger, timeline and caller. */
77
+ export function classifyEmailSendOutcome(outcome: EmailSendOutcomeLike): EmailSendOutcomeProjection {
78
+ const skipReason = outcome.skipReason
79
+ ?? (outcome.adminDisabled ? "admin_disabled" : null)
80
+ ?? (outcome.suppressed === "drop" ? "egress_suppressed" : null);
81
+ if (skipReason) {
82
+ return {
83
+ skipReason,
84
+ timelineStatus: "skipped",
85
+ ledgerStatus: "skipped",
86
+ sentAtEligible: false,
87
+ lastErrorCode: skipReason,
88
+ };
89
+ }
90
+ // `ok` deliberately remains the transport-acceptance contract. In particular,
91
+ // this wave does not turn a historical 2xx-without-id answer into a retry.
92
+ if (outcome.ok) {
93
+ return {
94
+ skipReason: null,
95
+ timelineStatus: "sent",
96
+ ledgerStatus: "sent",
97
+ sentAtEligible: true,
98
+ lastErrorCode: null,
99
+ };
100
+ }
101
+ if (outcome.aborted) {
102
+ return {
103
+ skipReason: null,
104
+ timelineStatus: "delivery_delayed",
105
+ ledgerStatus: "failed",
106
+ sentAtEligible: false,
107
+ lastErrorCode: "provider_request_aborted",
108
+ };
109
+ }
110
+ return {
111
+ skipReason: null,
112
+ timelineStatus: "failed",
113
+ ledgerStatus: "failed",
114
+ sentAtEligible: false,
115
+ lastErrorCode: normalizeEmailFailureCode(outcome.providerError),
116
+ };
117
+ }
118
+
119
+ /** Adds a provider-neutral skip reason without changing ordinary wire shapes. */
120
+ export function withEmailSendSkipReason<T extends EmailSendOutcomeLike>(outcome: T): T {
121
+ const skipReason = classifyEmailSendOutcome(outcome).skipReason;
122
+ return skipReason ? { ...outcome, skipReason } : outcome;
123
+ }
124
+
125
+ function normalizeEmailFailureCode(value: string | null): string {
126
+ if (!value) return "provider_send_failed";
127
+ const normalized = value
128
+ .toLowerCase()
129
+ .replace(/[^a-z0-9]+/g, "_")
130
+ .replace(/^_+|_+$/g, "")
131
+ .slice(0, 80);
132
+ return normalized || "provider_send_failed";
133
+ }
134
+
135
+ export interface EmailTransport {
136
+ /** Stable provider tag for ledgers/observability (e.g. "mailProvider", "in-memory"). */
137
+ readonly providerKind: string;
138
+ send(message: EmailMessage): Promise<EmailSendResult>;
139
+ }
140
+
141
+ export interface InMemoryEmailTransport extends EmailTransport {
142
+ /** Every message handed to send(), in order — for tests and dry runs. */
143
+ readonly sent: ReadonlyArray<EmailMessage>;
144
+ }
145
+
146
+ /**
147
+ * Reference capture transport: captures sends in memory and never makes a
148
+ * network call. Proves the seam is real — a port wired to this sends email with
149
+ * no HTTP client — and doubles as the substitute an OSS fork starts from
150
+ * before writing its own SES/SMTP adapter.
151
+ */
152
+ export function createInMemoryEmailTransport(opts?: { idPrefix?: string }): InMemoryEmailTransport {
153
+ const sent: EmailMessage[] = [];
154
+ const prefix = opts?.idPrefix ?? "in-memory";
155
+ return admitPolicyEnforcedEmailTransport({
156
+ providerKind: "in-memory",
157
+ sent,
158
+ async send(message) {
159
+ sent.push(message);
160
+ const id = `${prefix}-${sent.length}`;
161
+ return {
162
+ outcome: { ok: true, resendId: id, httpStatus: 200, providerError: null, aborted: false },
163
+ providerResponse: { id },
164
+ };
165
+ },
166
+ });
167
+ }
@@ -0,0 +1,34 @@
1
+ export class CommunicationRecipientNotFoundError extends Error {
2
+ constructor(message = "Communication recipient not found") {
3
+ super(message);
4
+ this.name = "CommunicationRecipientNotFoundError";
5
+ }
6
+ }
7
+
8
+ export class CommunicationTemplateNotFoundError extends Error {
9
+ constructor(message = "Communication template not found") {
10
+ super(message);
11
+ this.name = "CommunicationTemplateNotFoundError";
12
+ }
13
+ }
14
+
15
+ export class CommunicationConflictError extends Error {
16
+ constructor(message = "Communication request conflicts with current state") {
17
+ super(message);
18
+ this.name = "CommunicationConflictError";
19
+ }
20
+ }
21
+
22
+ export class CommunicationValidationError extends Error {
23
+ constructor(message = "Communication request is invalid") {
24
+ super(message);
25
+ this.name = "CommunicationValidationError";
26
+ }
27
+ }
28
+
29
+ export class CommunicationUnavailableError extends Error {
30
+ constructor(message = "Communication capability is unavailable") {
31
+ super(message);
32
+ this.name = "CommunicationUnavailableError";
33
+ }
34
+ }