@openlup/platform 0.17.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 (486) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +284 -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/contracts/index.d.ts +1 -0
  90. package/dist/communications/contracts/marketingSync.d.ts +194 -0
  91. package/dist/communications/contracts/marketingSync.js +1 -0
  92. package/dist/communications/index.d.ts +1 -0
  93. package/dist/communications/klaviyo/consentPush.d.ts +51 -0
  94. package/dist/communications/klaviyo/consentPush.js +19 -0
  95. package/dist/communications/klaviyo/index.d.ts +110 -0
  96. package/dist/communications/klaviyo/index.js +860 -0
  97. package/dist/communications/newsletterIntegrationContracts.d.ts +3 -3
  98. package/dist/communications/resend/index.d.ts +40 -0
  99. package/dist/communications/resend/index.js +310 -0
  100. package/dist/composition/catalogContribution.d.ts +18 -0
  101. package/dist/composition/catalogContribution.js +21 -0
  102. package/dist/composition/index.d.ts +1 -0
  103. package/dist/composition/index.js +1 -0
  104. package/dist/identity/customerContracts.d.ts +2 -2
  105. package/dist/inventory/adminInventory.d.ts +13 -0
  106. package/dist/inventory/adminInventory.js +214 -0
  107. package/dist/inventory/contracts/forecast.d.ts +86 -0
  108. package/dist/inventory/contracts/forecast.js +1 -0
  109. package/dist/inventory/contracts/index.d.ts +4 -0
  110. package/dist/inventory/contracts/index.js +1 -0
  111. package/dist/inventory/contracts/inventory.d.ts +157 -0
  112. package/dist/inventory/contracts/inventory.js +1 -0
  113. package/dist/inventory/contracts/newPurchaseStock.d.ts +20 -0
  114. package/dist/inventory/contracts/newPurchaseStock.js +1 -0
  115. package/dist/inventory/contracts/reservation.d.ts +18 -0
  116. package/dist/inventory/contracts/reservation.js +1 -0
  117. package/dist/inventory/forecast.d.ts +24 -0
  118. package/dist/inventory/forecast.js +200 -0
  119. package/dist/inventory/index.d.ts +13 -0
  120. package/dist/inventory/index.js +10 -0
  121. package/dist/inventory/inventoryHandlers.d.ts +53 -0
  122. package/dist/inventory/inventoryHandlers.js +151 -0
  123. package/dist/inventory/newPurchaseStockAvailability.d.ts +47 -0
  124. package/dist/inventory/newPurchaseStockAvailability.js +75 -0
  125. package/dist/inventory/ports.d.ts +21 -0
  126. package/dist/inventory/ports.js +16 -0
  127. package/dist/inventory/renewalReservation.d.ts +27 -0
  128. package/dist/inventory/renewalReservation.js +61 -0
  129. package/dist/inventory/reservationPolicy.d.ts +6 -0
  130. package/dist/inventory/reservationPolicy.js +19 -0
  131. package/dist/inventory/schemas.d.ts +137 -0
  132. package/dist/inventory/schemas.js +112 -0
  133. package/dist/inventory/sql.d.ts +14 -0
  134. package/dist/inventory/sql.js +5 -0
  135. package/dist/inventory/subscriptionForecastCalculation.d.ts +4 -0
  136. package/dist/inventory/subscriptionForecastCalculation.js +133 -0
  137. package/dist/pricing/acquisitionFinancialPolicy.d.ts +26 -0
  138. package/dist/pricing/acquisitionFinancialPolicy.js +1 -0
  139. package/dist/pricing/acquisitionOfferPricing.d.ts +27 -0
  140. package/dist/pricing/acquisitionOfferPricing.js +25 -0
  141. package/dist/pricing/acquisitionOfferPricingHandler.d.ts +20 -0
  142. package/dist/pricing/acquisitionOfferPricingHandler.js +105 -0
  143. package/dist/pricing/acquisitionOfferPricingSchemas.d.ts +31 -0
  144. package/dist/pricing/acquisitionOfferPricingSchemas.js +33 -0
  145. package/dist/pricing/acquisitionQuoteBinding.d.ts +12 -0
  146. package/dist/pricing/acquisitionQuoteBinding.js +12 -0
  147. package/dist/pricing/acquisitionReadiness.d.ts +31 -0
  148. package/dist/pricing/acquisitionReadiness.js +117 -0
  149. package/dist/pricing/acquisitionTerms.d.ts +19 -0
  150. package/dist/pricing/acquisitionTerms.js +126 -0
  151. package/dist/pricing/acquisitionTermsSchemas.d.ts +59 -0
  152. package/dist/pricing/acquisitionTermsSchemas.js +42 -0
  153. package/dist/pricing/catalogFactsProvenance.d.ts +33 -0
  154. package/dist/pricing/catalogFactsProvenance.js +64 -0
  155. package/dist/pricing/catalogFactsSchemas.d.ts +45 -0
  156. package/dist/pricing/catalogFactsSchemas.js +58 -0
  157. package/dist/pricing/commerceOfferPricing.d.ts +25 -0
  158. package/dist/pricing/commerceOfferPricing.js +139 -0
  159. package/dist/pricing/commerceOfferPricingCache.d.ts +10 -0
  160. package/dist/pricing/commerceOfferPricingCache.js +44 -0
  161. package/dist/pricing/commerceOfferPricingHandler.d.ts +21 -0
  162. package/dist/pricing/commerceOfferPricingHandler.js +78 -0
  163. package/dist/pricing/commercePriceAuthority.d.ts +26 -0
  164. package/dist/pricing/commercePriceAuthority.js +79 -0
  165. package/dist/pricing/commercePricingPolicyErrors.d.ts +40 -0
  166. package/dist/pricing/commercePricingPolicyErrors.js +67 -0
  167. package/dist/pricing/commerceQuoteBatchHandler.d.ts +37 -0
  168. package/dist/pricing/commerceQuoteBatchHandler.js +83 -0
  169. package/dist/pricing/commerceQuoteCatalogReadPort.d.ts +27 -0
  170. package/dist/pricing/commerceQuoteCatalogReadPort.js +8 -0
  171. package/dist/pricing/commerceQuoteHandler.d.ts +31 -0
  172. package/dist/pricing/commerceQuoteHandler.js +110 -0
  173. package/dist/pricing/commerceQuoteSnapshotExpect.d.ts +9 -0
  174. package/dist/pricing/commerceQuoteSnapshotExpect.js +22 -0
  175. package/dist/pricing/contracts/acquisitionTerms.d.ts +32 -0
  176. package/dist/pricing/contracts/acquisitionTerms.js +2 -0
  177. package/dist/pricing/contracts/authority.d.ts +27 -0
  178. package/dist/pricing/contracts/authority.js +1 -0
  179. package/dist/pricing/contracts/evidence.d.ts +33 -0
  180. package/dist/pricing/contracts/evidence.js +1 -0
  181. package/dist/pricing/contracts/index.d.ts +17 -0
  182. package/dist/pricing/contracts/index.js +7 -0
  183. package/dist/pricing/contracts/money.d.ts +27 -0
  184. package/dist/pricing/contracts/money.js +1 -0
  185. package/dist/pricing/contracts/offer.d.ts +52 -0
  186. package/dist/pricing/contracts/offer.js +4 -0
  187. package/dist/pricing/contracts/offerPolicy.d.ts +16 -0
  188. package/dist/pricing/contracts/offerPolicy.js +5 -0
  189. package/dist/pricing/contracts/policy.d.ts +22 -0
  190. package/dist/pricing/contracts/policy.js +3 -0
  191. package/dist/pricing/contracts/provenance.d.ts +24 -0
  192. package/dist/pricing/contracts/provenance.js +2 -0
  193. package/dist/pricing/contracts/quote.d.ts +94 -0
  194. package/dist/pricing/contracts/quote.js +1 -0
  195. package/dist/pricing/dbBackedCommerceQuoteHelpers.d.ts +78 -0
  196. package/dist/pricing/dbBackedCommerceQuoteHelpers.js +146 -0
  197. package/dist/pricing/dbBackedCommerceQuotePort.d.ts +66 -0
  198. package/dist/pricing/dbBackedCommerceQuotePort.js +206 -0
  199. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
  200. package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
  201. package/dist/pricing/index.d.ts +51 -0
  202. package/dist/pricing/index.js +36 -0
  203. package/dist/pricing/offerPolicyReadiness.d.ts +21 -0
  204. package/dist/pricing/offerPolicyReadiness.js +79 -0
  205. package/dist/pricing/offerPolicySchemas.d.ts +25 -0
  206. package/dist/pricing/offerPolicySchemas.js +15 -0
  207. package/dist/pricing/offerPricingSchemas.d.ts +315 -0
  208. package/dist/pricing/offerPricingSchemas.js +65 -0
  209. package/dist/pricing/ports.d.ts +13 -0
  210. package/dist/pricing/ports.js +9 -0
  211. package/dist/pricing/pricingPolicyToken.d.ts +39 -0
  212. package/dist/pricing/pricingPolicyToken.js +84 -0
  213. package/dist/pricing/quoteAcquisitionTerms.d.ts +2 -0
  214. package/dist/pricing/quoteAcquisitionTerms.js +4 -0
  215. package/dist/pricing/quoteCodeRejectionDetails.d.ts +20 -0
  216. package/dist/pricing/quoteCodeRejectionDetails.js +22 -0
  217. package/dist/pricing/quotePorts.d.ts +30 -0
  218. package/dist/pricing/quotePorts.js +20 -0
  219. package/dist/pricing/quotePrimitives.d.ts +13 -0
  220. package/dist/pricing/quotePrimitives.js +18 -0
  221. package/dist/pricing/quotePromotionEvidence.d.ts +39 -0
  222. package/dist/pricing/quotePromotionEvidence.js +73 -0
  223. package/dist/pricing/quoteSchemas.d.ts +1176 -0
  224. package/dist/pricing/quoteSchemas.js +196 -0
  225. package/dist/pricing/subscriptionPricePolicy.d.ts +52 -0
  226. package/dist/pricing/subscriptionPricePolicy.js +96 -0
  227. package/dist/pricing/taxProfileGuard.d.ts +2 -0
  228. package/dist/pricing/taxProfileGuard.js +24 -0
  229. package/dist/pricing/validation.d.ts +2 -0
  230. package/dist/pricing/validation.js +3 -0
  231. package/dist/promotions/adminBindings.d.ts +72 -0
  232. package/dist/promotions/adminBindings.js +1 -0
  233. package/dist/promotions/adminPromotionCodesContracts.d.ts +498 -0
  234. package/dist/promotions/adminPromotionCodesContracts.js +211 -0
  235. package/dist/promotions/adminPromotionCodesDataPort.d.ts +47 -0
  236. package/dist/promotions/adminPromotionCodesDataPort.js +1 -0
  237. package/dist/promotions/adminPromotionCodesHandler.d.ts +14 -0
  238. package/dist/promotions/adminPromotionCodesHandler.js +194 -0
  239. package/dist/promotions/adminPromotionsContracts.d.ts +235 -0
  240. package/dist/promotions/adminPromotionsContracts.js +99 -0
  241. package/dist/promotions/adminPromotionsDataPort.d.ts +42 -0
  242. package/dist/promotions/adminPromotionsDataPort.js +1 -0
  243. package/dist/promotions/adminPromotionsHandler.d.ts +16 -0
  244. package/dist/promotions/adminPromotionsHandler.js +47 -0
  245. package/dist/promotions/contracts/index.d.ts +387 -0
  246. package/dist/promotions/contracts/index.js +1 -0
  247. package/dist/promotions/index.d.ts +22 -0
  248. package/dist/promotions/index.js +21 -0
  249. package/dist/promotions/promoDataPort.d.ts +47 -0
  250. package/dist/promotions/promoDataPort.js +14 -0
  251. package/dist/promotions/promotionAcceptanceTelemetry.d.ts +29 -0
  252. package/dist/promotions/promotionAcceptanceTelemetry.js +45 -0
  253. package/dist/promotions/promotionBenefitDefinition.d.ts +37 -0
  254. package/dist/promotions/promotionBenefitDefinition.js +33 -0
  255. package/dist/promotions/promotionClaimSweepPort.d.ts +14 -0
  256. package/dist/promotions/promotionClaimSweepPort.js +8 -0
  257. package/dist/promotions/promotionClaims.d.ts +5 -0
  258. package/dist/promotions/promotionClaims.js +57 -0
  259. package/dist/promotions/promotionCodePreview.d.ts +11 -0
  260. package/dist/promotions/promotionCodePreview.js +154 -0
  261. package/dist/promotions/promotionCodeQuotePort.d.ts +25 -0
  262. package/dist/promotions/promotionCodeQuotePort.js +1 -0
  263. package/dist/promotions/promotionQuoteAcceptance.d.ts +65 -0
  264. package/dist/promotions/promotionQuoteAcceptance.js +202 -0
  265. package/dist/promotions/promotionQuoteBinding.d.ts +71 -0
  266. package/dist/promotions/promotionQuoteBinding.js +85 -0
  267. package/dist/promotions/quoteAutomaticPromotions.d.ts +24 -0
  268. package/dist/promotions/quoteAutomaticPromotions.js +36 -0
  269. package/dist/promotions/quotePromoDiscounts.d.ts +32 -0
  270. package/dist/promotions/quotePromoDiscounts.js +140 -0
  271. package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
  272. package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
  273. package/dist/promotions/quotePromotionV2.d.ts +29 -0
  274. package/dist/promotions/quotePromotionV2.js +174 -0
  275. package/dist/promotions/sql.d.ts +14 -0
  276. package/dist/promotions/sql.js +5 -0
  277. package/dist/promotions/validation.d.ts +2 -0
  278. package/dist/promotions/validation.js +3 -0
  279. package/dist/shipping/addressCanonLookupHandler.d.ts +7 -0
  280. package/dist/shipping/addressCanonLookupHandler.js +105 -0
  281. package/dist/shipping/addressCanonical.d.ts +2 -0
  282. package/dist/shipping/addressCanonical.js +26 -0
  283. package/dist/shipping/addressPorts.d.ts +39 -0
  284. package/dist/shipping/addressPorts.js +1 -0
  285. package/dist/shipping/addressSchemas.d.ts +30 -0
  286. package/dist/shipping/addressSchemas.js +1 -0
  287. package/dist/shipping/adminShippingRateHandler.d.ts +4 -0
  288. package/dist/shipping/adminShippingRateHandler.js +64 -0
  289. package/dist/shipping/contracts/address.d.ts +144 -0
  290. package/dist/shipping/contracts/address.js +1 -0
  291. package/dist/shipping/contracts/delivery.d.ts +110 -0
  292. package/dist/shipping/contracts/delivery.js +1 -0
  293. package/dist/shipping/contracts/index.d.ts +3 -0
  294. package/dist/shipping/contracts/index.js +1 -0
  295. package/dist/shipping/contracts/shippingRate.d.ts +11 -0
  296. package/dist/shipping/contracts/shippingRate.js +1 -0
  297. package/dist/shipping/customerAddressesHandler.d.ts +5 -0
  298. package/dist/shipping/customerAddressesHandler.js +80 -0
  299. package/dist/shipping/customerSelfServiceAddressModels.d.ts +27 -0
  300. package/dist/shipping/customerSelfServiceAddressModels.js +101 -0
  301. package/dist/shipping/deliverySelectionHandler.d.ts +10 -0
  302. package/dist/shipping/deliverySelectionHandler.js +77 -0
  303. package/dist/shipping/deliverySelectionPort.d.ts +8 -0
  304. package/dist/shipping/deliverySelectionPort.js +1 -0
  305. package/dist/shipping/deliverySelectionSummary.d.ts +2 -0
  306. package/dist/shipping/deliverySelectionSummary.js +53 -0
  307. package/dist/shipping/handlerSchemas.d.ts +21 -0
  308. package/dist/shipping/handlerSchemas.js +1 -0
  309. package/dist/shipping/index.d.ts +17 -0
  310. package/dist/shipping/index.js +8 -0
  311. package/dist/shipping/pickupPointSearchPort.d.ts +4 -0
  312. package/dist/shipping/pickupPointSearchPort.js +1 -0
  313. package/dist/shipping/readDeliverySelectionEvidence.d.ts +2 -0
  314. package/dist/shipping/readDeliverySelectionEvidence.js +44 -0
  315. package/dist/shipping/shippingRatePorts.d.ts +52 -0
  316. package/dist/shipping/shippingRatePorts.js +1 -0
  317. package/package.json +62 -2
  318. package/release-gates.json +218 -10
  319. package/sql/20260807140000_read_parity_catalog.sql +94 -0
  320. package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
  321. package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
  322. package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
  323. package/sql/20260814000000_fulfillment_stock_evidence.sql +239 -0
  324. package/sql/20260815120000_automatic_subscription_renewal.sql +1083 -0
  325. package/sql/20260817180000_promotion_claim_lifecycle.sql +591 -0
  326. package/sql/20260817180100_promotion_claim_lifecycle_validation.sql +23 -0
  327. package/sql/20260827220000_catalog_document_revision_foundation.sql +226 -0
  328. package/sql/20260827220001_catalog_document_revision_foundation_validate.sql +10 -0
  329. package/sql/20260908100000_catalog_draft_foundation.sql +217 -0
  330. package/src/catalog/activeSkuSelection.ts +20 -0
  331. package/src/catalog/adminBindings.ts +59 -0
  332. package/src/catalog/adminBundleHandler.ts +165 -0
  333. package/src/catalog/adminBundleReadHandler.ts +261 -0
  334. package/src/catalog/adminBundleWritePort.ts +102 -0
  335. package/src/catalog/bundleAvailability.ts +129 -0
  336. package/src/catalog/bundleAvailabilityService.ts +171 -0
  337. package/src/catalog/bundleBindings.ts +29 -0
  338. package/src/catalog/bundleCatalogQueries.ts +98 -0
  339. package/src/catalog/bundleCatalogReadPort.ts +177 -0
  340. package/src/catalog/bundleCatalogStore.ts +269 -0
  341. package/src/catalog/bundleRuleCodes.ts +134 -0
  342. package/src/catalog/bundleRules.ts +153 -0
  343. package/src/catalog/catalogDraftStore.ts +71 -0
  344. package/src/catalog/catalogSkuEnvelope.ts +214 -0
  345. package/src/catalog/catalogSkuEnvelopeMapper.ts +160 -0
  346. package/src/catalog/contracts/bundleAdmin.ts +20 -0
  347. package/src/catalog/contracts/bundleAvailability.ts +5 -0
  348. package/src/catalog/contracts/bundleRead.ts +13 -0
  349. package/src/catalog/contracts/draft.ts +69 -0
  350. package/src/catalog/contracts/foundation.ts +104 -0
  351. package/src/catalog/contracts/index.ts +14 -0
  352. package/src/catalog/contracts/lifecycle.ts +74 -0
  353. package/src/catalog/contracts/productMediaContracts.ts +170 -0
  354. package/src/catalog/contracts/productTypes.ts +35 -0
  355. package/src/catalog/contracts/resolveProductMedia.ts +85 -0
  356. package/src/catalog/contracts/sellable.ts +12 -0
  357. package/src/catalog/draftHandler.ts +105 -0
  358. package/src/catalog/draftPorts.ts +18 -0
  359. package/src/catalog/draftSchemas.ts +88 -0
  360. package/src/catalog/draftValidation.ts +100 -0
  361. package/src/catalog/foundationSchemas.ts +123 -0
  362. package/src/catalog/index.ts +43 -0
  363. package/src/catalog/mediaSourcePack.ts +219 -0
  364. package/src/catalog/productTypeSchemas.ts +70 -0
  365. package/src/catalog/publicationPorts.ts +44 -0
  366. package/src/catalog/readPorts.ts +61 -0
  367. package/src/catalog/referenceCatalogHandler.ts +39 -0
  368. package/src/catalog/resolvedSkuProjection.ts +76 -0
  369. package/src/catalog/sellableBundleHandler.ts +133 -0
  370. package/src/catalog/sellableSchemas.ts +33 -0
  371. package/src/catalog/sql.ts +14 -0
  372. package/src/catalog/validation.ts +3 -0
  373. package/src/communications/contracts/index.ts +1 -0
  374. package/src/communications/contracts/marketingSync.ts +109 -0
  375. package/src/communications/index.ts +1 -0
  376. package/src/communications/klaviyo/consentPush.ts +19 -0
  377. package/src/communications/klaviyo/index.ts +649 -0
  378. package/src/communications/resend/index.ts +350 -0
  379. package/src/composition/catalogContribution.ts +32 -0
  380. package/src/composition/index.ts +1 -0
  381. package/src/inventory/adminInventory.ts +251 -0
  382. package/src/inventory/contracts/forecast.ts +96 -0
  383. package/src/inventory/contracts/index.ts +18 -0
  384. package/src/inventory/contracts/inventory.ts +14 -0
  385. package/src/inventory/contracts/newPurchaseStock.ts +23 -0
  386. package/src/inventory/contracts/reservation.ts +20 -0
  387. package/src/inventory/forecast.ts +239 -0
  388. package/src/inventory/index.ts +21 -0
  389. package/src/inventory/inventoryHandlers.ts +215 -0
  390. package/src/inventory/newPurchaseStockAvailability.ts +120 -0
  391. package/src/inventory/ports.ts +46 -0
  392. package/src/inventory/renewalReservation.ts +88 -0
  393. package/src/inventory/reservationPolicy.ts +27 -0
  394. package/src/inventory/schemas.ts +128 -0
  395. package/src/inventory/sql.ts +5 -0
  396. package/src/inventory/subscriptionForecastCalculation.ts +157 -0
  397. package/src/pricing/acquisitionFinancialPolicy.ts +26 -0
  398. package/src/pricing/acquisitionOfferPricing.ts +38 -0
  399. package/src/pricing/acquisitionOfferPricingHandler.ts +157 -0
  400. package/src/pricing/acquisitionOfferPricingSchemas.ts +35 -0
  401. package/src/pricing/acquisitionQuoteBinding.ts +12 -0
  402. package/src/pricing/acquisitionReadiness.ts +148 -0
  403. package/src/pricing/acquisitionTerms.ts +125 -0
  404. package/src/pricing/acquisitionTermsSchemas.ts +52 -0
  405. package/src/pricing/catalogFactsProvenance.ts +102 -0
  406. package/src/pricing/catalogFactsSchemas.ts +69 -0
  407. package/src/pricing/commerceOfferPricing.ts +224 -0
  408. package/src/pricing/commerceOfferPricingCache.ts +53 -0
  409. package/src/pricing/commerceOfferPricingHandler.ts +137 -0
  410. package/src/pricing/commercePriceAuthority.ts +104 -0
  411. package/src/pricing/commercePricingPolicyErrors.ts +88 -0
  412. package/src/pricing/commerceQuoteBatchHandler.ts +129 -0
  413. package/src/pricing/commerceQuoteCatalogReadPort.ts +42 -0
  414. package/src/pricing/commerceQuoteHandler.ts +184 -0
  415. package/src/pricing/commerceQuoteSnapshotExpect.ts +48 -0
  416. package/src/pricing/contracts/acquisitionTerms.ts +26 -0
  417. package/src/pricing/contracts/authority.ts +44 -0
  418. package/src/pricing/contracts/evidence.ts +25 -0
  419. package/src/pricing/contracts/index.ts +17 -0
  420. package/src/pricing/contracts/money.ts +32 -0
  421. package/src/pricing/contracts/offer.ts +42 -0
  422. package/src/pricing/contracts/offerPolicy.ts +17 -0
  423. package/src/pricing/contracts/policy.ts +26 -0
  424. package/src/pricing/contracts/provenance.ts +19 -0
  425. package/src/pricing/contracts/quote.ts +106 -0
  426. package/src/pricing/dbBackedCommerceQuoteHelpers.ts +256 -0
  427. package/src/pricing/dbBackedCommerceQuotePort.ts +260 -0
  428. package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
  429. package/src/pricing/index.ts +52 -0
  430. package/src/pricing/offerPolicyReadiness.ts +110 -0
  431. package/src/pricing/offerPolicySchemas.ts +23 -0
  432. package/src/pricing/offerPricingSchemas.ts +92 -0
  433. package/src/pricing/ports.ts +17 -0
  434. package/src/pricing/pricingPolicyToken.ts +119 -0
  435. package/src/pricing/quoteAcquisitionTerms.ts +10 -0
  436. package/src/pricing/quoteCodeRejectionDetails.ts +23 -0
  437. package/src/pricing/quotePorts.ts +58 -0
  438. package/src/pricing/quotePrimitives.ts +21 -0
  439. package/src/pricing/quotePromotionEvidence.ts +82 -0
  440. package/src/pricing/quoteSchemas.ts +230 -0
  441. package/src/pricing/subscriptionPricePolicy.ts +113 -0
  442. package/src/pricing/taxProfileGuard.ts +33 -0
  443. package/src/pricing/validation.ts +3 -0
  444. package/src/promotions/adminBindings.ts +53 -0
  445. package/src/promotions/adminPromotionCodesContracts.ts +244 -0
  446. package/src/promotions/adminPromotionCodesDataPort.ts +56 -0
  447. package/src/promotions/adminPromotionCodesHandler.ts +254 -0
  448. package/src/promotions/adminPromotionsContracts.ts +121 -0
  449. package/src/promotions/adminPromotionsDataPort.ts +48 -0
  450. package/src/promotions/adminPromotionsHandler.ts +72 -0
  451. package/src/promotions/contracts/index.ts +387 -0
  452. package/src/promotions/index.ts +22 -0
  453. package/src/promotions/promoDataPort.ts +65 -0
  454. package/src/promotions/promotionAcceptanceTelemetry.ts +73 -0
  455. package/src/promotions/promotionBenefitDefinition.ts +48 -0
  456. package/src/promotions/promotionClaimSweepPort.ts +23 -0
  457. package/src/promotions/promotionClaims.ts +70 -0
  458. package/src/promotions/promotionCodePreview.ts +183 -0
  459. package/src/promotions/promotionCodeQuotePort.ts +35 -0
  460. package/src/promotions/promotionQuoteAcceptance.ts +284 -0
  461. package/src/promotions/promotionQuoteBinding.ts +158 -0
  462. package/src/promotions/quoteAutomaticPromotions.ts +58 -0
  463. package/src/promotions/quotePromoDiscounts.ts +185 -0
  464. package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
  465. package/src/promotions/quotePromotionV2.ts +223 -0
  466. package/src/promotions/sql.ts +5 -0
  467. package/src/promotions/validation.ts +3 -0
  468. package/src/shipping/addressCanonLookupHandler.ts +114 -0
  469. package/src/shipping/addressCanonical.ts +31 -0
  470. package/src/shipping/addressPorts.ts +48 -0
  471. package/src/shipping/addressSchemas.ts +28 -0
  472. package/src/shipping/adminShippingRateHandler.ts +72 -0
  473. package/src/shipping/contracts/address.ts +71 -0
  474. package/src/shipping/contracts/delivery.ts +114 -0
  475. package/src/shipping/contracts/index.ts +18 -0
  476. package/src/shipping/contracts/shippingRate.ts +7 -0
  477. package/src/shipping/customerAddressesHandler.ts +100 -0
  478. package/src/shipping/customerSelfServiceAddressModels.ts +124 -0
  479. package/src/shipping/deliverySelectionHandler.ts +94 -0
  480. package/src/shipping/deliverySelectionPort.ts +10 -0
  481. package/src/shipping/deliverySelectionSummary.ts +56 -0
  482. package/src/shipping/handlerSchemas.ts +19 -0
  483. package/src/shipping/index.ts +23 -0
  484. package/src/shipping/pickupPointSearchPort.ts +8 -0
  485. package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
  486. package/src/shipping/shippingRatePorts.ts +36 -0
@@ -21,8 +21,8 @@ export declare const newsletterSyncEventTypeSchema: z.ZodEnum<{
21
21
  suppress: "suppress";
22
22
  }>;
23
23
  export declare const newsletterWebhookEventTypeSchema: z.ZodEnum<{
24
- email_change: "email_change";
25
24
  update: "update";
25
+ email_change: "email_change";
26
26
  subscribe: "subscribe";
27
27
  unsubscribe: "unsubscribe";
28
28
  suppress: "suppress";
@@ -46,8 +46,8 @@ export declare const canonicalNewsletterWebhookEventSchema: z.ZodObject<{
46
46
  providerKind: z.ZodString;
47
47
  providerEventId: z.ZodString;
48
48
  eventType: z.ZodEnum<{
49
- email_change: "email_change";
50
49
  update: "update";
50
+ email_change: "email_change";
51
51
  subscribe: "subscribe";
52
52
  unsubscribe: "unsubscribe";
53
53
  suppress: "suppress";
@@ -85,8 +85,8 @@ export declare function createNewsletterIntegrationSchemas<Purpose extends strin
85
85
  providerKind: z.ZodString;
86
86
  providerEventId: z.ZodString;
87
87
  eventType: z.ZodEnum<{
88
- email_change: "email_change";
89
88
  update: "update";
89
+ email_change: "email_change";
90
90
  subscribe: "subscribe";
91
91
  unsubscribe: "unsubscribe";
92
92
  suppress: "suppress";
@@ -0,0 +1,40 @@
1
+ import { type EmailEgressPolicy } from "../emailEgress.js";
2
+ import type { EmailTransport } from "../emailTransport.js";
3
+ import { type EmailObservationPort } from "../emailObservation.js";
4
+ import { type DeliveryReconciliationPort, type DeliveryReconciliationResult } from "../deliveryReconciliation.js";
5
+ /** Opt-in Node sender. Every send obtains a fresh validated host egress decision. */
6
+ export declare function createResendTransport(input: {
7
+ policy: EmailEgressPolicy;
8
+ environmentTagName: string;
9
+ fetch?: typeof fetch;
10
+ }): EmailTransport;
11
+ /** Poll existing IDs through the neutral runner; never retries a send. */
12
+ export declare function runResendDeliveryReconciliation(input: {
13
+ port: DeliveryReconciliationPort;
14
+ now: string;
15
+ graceMinutes: number;
16
+ limit: number;
17
+ apiKey: string;
18
+ fetch?: typeof fetch;
19
+ signal?: AbortSignal;
20
+ }): Promise<DeliveryReconciliationResult>;
21
+ /** Authenticate untouched bytes before decoding. now returns UTC seconds; receiver defaults to non-production. */
22
+ export declare function createResendWebhookHandler(input: {
23
+ port: EmailObservationPort;
24
+ webhookSecret: string;
25
+ environmentTagName: string;
26
+ resolveReceiverEnvironmentTag?: () => "production" | "non_production";
27
+ now?: () => number;
28
+ receivedAt?: () => Date;
29
+ }): (request: {
30
+ method?: string;
31
+ rawBody: string | Uint8Array;
32
+ headers: {
33
+ webhookId?: string;
34
+ timestamp?: string;
35
+ signature?: string;
36
+ };
37
+ }) => Promise<{
38
+ status: number;
39
+ body: Record<string, unknown> | "ok";
40
+ }>;
@@ -0,0 +1,310 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ import { createGuardedEmailTransport } from "../emailEgress.js";
3
+ import { processEmailObservation } from "../emailObservation.js";
4
+ import { runDeliveryReconciliation } from "../deliveryReconciliation.js";
5
+ /** Opt-in Node sender. Every send obtains a fresh validated host egress decision. */
6
+ export function createResendTransport(input) {
7
+ return createGuardedEmailTransport({
8
+ providerKind: "resend",
9
+ policy: input.policy,
10
+ send: (message, context) => postResendEmail(message, context, input.environmentTagName, input.fetch ?? fetch),
11
+ });
12
+ }
13
+ const RESEND_ENDPOINT = "https://api.resend.com/emails";
14
+ const PROVIDER_ERROR_MAX = 240;
15
+ const PROVIDER_ERROR_CODE_MAX = 80;
16
+ const EMAIL_ADDRESS_PATTERN = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi;
17
+ function truncate(value, max) {
18
+ return value.length > max ? `${value.slice(0, max - 1)}...` : value;
19
+ }
20
+ function sanitizeProviderText(value) {
21
+ return truncate(value.replace(EMAIL_ADDRESS_PATTERN, "[email]").replace(/\s+/g, " ").trim(), PROVIDER_ERROR_MAX);
22
+ }
23
+ function sanitizeProviderCode(value) {
24
+ return truncate(value.replace(/[^A-Za-z0-9._:-]/g, "_"), PROVIDER_ERROR_CODE_MAX);
25
+ }
26
+ function providerErrorFromBody(body, httpStatus) {
27
+ const errField = body.error;
28
+ if (typeof errField === "string")
29
+ return sanitizeProviderText(errField);
30
+ if (errField && typeof errField === "object") {
31
+ const message = errField.message;
32
+ if (typeof message === "string")
33
+ return sanitizeProviderText(message);
34
+ }
35
+ if (typeof body.message === "string")
36
+ return sanitizeProviderText(body.message);
37
+ return `Resend HTTP ${httpStatus}`;
38
+ }
39
+ function providerErrorCodeFromBody(body) {
40
+ const errField = body.error;
41
+ const errorRecord = errField && typeof errField === "object"
42
+ ? errField
43
+ : {};
44
+ const candidates = [
45
+ errorRecord.code,
46
+ errorRecord.name,
47
+ errorRecord.type,
48
+ body.code,
49
+ body.name,
50
+ body.type,
51
+ ];
52
+ const value = candidates.find((candidate) => typeof candidate === "string" && candidate.trim() !== "");
53
+ return typeof value === "string" ? sanitizeProviderCode(value) : null;
54
+ }
55
+ function providerErrorResponse(body, httpStatus) {
56
+ const providerErrorMessage = providerErrorFromBody(body, httpStatus);
57
+ const providerErrorCode = providerErrorCodeFromBody(body);
58
+ return {
59
+ http_status: httpStatus,
60
+ provider_error_message: providerErrorMessage,
61
+ ...(providerErrorCode ? { provider_error_code: providerErrorCode } : {}),
62
+ };
63
+ }
64
+ async function postResendEmail(input, context, environmentTagName, fetcher) {
65
+ const headers = {
66
+ Authorization: `Bearer ${context.credential}`,
67
+ "Content-Type": "application/json",
68
+ };
69
+ if (input.idempotencyKey !== undefined)
70
+ headers["Idempotency-Key"] = input.idempotencyKey;
71
+ if (context.mode === "sandbox_sink")
72
+ headers["X-Original-Recipient"] = context.intendedRecipient;
73
+ try {
74
+ const res = await fetcher(RESEND_ENDPOINT, {
75
+ method: "POST",
76
+ headers,
77
+ body: JSON.stringify({
78
+ from: input.from,
79
+ to: [context.recipient],
80
+ subject: input.subject,
81
+ html: input.html,
82
+ ...(input.text === undefined ? {} : { text: input.text }),
83
+ ...(input.replyTo === undefined ? {} : { reply_to: input.replyTo }),
84
+ ...(input.attachments === undefined ? {} : { attachments: input.attachments }),
85
+ tags: [{
86
+ name: environmentTagName,
87
+ value: context.environmentTag,
88
+ }],
89
+ }),
90
+ signal: input.signal,
91
+ });
92
+ const parsed = await res.json().catch(() => ({}));
93
+ const body = typeof parsed === "object" && parsed !== null
94
+ ? parsed
95
+ : {};
96
+ if (!res.ok) {
97
+ const providerErrorMessage = providerErrorFromBody(body, res.status);
98
+ const providerErrorCode = providerErrorCodeFromBody(body);
99
+ return {
100
+ outcome: {
101
+ ok: false,
102
+ resendId: null,
103
+ httpStatus: res.status,
104
+ providerError: providerErrorMessage,
105
+ providerErrorCode,
106
+ aborted: false,
107
+ egressMode: context.mode,
108
+ egressReason: context.reason,
109
+ },
110
+ providerResponse: providerErrorResponse(body, res.status),
111
+ };
112
+ }
113
+ const id = typeof body.id === "string" ? body.id : null;
114
+ return {
115
+ outcome: {
116
+ ok: true,
117
+ resendId: id,
118
+ httpStatus: res.status,
119
+ providerError: null,
120
+ aborted: false,
121
+ egressMode: context.mode,
122
+ egressReason: context.reason,
123
+ },
124
+ providerResponse: { id },
125
+ };
126
+ }
127
+ catch (err) {
128
+ const aborted = input.signal?.aborted === true ||
129
+ (err instanceof Error && err.name === "AbortError");
130
+ const msg = err instanceof Error ? err.message : String(err);
131
+ return {
132
+ outcome: {
133
+ ok: false,
134
+ resendId: null,
135
+ httpStatus: 0,
136
+ providerError: sanitizeProviderText(msg),
137
+ aborted,
138
+ egressMode: context.mode,
139
+ egressReason: context.reason,
140
+ },
141
+ providerResponse: { exception: true, aborted },
142
+ };
143
+ }
144
+ }
145
+ function readFirstRecipient(value) {
146
+ if (typeof value === "string" && value.includes("@"))
147
+ return value;
148
+ if (!Array.isArray(value))
149
+ return null;
150
+ return value.find((recipient) => typeof recipient === "string" && recipient.includes("@")) ?? null;
151
+ }
152
+ // Read-only status retrieval for the delivery reconciliation poller
153
+ // (docs/platform/RUNTIME_AND_SELF_HOSTING.md Wave 4). No egress gating needed: this never
154
+ // sends mail — it only reads the provider's view of an already-sent message.
155
+ async function getResendEmail(input, fetcher) {
156
+ try {
157
+ const res = await fetcher(`${RESEND_ENDPOINT}/${encodeURIComponent(input.resendId)}`, {
158
+ method: "GET",
159
+ headers: { Authorization: `Bearer ${input.apiKey}` },
160
+ signal: input.signal,
161
+ });
162
+ const parsed = (await res.json().catch(() => ({})));
163
+ if (!res.ok) {
164
+ return {
165
+ ok: false,
166
+ httpStatus: res.status,
167
+ lastEvent: null,
168
+ recipientEmail: null,
169
+ providerError: providerErrorFromBody(parsed, res.status),
170
+ };
171
+ }
172
+ const lastEvent = typeof parsed.last_event === "string" ? parsed.last_event : null;
173
+ return {
174
+ ok: true,
175
+ httpStatus: res.status,
176
+ lastEvent,
177
+ recipientEmail: readFirstRecipient(parsed.to),
178
+ providerError: null,
179
+ };
180
+ }
181
+ catch (error) {
182
+ return {
183
+ ok: false,
184
+ httpStatus: 0,
185
+ lastEvent: null,
186
+ recipientEmail: null,
187
+ providerError: error instanceof Error ? sanitizeProviderCode(error.message) : "fetch_failed",
188
+ };
189
+ }
190
+ }
191
+ /** Poll existing IDs through the neutral runner; never retries a send. */
192
+ export function runResendDeliveryReconciliation(input) {
193
+ return runDeliveryReconciliation({
194
+ port: input.port, now: input.now, graceMinutes: input.graceMinutes, limit: input.limit,
195
+ readEmail: messageId => getResendEmail({ apiKey: input.apiKey, resendId: messageId, signal: input.signal }, input.fetch ?? fetch),
196
+ observationFor: read => {
197
+ const status = read.lastEvent;
198
+ if (!status || !["delivered", "delivery_delayed", "bounced", "complained", "failed"].includes(status))
199
+ return null;
200
+ return { eventType: `email.${status}`, terminal: ["bounced", "complained", "failed"].includes(status) };
201
+ },
202
+ });
203
+ }
204
+ const eventKinds = new Map([
205
+ ["email.sent", "sent"], ["email.delivered", "delivered"], ["email.delivery_delayed", "delivery_delayed"],
206
+ ["email.opened", "open"], ["email.clicked", "click"], ["email.bounced", "bounce"],
207
+ ["email.complained", "complaint"], ["email.failed", "failed"], ["email.suppressed", "suppressed"], ["email.scheduled", "scheduled"],
208
+ ]);
209
+ /** Authenticate untouched bytes before decoding. now returns UTC seconds; receiver defaults to non-production. */
210
+ export function createResendWebhookHandler(input) {
211
+ return async (request) => {
212
+ if (request.method === "OPTIONS")
213
+ return { status: 200, body: "ok" };
214
+ if (!verifyResendWebhookSignature({ ...request.headers, rawBody: request.rawBody, secret: input.webhookSecret, now: input.now })) {
215
+ return { status: 401, body: { error: "Invalid signature" } };
216
+ }
217
+ try {
218
+ const payload = JSON.parse(typeof request.rawBody === "string" ? request.rawBody : Buffer.from(request.rawBody).toString("utf8"));
219
+ const type = isRecord(payload) ? payload.type : null;
220
+ const data = isRecord(payload) ? payload.data : null;
221
+ if (typeof type !== "string" || !eventKinds.has(type))
222
+ return { status: 200, body: { ignored: true } };
223
+ const messageId = isRecord(data) && typeof data.email_id === "string" ? data.email_id : null;
224
+ if (!messageId)
225
+ return { status: 200, body: { ignored: true, reason: "missing_email_id" } };
226
+ const tag = readEnvironmentTag(data, input.environmentTagName);
227
+ if (tag && tag !== (input.resolveReceiverEnvironmentTag?.() ?? "non_production")) {
228
+ return { status: 200, body: { ignored: true, reason: "foreign_send_not_found" } };
229
+ }
230
+ const disposition = await processEmailObservation({
231
+ port: input.port, messageId,
232
+ observation: () => {
233
+ const time = resolveEventTime(isRecord(payload) ? payload.created_at : null, request.headers.timestamp, input.receivedAt?.() ?? new Date());
234
+ return { eventType: type, eventAt: time.eventAt, metadata: {
235
+ providerEventId: request.headers.webhookId ?? null, eventMetadata: data ?? {},
236
+ link: isRecord(data) && isRecord(data.click) && typeof data.click.link === "string" ? data.click.link : null,
237
+ source: "resend-webhook", eventTimeSource: time.source,
238
+ } };
239
+ },
240
+ });
241
+ return disposition.outcome === "send_not_found"
242
+ ? { status: 200, body: { ignored: true, reason: "send_not_found" } }
243
+ : { status: 200, body: { success: true } };
244
+ }
245
+ catch {
246
+ return { status: 500, body: { error: "Webhook processing failed" } };
247
+ }
248
+ };
249
+ }
250
+ function isRecord(value) {
251
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
252
+ }
253
+ function readEnvironmentTag(data, tagName) {
254
+ if (!isRecord(data))
255
+ return null;
256
+ const tags = data.tags;
257
+ const value = Array.isArray(tags)
258
+ ? tags.find(entry => isRecord(entry) && entry.name === tagName)?.value
259
+ : isRecord(tags) ? tags[tagName] : null;
260
+ return value === "production" || value === "non_production" ? value : null;
261
+ }
262
+ function resolveEventTime(createdAt, timestamp, receivedAt) {
263
+ if (typeof createdAt === "string" && Number.isFinite(Date.parse(createdAt))) {
264
+ return { eventAt: new Date(createdAt).toISOString(), source: "provider_created_at" };
265
+ }
266
+ const seconds = Number(timestamp);
267
+ if (Number.isFinite(seconds) && seconds > 0)
268
+ return { eventAt: new Date(seconds * 1000).toISOString(), source: "svix_timestamp" };
269
+ return { eventAt: receivedAt.toISOString(), source: "received_at" };
270
+ }
271
+ function verifyResendWebhookSignature(input) {
272
+ const { webhookId, timestamp, signature, rawBody, secret } = input;
273
+ if (!webhookId || !timestamp || !signature || !secret)
274
+ return false;
275
+ const timestampSeconds = Number(timestamp);
276
+ if (!Number.isFinite(timestampSeconds))
277
+ return false;
278
+ const now = input.now ?? (() => Math.floor(Date.now() / 1000));
279
+ if (Math.abs(now() - timestampSeconds) > 300)
280
+ return false;
281
+ const secretKey = signingSecret(secret);
282
+ if (secretKey === null)
283
+ return false;
284
+ const expected = createHmac("sha256", secretKey)
285
+ .update(`${webhookId}.${timestamp}.`).update(rawBody)
286
+ .digest("base64");
287
+ return signature.split(" ").some((member) => timingSafeStringEqual(member, `v1,${expected}`) || timingSafeStringEqual(member, expected));
288
+ }
289
+ function signingSecret(secret) {
290
+ if (!secret.startsWith("whsec_"))
291
+ return secret;
292
+ // Svix encodes endpoint secrets after the whsec_ prefix. Buffer preserves the
293
+ // decoded bytes for node:crypto rather than treating the base64 text as a key.
294
+ // Buffer.from(base64) is deliberately permissive, so reject empty, malformed,
295
+ // or non-canonical input before it can silently become an empty/partial key.
296
+ const encoded = secret.slice("whsec_".length);
297
+ if (!encoded || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded) || encoded.length % 4 === 1)
298
+ return null;
299
+ const decoded = Buffer.from(encoded, "base64");
300
+ if (decoded.length === 0)
301
+ return null;
302
+ const canonicalPadded = decoded.toString("base64");
303
+ const canonicalUnpadded = canonicalPadded.replace(/=+$/, "");
304
+ return encoded === canonicalPadded || encoded === canonicalUnpadded ? decoded : null;
305
+ }
306
+ function timingSafeStringEqual(left, right) {
307
+ const leftBuffer = Buffer.from(left);
308
+ const rightBuffer = Buffer.from(right);
309
+ return leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);
310
+ }
@@ -0,0 +1,18 @@
1
+ import type { Contribution, RequiredSchema } from "@openlup/core/readiness";
2
+ /** Actual selected callables, supplied by the host; declarations never activate them. */
3
+ export interface CatalogContributionInput {
4
+ version: string;
5
+ requiredSchema: RequiredSchema;
6
+ catalog: Readonly<Record<string, (...args: never[]) => unknown>>;
7
+ pricing: Readonly<Record<string, (...args: never[]) => unknown>>;
8
+ promotions: Readonly<Record<string, (...args: never[]) => unknown>>;
9
+ routes: Contribution["routes"];
10
+ }
11
+ /** Thin structural declarations under the existing logical module identities. */
12
+ export declare function createCatalogContribution(input: CatalogContributionInput): {
13
+ contributions: Contribution[];
14
+ ports: Record<string, unknown>;
15
+ routes: {
16
+ [k: string]: (...args: never[]) => unknown;
17
+ };
18
+ };
@@ -0,0 +1,21 @@
1
+ /** Thin structural declarations under the existing logical module identities. */
2
+ export function createCatalogContribution(input) {
3
+ const contributions = [];
4
+ const ports = {};
5
+ for (const module of ["catalog", "pricing", "promotions"]) {
6
+ const selected = input[module];
7
+ for (const [name, callable] of Object.entries(selected))
8
+ ports[`@openlup/platform/${module}:${name}`] = callable;
9
+ contributions.push({
10
+ manifest: {
11
+ name: "@openlup/platform", version: input.version, kind: "rail",
12
+ module: { id: module, kind: "capability", provides: [`./${module}`], dependsOn: [] },
13
+ emits: [], handles: [], schedules: [], env: [], requiredPorts: Object.keys(selected),
14
+ routes: module === "catalog" ? input.routes.map(route => route.id) : [],
15
+ ...(module === "catalog" ? { requiredSchema: input.requiredSchema } : {}),
16
+ },
17
+ handlers: [], schedules: [], routes: module === "catalog" ? input.routes : [],
18
+ });
19
+ }
20
+ return { contributions, ports, routes: Object.fromEntries(input.routes.map(route => [`@openlup/platform/catalog:${route.id}`, route.handle])) };
21
+ }
@@ -1,3 +1,4 @@
1
1
  export { createBundleComposer, type ComposeBundle, type PlatformBundle, type PlatformBundleBinders, type PlatformBundlePorts, } from "./composeBundle.js";
2
2
  export { bindNodeHttpPort, createScheduledEntrypointResolver } from "./httpBinding.js";
3
3
  export { createNodeHost, type NodeHost, type NodeHostAdmission, type NodeHostDependencies, type NodeSchedulerProfile, type ServeNodeOptions, type ServeNodeResult, } from "./nodeHost.js";
4
+ export { createCatalogContribution, type CatalogContributionInput } from "./catalogContribution.js";
@@ -1,3 +1,4 @@
1
1
  export { createBundleComposer, } from "./composeBundle.js";
2
2
  export { bindNodeHttpPort, createScheduledEntrypointResolver } from "./httpBinding.js";
3
3
  export { createNodeHost, } from "./nodeHost.js";
4
+ export { createCatalogContribution } from "./catalogContribution.js";
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
2
  export declare const customerLifecycleStageSchema: z.ZodEnum<{
3
+ inactive: "inactive";
3
4
  lead: "lead";
4
5
  tester: "tester";
5
6
  customer: "customer";
6
- inactive: "inactive";
7
7
  }>;
8
8
  export declare const customerMeRequestSchema: z.ZodObject<{}, z.core.$strict>;
9
9
  export declare const customerMeResponseSchema: z.ZodObject<{
@@ -12,10 +12,10 @@ export declare const customerMeResponseSchema: z.ZodObject<{
12
12
  firstName: z.ZodNullable<z.ZodString>;
13
13
  lastName: z.ZodNullable<z.ZodString>;
14
14
  lifecycleStage: z.ZodEnum<{
15
+ inactive: "inactive";
15
16
  lead: "lead";
16
17
  tester: "tester";
17
18
  customer: "customer";
18
- inactive: "inactive";
19
19
  }>;
20
20
  subscriptions: z.ZodOptional<z.ZodArray<z.ZodObject<{
21
21
  subscriptionId: z.ZodGUID;
@@ -0,0 +1,13 @@
1
+ import type { z } from "zod";
2
+ import { type InventoryMutationPort, type InventoryReadPort } from "./ports.js";
3
+ interface PgQueryExecutor {
4
+ query(text: string, values?: unknown[]): Promise<{
5
+ rows: Record<string, unknown>[];
6
+ }>;
7
+ }
8
+ /** Operator readback over the same public stock and reservation rail used by renewal. */
9
+ export declare function createPostgresAdminInventoryPort(executor: PgQueryExecutor, config: {
10
+ stockMasterProvider: string;
11
+ providerSchema: z.ZodType<string>;
12
+ }, now?: () => string): InventoryReadPort & InventoryMutationPort;
13
+ export {};