@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.
- package/CHANGELOG.md +180 -0
- package/README.md +564 -6
- package/dist/catalog/activeSkuSelection.d.ts +2 -0
- package/dist/catalog/activeSkuSelection.js +20 -0
- package/dist/catalog/adminBindings.d.ts +72 -0
- package/dist/catalog/adminBindings.js +1 -0
- package/dist/catalog/adminBundleHandler.d.ts +26 -0
- package/dist/catalog/adminBundleHandler.js +111 -0
- package/dist/catalog/adminBundleReadHandler.d.ts +20 -0
- package/dist/catalog/adminBundleReadHandler.js +185 -0
- package/dist/catalog/adminBundleWritePort.d.ts +85 -0
- package/dist/catalog/adminBundleWritePort.js +1 -0
- package/dist/catalog/bundleAvailability.d.ts +63 -0
- package/dist/catalog/bundleAvailability.js +78 -0
- package/dist/catalog/bundleAvailabilityService.d.ts +65 -0
- package/dist/catalog/bundleAvailabilityService.js +89 -0
- package/dist/catalog/bundleBindings.d.ts +33 -0
- package/dist/catalog/bundleBindings.js +1 -0
- package/dist/catalog/bundleCatalogQueries.d.ts +28 -0
- package/dist/catalog/bundleCatalogQueries.js +84 -0
- package/dist/catalog/bundleCatalogReadPort.d.ts +166 -0
- package/dist/catalog/bundleCatalogReadPort.js +36 -0
- package/dist/catalog/bundleCatalogStore.d.ts +3 -0
- package/dist/catalog/bundleCatalogStore.js +152 -0
- package/dist/catalog/bundleRuleCodes.d.ts +41 -0
- package/dist/catalog/bundleRuleCodes.js +110 -0
- package/dist/catalog/bundleRules.d.ts +69 -0
- package/dist/catalog/bundleRules.js +102 -0
- package/dist/catalog/catalogDraftStore.d.ts +4 -0
- package/dist/catalog/catalogDraftStore.js +63 -0
- package/dist/catalog/catalogSkuEnvelope.d.ts +7 -0
- package/dist/catalog/catalogSkuEnvelope.js +142 -0
- package/dist/catalog/catalogSkuEnvelopeMapper.d.ts +38 -0
- package/dist/catalog/catalogSkuEnvelopeMapper.js +88 -0
- package/dist/catalog/contracts/bundleAdmin.d.ts +143 -0
- package/dist/catalog/contracts/bundleAdmin.js +1 -0
- package/dist/catalog/contracts/bundleAvailability.d.ts +61 -0
- package/dist/catalog/contracts/bundleAvailability.js +1 -0
- package/dist/catalog/contracts/bundleRead.d.ts +223 -0
- package/dist/catalog/contracts/bundleRead.js +1 -0
- package/dist/catalog/contracts/draft.d.ts +79 -0
- package/dist/catalog/contracts/draft.js +47 -0
- package/dist/catalog/contracts/foundation.d.ts +78 -0
- package/dist/catalog/contracts/foundation.js +53 -0
- package/dist/catalog/contracts/index.d.ts +14 -0
- package/dist/catalog/contracts/index.js +6 -0
- package/dist/catalog/contracts/lifecycle.d.ts +77 -0
- package/dist/catalog/contracts/lifecycle.js +1 -0
- package/dist/catalog/contracts/productMediaContracts.d.ts +77 -0
- package/dist/catalog/contracts/productMediaContracts.js +149 -0
- package/dist/catalog/contracts/productTypes.d.ts +54 -0
- package/dist/catalog/contracts/productTypes.js +16 -0
- package/dist/catalog/contracts/resolveProductMedia.d.ts +3 -0
- package/dist/catalog/contracts/resolveProductMedia.js +78 -0
- package/dist/catalog/contracts/sellable.d.ts +23 -0
- package/dist/catalog/contracts/sellable.js +1 -0
- package/dist/catalog/draftHandler.d.ts +25 -0
- package/dist/catalog/draftHandler.js +118 -0
- package/dist/catalog/draftPorts.d.ts +18 -0
- package/dist/catalog/draftPorts.js +8 -0
- package/dist/catalog/draftSchemas.d.ts +423 -0
- package/dist/catalog/draftSchemas.js +89 -0
- package/dist/catalog/draftValidation.d.ts +21 -0
- package/dist/catalog/draftValidation.js +125 -0
- package/dist/catalog/foundationSchemas.d.ts +98 -0
- package/dist/catalog/foundationSchemas.js +110 -0
- package/dist/catalog/index.d.ts +43 -0
- package/dist/catalog/index.js +25 -0
- package/dist/catalog/mediaSourcePack.d.ts +51 -0
- package/dist/catalog/mediaSourcePack.js +247 -0
- package/dist/catalog/productTypeSchemas.d.ts +46 -0
- package/dist/catalog/productTypeSchemas.js +72 -0
- package/dist/catalog/publicationPorts.d.ts +42 -0
- package/dist/catalog/publicationPorts.js +1 -0
- package/dist/catalog/readPorts.d.ts +51 -0
- package/dist/catalog/readPorts.js +1 -0
- package/dist/catalog/referenceCatalogHandler.d.ts +7 -0
- package/dist/catalog/referenceCatalogHandler.js +27 -0
- package/dist/catalog/resolvedSkuProjection.d.ts +88 -0
- package/dist/catalog/resolvedSkuProjection.js +60 -0
- package/dist/catalog/sellableBundleHandler.d.ts +46 -0
- package/dist/catalog/sellableBundleHandler.js +84 -0
- package/dist/catalog/sellableSchemas.d.ts +46 -0
- package/dist/catalog/sellableSchemas.js +27 -0
- package/dist/catalog/sql.d.ts +46 -0
- package/dist/catalog/sql.js +13 -0
- package/dist/catalog/validation.d.ts +2 -0
- package/dist/catalog/validation.js +3 -0
- package/dist/communications/accountingDocumentDelivery.d.ts +35 -0
- package/dist/communications/accountingDocumentDelivery.js +33 -0
- package/dist/communications/authEmailError.d.ts +5 -0
- package/dist/communications/authEmailError.js +8 -0
- package/dist/communications/authEmailPorts.d.ts +2 -0
- package/dist/communications/authEmailPorts.js +1 -0
- package/dist/communications/authSendEmailHook.d.ts +35 -0
- package/dist/communications/authSendEmailHook.js +250 -0
- package/dist/communications/capturedTransactionalDelivery.d.ts +13 -0
- package/dist/communications/capturedTransactionalDelivery.js +14 -0
- package/dist/communications/communicationSync.d.ts +11 -0
- package/dist/communications/communicationSync.js +79 -0
- package/dist/communications/communicationSyncWorker.d.ts +68 -0
- package/dist/communications/communicationSyncWorker.js +218 -0
- package/dist/communications/consentPolicy.d.ts +19 -0
- package/dist/communications/consentPolicy.js +43 -0
- package/dist/communications/consentPurposeRegistry.d.ts +4 -0
- package/dist/communications/consentPurposeRegistry.js +24 -0
- package/dist/communications/contracts/abandonedCart.d.ts +27 -0
- package/dist/communications/contracts/abandonedCart.js +25 -0
- package/dist/communications/contracts/authEmail.d.ts +62 -0
- package/dist/communications/contracts/authEmail.js +1 -0
- package/dist/communications/contracts/backInStock.d.ts +28 -0
- package/dist/communications/contracts/backInStock.js +28 -0
- package/dist/communications/contracts/blocks.d.ts +24 -0
- package/dist/communications/contracts/blocks.js +23 -0
- package/dist/communications/contracts/checkoutExpired.d.ts +22 -0
- package/dist/communications/contracts/checkoutExpired.js +25 -0
- package/dist/communications/contracts/checkoutRecovery.d.ts +26 -0
- package/dist/communications/contracts/checkoutRecovery.js +37 -0
- package/dist/communications/contracts/commerceEmailContent.d.ts +176 -0
- package/dist/communications/contracts/commerceEmailContent.js +1 -0
- package/dist/communications/contracts/commerceEngagementEmailContent.d.ts +95 -0
- package/dist/communications/contracts/commerceEngagementEmailContent.js +1 -0
- package/dist/communications/contracts/consent.d.ts +12 -0
- package/dist/communications/contracts/consent.js +1 -0
- package/dist/communications/contracts/email.d.ts +182 -0
- package/dist/communications/contracts/email.js +1 -0
- package/dist/communications/contracts/guideCard.d.ts +3 -0
- package/dist/communications/contracts/guideCard.js +26 -0
- package/dist/communications/contracts/index.d.ts +52 -0
- package/dist/communications/contracts/index.js +42 -0
- package/dist/communications/contracts/inquiryContent.d.ts +32 -0
- package/dist/communications/contracts/inquiryContent.js +33 -0
- package/dist/communications/contracts/invoiceDocumentContent.d.ts +26 -0
- package/dist/communications/contracts/invoiceDocumentContent.js +36 -0
- package/dist/communications/contracts/marketingAutomation.d.ts +52 -0
- package/dist/communications/contracts/marketingAutomation.js +1 -0
- package/dist/communications/contracts/marketingSync.d.ts +194 -0
- package/dist/communications/contracts/marketingSync.js +1 -0
- package/dist/communications/contracts/newsletter.d.ts +63 -0
- package/dist/communications/contracts/newsletter.js +1 -0
- package/dist/communications/contracts/newsletterWebhook.d.ts +26 -0
- package/dist/communications/contracts/newsletterWebhook.js +1 -0
- package/dist/communications/contracts/optOutContent.d.ts +11 -0
- package/dist/communications/contracts/optOutContent.js +17 -0
- package/dist/communications/contracts/orderCanceled.d.ts +25 -0
- package/dist/communications/contracts/orderCanceled.js +27 -0
- package/dist/communications/contracts/orderDraft.d.ts +46 -0
- package/dist/communications/contracts/orderDraft.js +46 -0
- package/dist/communications/contracts/orderPaid.d.ts +53 -0
- package/dist/communications/contracts/orderPaid.js +71 -0
- package/dist/communications/contracts/orderRefunded.d.ts +24 -0
- package/dist/communications/contracts/orderRefunded.js +27 -0
- package/dist/communications/contracts/paymentFailed.d.ts +24 -0
- package/dist/communications/contracts/paymentFailed.js +24 -0
- package/dist/communications/contracts/publicIntake.d.ts +49 -0
- package/dist/communications/contracts/publicIntake.js +1 -0
- package/dist/communications/contracts/render.d.ts +2 -0
- package/dist/communications/contracts/render.js +229 -0
- package/dist/communications/contracts/reorderReminder.d.ts +24 -0
- package/dist/communications/contracts/reorderReminder.js +24 -0
- package/dist/communications/contracts/returnEmails.d.ts +25 -0
- package/dist/communications/contracts/returnEmails.js +62 -0
- package/dist/communications/contracts/reviewEffects.d.ts +26 -0
- package/dist/communications/contracts/reviewEffects.js +25 -0
- package/dist/communications/contracts/reviewRequest.d.ts +26 -0
- package/dist/communications/contracts/reviewRequest.js +24 -0
- package/dist/communications/contracts/roleNotificationContent.d.ts +25 -0
- package/dist/communications/contracts/roleNotificationContent.js +46 -0
- package/dist/communications/contracts/shipmentDelivered.d.ts +23 -0
- package/dist/communications/contracts/shipmentDelivered.js +24 -0
- package/dist/communications/contracts/shipmentDispatched.d.ts +27 -0
- package/dist/communications/contracts/shipmentDispatched.js +35 -0
- package/dist/communications/contracts/shipmentException.d.ts +21 -0
- package/dist/communications/contracts/shipmentException.js +26 -0
- package/dist/communications/contracts/subscriptionActivationActionRequired.d.ts +17 -0
- package/dist/communications/contracts/subscriptionActivationActionRequired.js +22 -0
- package/dist/communications/contracts/subscriptionAddressChanged.d.ts +19 -0
- package/dist/communications/contracts/subscriptionAddressChanged.js +25 -0
- package/dist/communications/contracts/subscriptionCancelled.d.ts +19 -0
- package/dist/communications/contracts/subscriptionCancelled.js +25 -0
- package/dist/communications/contracts/subscriptionCycleSkipped.d.ts +25 -0
- package/dist/communications/contracts/subscriptionCycleSkipped.js +40 -0
- package/dist/communications/contracts/subscriptionDeliveryRescheduled.d.ts +25 -0
- package/dist/communications/contracts/subscriptionDeliveryRescheduled.js +39 -0
- package/dist/communications/contracts/subscriptionEmailContent.d.ts +145 -0
- package/dist/communications/contracts/subscriptionEmailContent.js +1 -0
- package/dist/communications/contracts/subscriptionPackageChanged.d.ts +20 -0
- package/dist/communications/contracts/subscriptionPackageChanged.js +26 -0
- package/dist/communications/contracts/subscriptionPauseReminder.d.ts +23 -0
- package/dist/communications/contracts/subscriptionPauseReminder.js +29 -0
- package/dist/communications/contracts/subscriptionPaused.d.ts +21 -0
- package/dist/communications/contracts/subscriptionPaused.js +25 -0
- package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +34 -0
- package/dist/communications/contracts/subscriptionPaymentExpired.js +37 -0
- package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +49 -0
- package/dist/communications/contracts/subscriptionPaymentFailed.js +56 -0
- package/dist/communications/contracts/subscriptionPaymentRecovered.d.ts +19 -0
- package/dist/communications/contracts/subscriptionPaymentRecovered.js +22 -0
- package/dist/communications/contracts/subscriptionRenewalAtRisk.d.ts +36 -0
- package/dist/communications/contracts/subscriptionRenewalAtRisk.js +36 -0
- package/dist/communications/contracts/subscriptionRenewalUpcoming.d.ts +49 -0
- package/dist/communications/contracts/subscriptionRenewalUpcoming.js +43 -0
- package/dist/communications/contracts/subscriptionResumed.d.ts +23 -0
- package/dist/communications/contracts/subscriptionResumed.js +25 -0
- package/dist/communications/contracts/subscriptionWelcome.d.ts +44 -0
- package/dist/communications/contracts/subscriptionWelcome.js +45 -0
- package/dist/communications/contracts/subscriptionWinback.d.ts +21 -0
- package/dist/communications/contracts/subscriptionWinback.js +28 -0
- package/dist/communications/contracts/transactionalDelivery.d.ts +42 -0
- package/dist/communications/contracts/transactionalDelivery.js +1 -0
- package/dist/communications/contracts/types.d.ts +46 -0
- package/dist/communications/contracts/types.js +1 -0
- package/dist/communications/contribution.d.ts +10 -0
- package/dist/communications/contribution.js +24 -0
- package/dist/communications/deliveryReconciliation.d.ts +64 -0
- package/dist/communications/deliveryReconciliation.js +60 -0
- package/dist/communications/emailEgress.d.ts +38 -0
- package/dist/communications/emailEgress.js +100 -0
- package/dist/communications/emailHealthAssessment.d.ts +39 -0
- package/dist/communications/emailHealthAssessment.js +59 -0
- package/dist/communications/emailHealthMetricsPort.d.ts +17 -0
- package/dist/communications/emailHealthMetricsPort.js +1 -0
- package/dist/communications/emailNotificationControl.d.ts +27 -0
- package/dist/communications/emailNotificationControl.js +10 -0
- package/dist/communications/emailObservation.d.ts +28 -0
- package/dist/communications/emailObservation.js +23 -0
- package/dist/communications/emailTransport.d.ts +82 -0
- package/dist/communications/emailTransport.js +95 -0
- package/dist/communications/errors.d.ts +15 -0
- package/dist/communications/errors.js +30 -0
- package/dist/communications/index.d.ts +47 -0
- package/dist/communications/index.js +38 -0
- package/dist/communications/integrationEventSignature.d.ts +15 -0
- package/dist/communications/integrationEventSignature.js +37 -0
- package/dist/communications/klaviyo/consentPush.d.ts +51 -0
- package/dist/communications/klaviyo/consentPush.js +19 -0
- package/dist/communications/klaviyo/index.d.ts +110 -0
- package/dist/communications/klaviyo/index.js +860 -0
- package/dist/communications/managedTransactionalDeliveryStore.d.ts +12 -0
- package/dist/communications/managedTransactionalDeliveryStore.js +49 -0
- package/dist/communications/nativeOperations.d.ts +79 -0
- package/dist/communications/nativeOperations.js +3 -0
- package/dist/communications/newsletterIntegrationContracts.d.ts +130 -0
- package/dist/communications/newsletterIntegrationContracts.js +128 -0
- package/dist/communications/newsletterWebhookPort.d.ts +11 -0
- package/dist/communications/newsletterWebhookPort.js +84 -0
- package/dist/communications/newsletterWebhookProcessing.d.ts +17 -0
- package/dist/communications/newsletterWebhookProcessing.js +71 -0
- package/dist/communications/originPolicy.d.ts +40 -0
- package/dist/communications/originPolicy.js +100 -0
- package/dist/communications/postgresCommunicationSync.d.ts +79 -0
- package/dist/communications/postgresCommunicationSync.js +111 -0
- package/dist/communications/postgresConsentEvaluator.d.ts +19 -0
- package/dist/communications/postgresConsentEvaluator.js +43 -0
- package/dist/communications/postgresDeliveryReconciliation.d.ts +3 -0
- package/dist/communications/postgresDeliveryReconciliation.js +113 -0
- package/dist/communications/postgresNativeOperations.d.ts +13 -0
- package/dist/communications/postgresNativeOperations.js +63 -0
- package/dist/communications/postgresNotificationRecipients.d.ts +37 -0
- package/dist/communications/postgresNotificationRecipients.js +60 -0
- package/dist/communications/postgresTransactionalDeliveryStore.d.ts +7 -0
- package/dist/communications/postgresTransactionalDeliveryStore.js +55 -0
- package/dist/communications/preferencesToken.d.ts +10 -0
- package/dist/communications/preferencesToken.js +40 -0
- package/dist/communications/publicPreferenceToken.d.ts +24 -0
- package/dist/communications/publicPreferenceToken.js +53 -0
- package/dist/communications/resend/index.d.ts +40 -0
- package/dist/communications/resend/index.js +310 -0
- package/dist/communications/shipmentNotifications.d.ts +34 -0
- package/dist/communications/shipmentNotifications.js +61 -0
- package/dist/communications/sql.d.ts +26 -0
- package/dist/communications/sql.js +7 -0
- package/dist/communications/standardWebhooks.d.ts +14 -0
- package/dist/communications/standardWebhooks.js +73 -0
- package/dist/communications/status.d.ts +11 -0
- package/dist/communications/status.js +36 -0
- package/dist/communications/transactionalDelivery.d.ts +19 -0
- package/dist/communications/transactionalDelivery.js +96 -0
- package/dist/communications/transactionalDeliveryIdentifier.d.ts +3 -0
- package/dist/communications/transactionalDeliveryIdentifier.js +6 -0
- package/dist/communications/unsubscribeToken.d.ts +77 -0
- package/dist/communications/unsubscribeToken.js +150 -0
- package/dist/communications/validation.d.ts +2 -0
- package/dist/communications/validation.js +3 -0
- package/dist/composition/catalogContribution.d.ts +18 -0
- package/dist/composition/catalogContribution.js +21 -0
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/http/index.d.ts +1 -0
- package/dist/http/index.js +1 -0
- package/dist/http/webhookSignature.d.ts +42 -0
- package/dist/http/webhookSignature.js +86 -0
- package/dist/identity/customerContracts.d.ts +2 -2
- package/dist/inventory/adminInventory.d.ts +13 -0
- package/dist/inventory/adminInventory.js +214 -0
- package/dist/inventory/contracts/forecast.d.ts +86 -0
- package/dist/inventory/contracts/forecast.js +1 -0
- package/dist/inventory/contracts/index.d.ts +4 -0
- package/dist/inventory/contracts/index.js +1 -0
- package/dist/inventory/contracts/inventory.d.ts +157 -0
- package/dist/inventory/contracts/inventory.js +1 -0
- package/dist/inventory/contracts/newPurchaseStock.d.ts +20 -0
- package/dist/inventory/contracts/newPurchaseStock.js +1 -0
- package/dist/inventory/contracts/reservation.d.ts +18 -0
- package/dist/inventory/contracts/reservation.js +1 -0
- package/dist/inventory/forecast.d.ts +24 -0
- package/dist/inventory/forecast.js +200 -0
- package/dist/inventory/index.d.ts +13 -0
- package/dist/inventory/index.js +10 -0
- package/dist/inventory/inventoryHandlers.d.ts +53 -0
- package/dist/inventory/inventoryHandlers.js +151 -0
- package/dist/inventory/newPurchaseStockAvailability.d.ts +47 -0
- package/dist/inventory/newPurchaseStockAvailability.js +75 -0
- package/dist/inventory/ports.d.ts +21 -0
- package/dist/inventory/ports.js +16 -0
- package/dist/inventory/renewalReservation.d.ts +27 -0
- package/dist/inventory/renewalReservation.js +61 -0
- package/dist/inventory/reservationPolicy.d.ts +6 -0
- package/dist/inventory/reservationPolicy.js +19 -0
- package/dist/inventory/schemas.d.ts +137 -0
- package/dist/inventory/schemas.js +112 -0
- package/dist/inventory/sql.d.ts +14 -0
- package/dist/inventory/sql.js +5 -0
- package/dist/inventory/subscriptionForecastCalculation.d.ts +4 -0
- package/dist/inventory/subscriptionForecastCalculation.js +133 -0
- package/dist/pricing/acquisitionFinancialPolicy.d.ts +26 -0
- package/dist/pricing/acquisitionFinancialPolicy.js +1 -0
- package/dist/pricing/acquisitionOfferPricing.d.ts +27 -0
- package/dist/pricing/acquisitionOfferPricing.js +25 -0
- package/dist/pricing/acquisitionOfferPricingHandler.d.ts +20 -0
- package/dist/pricing/acquisitionOfferPricingHandler.js +105 -0
- package/dist/pricing/acquisitionOfferPricingSchemas.d.ts +31 -0
- package/dist/pricing/acquisitionOfferPricingSchemas.js +33 -0
- package/dist/pricing/acquisitionQuoteBinding.d.ts +12 -0
- package/dist/pricing/acquisitionQuoteBinding.js +12 -0
- package/dist/pricing/acquisitionReadiness.d.ts +31 -0
- package/dist/pricing/acquisitionReadiness.js +117 -0
- package/dist/pricing/acquisitionTerms.d.ts +19 -0
- package/dist/pricing/acquisitionTerms.js +126 -0
- package/dist/pricing/acquisitionTermsSchemas.d.ts +59 -0
- package/dist/pricing/acquisitionTermsSchemas.js +42 -0
- package/dist/pricing/catalogFactsProvenance.d.ts +33 -0
- package/dist/pricing/catalogFactsProvenance.js +64 -0
- package/dist/pricing/catalogFactsSchemas.d.ts +45 -0
- package/dist/pricing/catalogFactsSchemas.js +58 -0
- package/dist/pricing/commerceOfferPricing.d.ts +25 -0
- package/dist/pricing/commerceOfferPricing.js +139 -0
- package/dist/pricing/commerceOfferPricingCache.d.ts +10 -0
- package/dist/pricing/commerceOfferPricingCache.js +44 -0
- package/dist/pricing/commerceOfferPricingHandler.d.ts +21 -0
- package/dist/pricing/commerceOfferPricingHandler.js +78 -0
- package/dist/pricing/commercePriceAuthority.d.ts +26 -0
- package/dist/pricing/commercePriceAuthority.js +79 -0
- package/dist/pricing/commercePricingPolicyErrors.d.ts +40 -0
- package/dist/pricing/commercePricingPolicyErrors.js +67 -0
- package/dist/pricing/commerceQuoteBatchHandler.d.ts +37 -0
- package/dist/pricing/commerceQuoteBatchHandler.js +83 -0
- package/dist/pricing/commerceQuoteCatalogReadPort.d.ts +27 -0
- package/dist/pricing/commerceQuoteCatalogReadPort.js +8 -0
- package/dist/pricing/commerceQuoteHandler.d.ts +31 -0
- package/dist/pricing/commerceQuoteHandler.js +110 -0
- package/dist/pricing/commerceQuoteSnapshotExpect.d.ts +9 -0
- package/dist/pricing/commerceQuoteSnapshotExpect.js +22 -0
- package/dist/pricing/contracts/acquisitionTerms.d.ts +32 -0
- package/dist/pricing/contracts/acquisitionTerms.js +2 -0
- package/dist/pricing/contracts/authority.d.ts +27 -0
- package/dist/pricing/contracts/authority.js +1 -0
- package/dist/pricing/contracts/evidence.d.ts +33 -0
- package/dist/pricing/contracts/evidence.js +1 -0
- package/dist/pricing/contracts/index.d.ts +17 -0
- package/dist/pricing/contracts/index.js +7 -0
- package/dist/pricing/contracts/money.d.ts +27 -0
- package/dist/pricing/contracts/money.js +1 -0
- package/dist/pricing/contracts/offer.d.ts +52 -0
- package/dist/pricing/contracts/offer.js +4 -0
- package/dist/pricing/contracts/offerPolicy.d.ts +16 -0
- package/dist/pricing/contracts/offerPolicy.js +5 -0
- package/dist/pricing/contracts/policy.d.ts +22 -0
- package/dist/pricing/contracts/policy.js +3 -0
- package/dist/pricing/contracts/provenance.d.ts +24 -0
- package/dist/pricing/contracts/provenance.js +2 -0
- package/dist/pricing/contracts/quote.d.ts +94 -0
- package/dist/pricing/contracts/quote.js +1 -0
- package/dist/pricing/dbBackedCommerceQuoteHelpers.d.ts +78 -0
- package/dist/pricing/dbBackedCommerceQuoteHelpers.js +146 -0
- package/dist/pricing/dbBackedCommerceQuotePort.d.ts +66 -0
- package/dist/pricing/dbBackedCommerceQuotePort.js +206 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.d.ts +4 -0
- package/dist/pricing/dbBackedCommerceQuoteSnapshotVerifier.js +25 -0
- package/dist/pricing/index.d.ts +51 -0
- package/dist/pricing/index.js +36 -0
- package/dist/pricing/offerPolicyReadiness.d.ts +21 -0
- package/dist/pricing/offerPolicyReadiness.js +79 -0
- package/dist/pricing/offerPolicySchemas.d.ts +25 -0
- package/dist/pricing/offerPolicySchemas.js +15 -0
- package/dist/pricing/offerPricingSchemas.d.ts +315 -0
- package/dist/pricing/offerPricingSchemas.js +65 -0
- package/dist/pricing/ports.d.ts +13 -0
- package/dist/pricing/ports.js +9 -0
- package/dist/pricing/pricingPolicyToken.d.ts +39 -0
- package/dist/pricing/pricingPolicyToken.js +84 -0
- package/dist/pricing/quoteAcquisitionTerms.d.ts +2 -0
- package/dist/pricing/quoteAcquisitionTerms.js +4 -0
- package/dist/pricing/quoteCodeRejectionDetails.d.ts +20 -0
- package/dist/pricing/quoteCodeRejectionDetails.js +22 -0
- package/dist/pricing/quotePorts.d.ts +30 -0
- package/dist/pricing/quotePorts.js +20 -0
- package/dist/pricing/quotePrimitives.d.ts +13 -0
- package/dist/pricing/quotePrimitives.js +18 -0
- package/dist/pricing/quotePromotionEvidence.d.ts +39 -0
- package/dist/pricing/quotePromotionEvidence.js +73 -0
- package/dist/pricing/quoteSchemas.d.ts +1176 -0
- package/dist/pricing/quoteSchemas.js +196 -0
- package/dist/pricing/subscriptionPricePolicy.d.ts +52 -0
- package/dist/pricing/subscriptionPricePolicy.js +96 -0
- package/dist/pricing/taxProfileGuard.d.ts +2 -0
- package/dist/pricing/taxProfileGuard.js +24 -0
- package/dist/pricing/validation.d.ts +2 -0
- package/dist/pricing/validation.js +3 -0
- package/dist/promotions/adminBindings.d.ts +72 -0
- package/dist/promotions/adminBindings.js +1 -0
- package/dist/promotions/adminPromotionCodesContracts.d.ts +498 -0
- package/dist/promotions/adminPromotionCodesContracts.js +211 -0
- package/dist/promotions/adminPromotionCodesDataPort.d.ts +47 -0
- package/dist/promotions/adminPromotionCodesDataPort.js +1 -0
- package/dist/promotions/adminPromotionCodesHandler.d.ts +14 -0
- package/dist/promotions/adminPromotionCodesHandler.js +194 -0
- package/dist/promotions/adminPromotionsContracts.d.ts +235 -0
- package/dist/promotions/adminPromotionsContracts.js +99 -0
- package/dist/promotions/adminPromotionsDataPort.d.ts +42 -0
- package/dist/promotions/adminPromotionsDataPort.js +1 -0
- package/dist/promotions/adminPromotionsHandler.d.ts +16 -0
- package/dist/promotions/adminPromotionsHandler.js +47 -0
- package/dist/promotions/contracts/index.d.ts +387 -0
- package/dist/promotions/contracts/index.js +1 -0
- package/dist/promotions/index.d.ts +22 -0
- package/dist/promotions/index.js +21 -0
- package/dist/promotions/promoDataPort.d.ts +47 -0
- package/dist/promotions/promoDataPort.js +14 -0
- package/dist/promotions/promotionAcceptanceTelemetry.d.ts +29 -0
- package/dist/promotions/promotionAcceptanceTelemetry.js +45 -0
- package/dist/promotions/promotionBenefitDefinition.d.ts +37 -0
- package/dist/promotions/promotionBenefitDefinition.js +33 -0
- package/dist/promotions/promotionClaimSweepPort.d.ts +14 -0
- package/dist/promotions/promotionClaimSweepPort.js +8 -0
- package/dist/promotions/promotionClaims.d.ts +5 -0
- package/dist/promotions/promotionClaims.js +57 -0
- package/dist/promotions/promotionCodePreview.d.ts +11 -0
- package/dist/promotions/promotionCodePreview.js +154 -0
- package/dist/promotions/promotionCodeQuotePort.d.ts +25 -0
- package/dist/promotions/promotionCodeQuotePort.js +1 -0
- package/dist/promotions/promotionQuoteAcceptance.d.ts +65 -0
- package/dist/promotions/promotionQuoteAcceptance.js +202 -0
- package/dist/promotions/promotionQuoteBinding.d.ts +71 -0
- package/dist/promotions/promotionQuoteBinding.js +85 -0
- package/dist/promotions/quoteAutomaticPromotions.d.ts +24 -0
- package/dist/promotions/quoteAutomaticPromotions.js +36 -0
- package/dist/promotions/quotePromoDiscounts.d.ts +32 -0
- package/dist/promotions/quotePromoDiscounts.js +140 -0
- package/dist/promotions/quotePromotionCodeAdjustments.d.ts +27 -0
- package/dist/promotions/quotePromotionCodeAdjustments.js +223 -0
- package/dist/promotions/quotePromotionV2.d.ts +29 -0
- package/dist/promotions/quotePromotionV2.js +174 -0
- package/dist/promotions/sql.d.ts +14 -0
- package/dist/promotions/sql.js +5 -0
- package/dist/promotions/validation.d.ts +2 -0
- package/dist/promotions/validation.js +3 -0
- package/dist/shipping/addressCanonLookupHandler.d.ts +7 -0
- package/dist/shipping/addressCanonLookupHandler.js +105 -0
- package/dist/shipping/addressCanonical.d.ts +2 -0
- package/dist/shipping/addressCanonical.js +26 -0
- package/dist/shipping/addressPorts.d.ts +39 -0
- package/dist/shipping/addressPorts.js +1 -0
- package/dist/shipping/addressSchemas.d.ts +30 -0
- package/dist/shipping/addressSchemas.js +1 -0
- package/dist/shipping/adminShippingRateHandler.d.ts +4 -0
- package/dist/shipping/adminShippingRateHandler.js +64 -0
- package/dist/shipping/contracts/address.d.ts +144 -0
- package/dist/shipping/contracts/address.js +1 -0
- package/dist/shipping/contracts/delivery.d.ts +110 -0
- package/dist/shipping/contracts/delivery.js +1 -0
- package/dist/shipping/contracts/index.d.ts +3 -0
- package/dist/shipping/contracts/index.js +1 -0
- package/dist/shipping/contracts/shippingRate.d.ts +11 -0
- package/dist/shipping/contracts/shippingRate.js +1 -0
- package/dist/shipping/customerAddressesHandler.d.ts +5 -0
- package/dist/shipping/customerAddressesHandler.js +80 -0
- package/dist/shipping/customerSelfServiceAddressModels.d.ts +27 -0
- package/dist/shipping/customerSelfServiceAddressModels.js +101 -0
- package/dist/shipping/deliverySelectionHandler.d.ts +10 -0
- package/dist/shipping/deliverySelectionHandler.js +77 -0
- package/dist/shipping/deliverySelectionPort.d.ts +8 -0
- package/dist/shipping/deliverySelectionPort.js +1 -0
- package/dist/shipping/deliverySelectionSummary.d.ts +2 -0
- package/dist/shipping/deliverySelectionSummary.js +53 -0
- package/dist/shipping/handlerSchemas.d.ts +21 -0
- package/dist/shipping/handlerSchemas.js +1 -0
- package/dist/shipping/index.d.ts +17 -0
- package/dist/shipping/index.js +8 -0
- package/dist/shipping/pickupPointSearchPort.d.ts +4 -0
- package/dist/shipping/pickupPointSearchPort.js +1 -0
- package/dist/shipping/readDeliverySelectionEvidence.d.ts +2 -0
- package/dist/shipping/readDeliverySelectionEvidence.js +44 -0
- package/dist/shipping/shippingRatePorts.d.ts +52 -0
- package/dist/shipping/shippingRatePorts.js +1 -0
- package/package.json +72 -2
- package/release-gates.json +249 -8
- package/sql/20260807140000_read_parity_catalog.sql +94 -0
- package/sql/20260807190000_comms_outbox_rail.sql +329 -0
- package/sql/20260810120000_storefront_catalog_attributes.sql +51 -0
- package/sql/20260810120001_transactional_delivery_receipts.sql +209 -0
- package/sql/20260812140000_sellable_bundle_catalog.sql +124 -0
- package/sql/20260812210000_bundle_operator_write_boundary.sql +567 -0
- package/sql/20260813120000_communications_control_plane.sql +568 -0
- package/sql/20260814000000_fulfillment_stock_evidence.sql +239 -0
- package/sql/20260815120000_automatic_subscription_renewal.sql +1083 -0
- package/sql/20260817180000_promotion_claim_lifecycle.sql +591 -0
- package/sql/20260817180100_promotion_claim_lifecycle_validation.sql +23 -0
- package/sql/20260827220000_catalog_document_revision_foundation.sql +226 -0
- package/sql/20260827220001_catalog_document_revision_foundation_validate.sql +10 -0
- package/sql/20260908100000_catalog_draft_foundation.sql +217 -0
- package/sql/20261019200000_communications_native_operations.sql +68 -0
- package/src/catalog/activeSkuSelection.ts +20 -0
- package/src/catalog/adminBindings.ts +59 -0
- package/src/catalog/adminBundleHandler.ts +165 -0
- package/src/catalog/adminBundleReadHandler.ts +261 -0
- package/src/catalog/adminBundleWritePort.ts +102 -0
- package/src/catalog/bundleAvailability.ts +129 -0
- package/src/catalog/bundleAvailabilityService.ts +171 -0
- package/src/catalog/bundleBindings.ts +29 -0
- package/src/catalog/bundleCatalogQueries.ts +98 -0
- package/src/catalog/bundleCatalogReadPort.ts +177 -0
- package/src/catalog/bundleCatalogStore.ts +269 -0
- package/src/catalog/bundleRuleCodes.ts +134 -0
- package/src/catalog/bundleRules.ts +153 -0
- package/src/catalog/catalogDraftStore.ts +71 -0
- package/src/catalog/catalogSkuEnvelope.ts +214 -0
- package/src/catalog/catalogSkuEnvelopeMapper.ts +160 -0
- package/src/catalog/contracts/bundleAdmin.ts +20 -0
- package/src/catalog/contracts/bundleAvailability.ts +5 -0
- package/src/catalog/contracts/bundleRead.ts +13 -0
- package/src/catalog/contracts/draft.ts +69 -0
- package/src/catalog/contracts/foundation.ts +104 -0
- package/src/catalog/contracts/index.ts +14 -0
- package/src/catalog/contracts/lifecycle.ts +74 -0
- package/src/catalog/contracts/productMediaContracts.ts +170 -0
- package/src/catalog/contracts/productTypes.ts +35 -0
- package/src/catalog/contracts/resolveProductMedia.ts +85 -0
- package/src/catalog/contracts/sellable.ts +12 -0
- package/src/catalog/draftHandler.ts +105 -0
- package/src/catalog/draftPorts.ts +18 -0
- package/src/catalog/draftSchemas.ts +88 -0
- package/src/catalog/draftValidation.ts +100 -0
- package/src/catalog/foundationSchemas.ts +123 -0
- package/src/catalog/index.ts +43 -0
- package/src/catalog/mediaSourcePack.ts +219 -0
- package/src/catalog/productTypeSchemas.ts +70 -0
- package/src/catalog/publicationPorts.ts +44 -0
- package/src/catalog/readPorts.ts +61 -0
- package/src/catalog/referenceCatalogHandler.ts +39 -0
- package/src/catalog/resolvedSkuProjection.ts +76 -0
- package/src/catalog/sellableBundleHandler.ts +133 -0
- package/src/catalog/sellableSchemas.ts +33 -0
- package/src/catalog/sql.ts +14 -0
- package/src/catalog/validation.ts +3 -0
- package/src/communications/accountingDocumentDelivery.ts +63 -0
- package/src/communications/authEmailError.ts +10 -0
- package/src/communications/authEmailPorts.ts +2 -0
- package/src/communications/authSendEmailHook.ts +310 -0
- package/src/communications/capturedTransactionalDelivery.ts +29 -0
- package/src/communications/communicationSync.ts +96 -0
- package/src/communications/communicationSyncWorker.ts +302 -0
- package/src/communications/consentPolicy.ts +82 -0
- package/src/communications/consentPurposeRegistry.ts +31 -0
- package/src/communications/contracts/abandonedCart.ts +64 -0
- package/src/communications/contracts/authEmail.ts +73 -0
- package/src/communications/contracts/backInStock.ts +69 -0
- package/src/communications/contracts/blocks.ts +47 -0
- package/src/communications/contracts/checkoutExpired.ts +62 -0
- package/src/communications/contracts/checkoutRecovery.ts +68 -0
- package/src/communications/contracts/commerceEmailContent.ts +189 -0
- package/src/communications/contracts/commerceEngagementEmailContent.ts +106 -0
- package/src/communications/contracts/consent.ts +13 -0
- package/src/communications/contracts/email.ts +210 -0
- package/src/communications/contracts/guideCard.ts +34 -0
- package/src/communications/contracts/index.ts +52 -0
- package/src/communications/contracts/inquiryContent.ts +53 -0
- package/src/communications/contracts/invoiceDocumentContent.ts +57 -0
- package/src/communications/contracts/marketingAutomation.ts +45 -0
- package/src/communications/contracts/marketingSync.ts +109 -0
- package/src/communications/contracts/newsletter.ts +78 -0
- package/src/communications/contracts/newsletterWebhook.ts +23 -0
- package/src/communications/contracts/optOutContent.ts +23 -0
- package/src/communications/contracts/orderCanceled.ts +64 -0
- package/src/communications/contracts/orderDraft.ts +112 -0
- package/src/communications/contracts/orderPaid.ts +147 -0
- package/src/communications/contracts/orderRefunded.ts +63 -0
- package/src/communications/contracts/paymentFailed.ts +59 -0
- package/src/communications/contracts/publicIntake.ts +53 -0
- package/src/communications/contracts/render.ts +271 -0
- package/src/communications/contracts/reorderReminder.ts +59 -0
- package/src/communications/contracts/returnEmails.ts +113 -0
- package/src/communications/contracts/reviewEffects.ts +60 -0
- package/src/communications/contracts/reviewRequest.ts +59 -0
- package/src/communications/contracts/roleNotificationContent.ts +65 -0
- package/src/communications/contracts/shipmentDelivered.ts +59 -0
- package/src/communications/contracts/shipmentDispatched.ts +77 -0
- package/src/communications/contracts/shipmentException.ts +62 -0
- package/src/communications/contracts/subscriptionActivationActionRequired.ts +37 -0
- package/src/communications/contracts/subscriptionAddressChanged.ts +56 -0
- package/src/communications/contracts/subscriptionCancelled.ts +57 -0
- package/src/communications/contracts/subscriptionCycleSkipped.ts +80 -0
- package/src/communications/contracts/subscriptionDeliveryRescheduled.ts +79 -0
- package/src/communications/contracts/subscriptionEmailContent.ts +163 -0
- package/src/communications/contracts/subscriptionPackageChanged.ts +59 -0
- package/src/communications/contracts/subscriptionPauseReminder.ts +63 -0
- package/src/communications/contracts/subscriptionPaused.ts +58 -0
- package/src/communications/contracts/subscriptionPaymentExpired.ts +83 -0
- package/src/communications/contracts/subscriptionPaymentFailed.ts +117 -0
- package/src/communications/contracts/subscriptionPaymentRecovered.ts +50 -0
- package/src/communications/contracts/subscriptionRenewalAtRisk.ts +85 -0
- package/src/communications/contracts/subscriptionRenewalUpcoming.ts +103 -0
- package/src/communications/contracts/subscriptionResumed.ts +60 -0
- package/src/communications/contracts/subscriptionWelcome.ts +102 -0
- package/src/communications/contracts/subscriptionWinback.ts +62 -0
- package/src/communications/contracts/transactionalDelivery.ts +43 -0
- package/src/communications/contracts/types.ts +58 -0
- package/src/communications/contribution.ts +33 -0
- package/src/communications/deliveryReconciliation.ts +108 -0
- package/src/communications/emailEgress.ts +111 -0
- package/src/communications/emailHealthAssessment.ts +106 -0
- package/src/communications/emailHealthMetricsPort.ts +17 -0
- package/src/communications/emailNotificationControl.ts +28 -0
- package/src/communications/emailObservation.ts +43 -0
- package/src/communications/emailTransport.ts +167 -0
- package/src/communications/errors.ts +34 -0
- package/src/communications/index.ts +47 -0
- package/src/communications/integrationEventSignature.ts +49 -0
- package/src/communications/klaviyo/consentPush.ts +19 -0
- package/src/communications/klaviyo/index.ts +649 -0
- package/src/communications/managedTransactionalDeliveryStore.ts +59 -0
- package/src/communications/nativeOperations.ts +40 -0
- package/src/communications/newsletterIntegrationContracts.ts +154 -0
- package/src/communications/newsletterWebhookPort.ts +104 -0
- package/src/communications/newsletterWebhookProcessing.ts +102 -0
- package/src/communications/originPolicy.ts +151 -0
- package/src/communications/postgresCommunicationSync.ts +127 -0
- package/src/communications/postgresConsentEvaluator.ts +49 -0
- package/src/communications/postgresDeliveryReconciliation.ts +101 -0
- package/src/communications/postgresNativeOperations.ts +55 -0
- package/src/communications/postgresNotificationRecipients.ts +57 -0
- package/src/communications/postgresTransactionalDeliveryStore.ts +79 -0
- package/src/communications/preferencesToken.ts +62 -0
- package/src/communications/publicPreferenceToken.ts +68 -0
- package/src/communications/resend/index.ts +350 -0
- package/src/communications/shipmentNotifications.ts +78 -0
- package/src/communications/sql.ts +7 -0
- package/src/communications/standardWebhooks.ts +84 -0
- package/src/communications/status.ts +51 -0
- package/src/communications/transactionalDelivery.ts +114 -0
- package/src/communications/transactionalDeliveryIdentifier.ts +9 -0
- package/src/communications/unsubscribeToken.ts +186 -0
- package/src/communications/validation.ts +3 -0
- package/src/composition/catalogContribution.ts +32 -0
- package/src/composition/index.ts +1 -0
- package/src/http/index.ts +1 -0
- package/src/http/webhookSignature.ts +96 -0
- package/src/inventory/adminInventory.ts +251 -0
- package/src/inventory/contracts/forecast.ts +96 -0
- package/src/inventory/contracts/index.ts +18 -0
- package/src/inventory/contracts/inventory.ts +14 -0
- package/src/inventory/contracts/newPurchaseStock.ts +23 -0
- package/src/inventory/contracts/reservation.ts +20 -0
- package/src/inventory/forecast.ts +239 -0
- package/src/inventory/index.ts +21 -0
- package/src/inventory/inventoryHandlers.ts +215 -0
- package/src/inventory/newPurchaseStockAvailability.ts +120 -0
- package/src/inventory/ports.ts +46 -0
- package/src/inventory/renewalReservation.ts +88 -0
- package/src/inventory/reservationPolicy.ts +27 -0
- package/src/inventory/schemas.ts +128 -0
- package/src/inventory/sql.ts +5 -0
- package/src/inventory/subscriptionForecastCalculation.ts +157 -0
- package/src/pricing/acquisitionFinancialPolicy.ts +26 -0
- package/src/pricing/acquisitionOfferPricing.ts +38 -0
- package/src/pricing/acquisitionOfferPricingHandler.ts +157 -0
- package/src/pricing/acquisitionOfferPricingSchemas.ts +35 -0
- package/src/pricing/acquisitionQuoteBinding.ts +12 -0
- package/src/pricing/acquisitionReadiness.ts +148 -0
- package/src/pricing/acquisitionTerms.ts +125 -0
- package/src/pricing/acquisitionTermsSchemas.ts +52 -0
- package/src/pricing/catalogFactsProvenance.ts +102 -0
- package/src/pricing/catalogFactsSchemas.ts +69 -0
- package/src/pricing/commerceOfferPricing.ts +224 -0
- package/src/pricing/commerceOfferPricingCache.ts +53 -0
- package/src/pricing/commerceOfferPricingHandler.ts +137 -0
- package/src/pricing/commercePriceAuthority.ts +104 -0
- package/src/pricing/commercePricingPolicyErrors.ts +88 -0
- package/src/pricing/commerceQuoteBatchHandler.ts +129 -0
- package/src/pricing/commerceQuoteCatalogReadPort.ts +42 -0
- package/src/pricing/commerceQuoteHandler.ts +184 -0
- package/src/pricing/commerceQuoteSnapshotExpect.ts +48 -0
- package/src/pricing/contracts/acquisitionTerms.ts +26 -0
- package/src/pricing/contracts/authority.ts +44 -0
- package/src/pricing/contracts/evidence.ts +25 -0
- package/src/pricing/contracts/index.ts +17 -0
- package/src/pricing/contracts/money.ts +32 -0
- package/src/pricing/contracts/offer.ts +42 -0
- package/src/pricing/contracts/offerPolicy.ts +17 -0
- package/src/pricing/contracts/policy.ts +26 -0
- package/src/pricing/contracts/provenance.ts +19 -0
- package/src/pricing/contracts/quote.ts +106 -0
- package/src/pricing/dbBackedCommerceQuoteHelpers.ts +256 -0
- package/src/pricing/dbBackedCommerceQuotePort.ts +260 -0
- package/src/pricing/dbBackedCommerceQuoteSnapshotVerifier.ts +49 -0
- package/src/pricing/index.ts +52 -0
- package/src/pricing/offerPolicyReadiness.ts +110 -0
- package/src/pricing/offerPolicySchemas.ts +23 -0
- package/src/pricing/offerPricingSchemas.ts +92 -0
- package/src/pricing/ports.ts +17 -0
- package/src/pricing/pricingPolicyToken.ts +119 -0
- package/src/pricing/quoteAcquisitionTerms.ts +10 -0
- package/src/pricing/quoteCodeRejectionDetails.ts +23 -0
- package/src/pricing/quotePorts.ts +58 -0
- package/src/pricing/quotePrimitives.ts +21 -0
- package/src/pricing/quotePromotionEvidence.ts +82 -0
- package/src/pricing/quoteSchemas.ts +230 -0
- package/src/pricing/subscriptionPricePolicy.ts +113 -0
- package/src/pricing/taxProfileGuard.ts +33 -0
- package/src/pricing/validation.ts +3 -0
- package/src/promotions/adminBindings.ts +53 -0
- package/src/promotions/adminPromotionCodesContracts.ts +244 -0
- package/src/promotions/adminPromotionCodesDataPort.ts +56 -0
- package/src/promotions/adminPromotionCodesHandler.ts +254 -0
- package/src/promotions/adminPromotionsContracts.ts +121 -0
- package/src/promotions/adminPromotionsDataPort.ts +48 -0
- package/src/promotions/adminPromotionsHandler.ts +72 -0
- package/src/promotions/contracts/index.ts +387 -0
- package/src/promotions/index.ts +22 -0
- package/src/promotions/promoDataPort.ts +65 -0
- package/src/promotions/promotionAcceptanceTelemetry.ts +73 -0
- package/src/promotions/promotionBenefitDefinition.ts +48 -0
- package/src/promotions/promotionClaimSweepPort.ts +23 -0
- package/src/promotions/promotionClaims.ts +70 -0
- package/src/promotions/promotionCodePreview.ts +183 -0
- package/src/promotions/promotionCodeQuotePort.ts +35 -0
- package/src/promotions/promotionQuoteAcceptance.ts +284 -0
- package/src/promotions/promotionQuoteBinding.ts +158 -0
- package/src/promotions/quoteAutomaticPromotions.ts +58 -0
- package/src/promotions/quotePromoDiscounts.ts +185 -0
- package/src/promotions/quotePromotionCodeAdjustments.ts +277 -0
- package/src/promotions/quotePromotionV2.ts +223 -0
- package/src/promotions/sql.ts +5 -0
- package/src/promotions/validation.ts +3 -0
- package/src/shipping/addressCanonLookupHandler.ts +114 -0
- package/src/shipping/addressCanonical.ts +31 -0
- package/src/shipping/addressPorts.ts +48 -0
- package/src/shipping/addressSchemas.ts +28 -0
- package/src/shipping/adminShippingRateHandler.ts +72 -0
- package/src/shipping/contracts/address.ts +71 -0
- package/src/shipping/contracts/delivery.ts +114 -0
- package/src/shipping/contracts/index.ts +18 -0
- package/src/shipping/contracts/shippingRate.ts +7 -0
- package/src/shipping/customerAddressesHandler.ts +100 -0
- package/src/shipping/customerSelfServiceAddressModels.ts +124 -0
- package/src/shipping/deliverySelectionHandler.ts +94 -0
- package/src/shipping/deliverySelectionPort.ts +10 -0
- package/src/shipping/deliverySelectionSummary.ts +56 -0
- package/src/shipping/handlerSchemas.ts +19 -0
- package/src/shipping/index.ts +23 -0
- package/src/shipping/pickupPointSearchPort.ts +8 -0
- package/src/shipping/readDeliverySelectionEvidence.ts +51 -0
- package/src/shipping/shippingRatePorts.ts +36 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const EMAIL_DEFAULT_ORIGIN_ENV = "EMAIL_DEFAULT_ORIGIN";
|
|
2
|
+
export const EMAIL_PRODUCTION_ORIGIN_HOSTS_ENV = "EMAIL_PRODUCTION_ORIGIN_HOSTS";
|
|
3
|
+
export const COMMS_PRODUCTION_PROJECT_REF_ENV = "COMMS_PRODUCTION_PROJECT_REF";
|
|
4
|
+
function clean(value) {
|
|
5
|
+
const trimmed = value?.trim();
|
|
6
|
+
return trimmed ? trimmed : null;
|
|
7
|
+
}
|
|
8
|
+
function resolveEnvironment(input) {
|
|
9
|
+
if (input.hiddenPreviewEnabled)
|
|
10
|
+
return "hidden_preview";
|
|
11
|
+
const value = clean(input.environment)?.toLowerCase().replace(/-/g, "_");
|
|
12
|
+
if (value === "hidden_preview" ||
|
|
13
|
+
value === "preview" ||
|
|
14
|
+
value === "staging" ||
|
|
15
|
+
value === "production" ||
|
|
16
|
+
value === "production_or_default") {
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
return "production_or_default";
|
|
20
|
+
}
|
|
21
|
+
export function normalizeEmailOrigin(value) {
|
|
22
|
+
try {
|
|
23
|
+
const url = new URL(value);
|
|
24
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
25
|
+
return null;
|
|
26
|
+
if (!url.hostname)
|
|
27
|
+
return null;
|
|
28
|
+
return url.origin.replace(/\/+$/, "");
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function isProductionEmailOrigin(origin, productionHosts) {
|
|
35
|
+
try {
|
|
36
|
+
return productionHosts.includes(new URL(origin).hostname.toLowerCase());
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function readEmailOriginConfiguration(env, fallback) {
|
|
43
|
+
const configuredDefault = env[EMAIL_DEFAULT_ORIGIN_ENV];
|
|
44
|
+
const configuredHosts = env[EMAIL_PRODUCTION_ORIGIN_HOSTS_ENV];
|
|
45
|
+
return {
|
|
46
|
+
defaultOrigin: configuredDefault === undefined ? fallback.defaultOrigin : configuredDefault,
|
|
47
|
+
productionEmailHosts: configuredHosts === undefined
|
|
48
|
+
? fallback.productionEmailHosts
|
|
49
|
+
: configuredHosts
|
|
50
|
+
.split(/[,\s;]+/)
|
|
51
|
+
.map((host) => host.trim().toLowerCase())
|
|
52
|
+
.filter(Boolean),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function requiresExplicitNonProductionOrigin(environment) {
|
|
56
|
+
return environment === "hidden_preview" || environment === "preview" || environment === "staging";
|
|
57
|
+
}
|
|
58
|
+
export function resolveEmailOrigin(input) {
|
|
59
|
+
const environment = resolveEnvironment(input);
|
|
60
|
+
const explicit = clean(input.explicitBaseUrl) ??
|
|
61
|
+
clean(input.customerAuthRedirectOrigin) ??
|
|
62
|
+
clean(input.siteUrl);
|
|
63
|
+
if (!explicit) {
|
|
64
|
+
if (requiresExplicitNonProductionOrigin(environment)) {
|
|
65
|
+
return { ok: false, error: "hidden_preview_origin_required" };
|
|
66
|
+
}
|
|
67
|
+
const defaultOrigin = normalizeEmailOrigin(input.defaultOrigin);
|
|
68
|
+
if (!defaultOrigin)
|
|
69
|
+
return { ok: false, error: "invalid_email_origin" };
|
|
70
|
+
return {
|
|
71
|
+
ok: true,
|
|
72
|
+
origin: defaultOrigin,
|
|
73
|
+
source: "default",
|
|
74
|
+
resolved: {
|
|
75
|
+
origin: defaultOrigin,
|
|
76
|
+
source: "default",
|
|
77
|
+
environment,
|
|
78
|
+
production: isProductionEmailOrigin(defaultOrigin, input.productionEmailHosts),
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const normalized = normalizeEmailOrigin(explicit);
|
|
83
|
+
if (!normalized)
|
|
84
|
+
return { ok: false, error: "invalid_email_origin" };
|
|
85
|
+
const production = isProductionEmailOrigin(normalized, input.productionEmailHosts);
|
|
86
|
+
if (requiresExplicitNonProductionOrigin(environment) && production) {
|
|
87
|
+
return { ok: false, error: "hidden_preview_origin_must_not_be_production" };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
ok: true,
|
|
91
|
+
origin: normalized,
|
|
92
|
+
source: "explicit",
|
|
93
|
+
resolved: {
|
|
94
|
+
origin: normalized,
|
|
95
|
+
source: "explicit",
|
|
96
|
+
environment,
|
|
97
|
+
production,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { SqlExecutor } from "@openlup/core/readiness";
|
|
2
|
+
import type { PostgresDataGatewayEnv } from "../data/index.js";
|
|
3
|
+
import type { CommunicationSyncStore } from "./communicationSyncWorker.js";
|
|
4
|
+
import type { NewsletterSyncEventType, NewsletterMarketingPurpose } from "./contracts/newsletter.js";
|
|
5
|
+
import type { NativeCommunicationsOptions } from "./nativeOperations.js";
|
|
6
|
+
/** Structural seam for the existing outbox store, scoped to this operation's transaction. */
|
|
7
|
+
export interface NativeSyncRail {
|
|
8
|
+
claimBatch(input: {
|
|
9
|
+
eventTypes: string[];
|
|
10
|
+
knownEventTypes: string[];
|
|
11
|
+
batchSize: number;
|
|
12
|
+
visibilitySeconds: number;
|
|
13
|
+
maxAttempts: number;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
id: string;
|
|
16
|
+
attempts: number;
|
|
17
|
+
metadata: Record<string, unknown>;
|
|
18
|
+
}[]>;
|
|
19
|
+
markProcessed(input: {
|
|
20
|
+
eventId: string;
|
|
21
|
+
claimToken: string;
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
applied: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
markFailed(input: {
|
|
27
|
+
eventId: string;
|
|
28
|
+
claimToken: string;
|
|
29
|
+
error: string;
|
|
30
|
+
outcome: "retry" | "discard";
|
|
31
|
+
baseDelaySeconds: number;
|
|
32
|
+
maxDelaySeconds: number;
|
|
33
|
+
maxAttempts: number;
|
|
34
|
+
snoozeSeconds: number;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
status: string;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
export interface NativeSyncRegistration {
|
|
40
|
+
sourceKey: string;
|
|
41
|
+
contactId: string;
|
|
42
|
+
normalizedEmail: string;
|
|
43
|
+
eventType: NewsletterSyncEventType;
|
|
44
|
+
purpose: NewsletterMarketingPurpose;
|
|
45
|
+
payload?: Record<string, unknown>;
|
|
46
|
+
originProviderKind?: string | null;
|
|
47
|
+
originProviderEventId?: string | null;
|
|
48
|
+
remoteProfileId?: string | null;
|
|
49
|
+
remoteListId?: string | null;
|
|
50
|
+
}
|
|
51
|
+
export interface NativeSyncOptions extends NativeCommunicationsOptions {
|
|
52
|
+
providerKind: string;
|
|
53
|
+
rail: (db: SqlExecutor) => NativeSyncRail;
|
|
54
|
+
}
|
|
55
|
+
export interface NativeCommunicationSyncStore extends CommunicationSyncStore {
|
|
56
|
+
registerWork(input: NativeSyncRegistration): Promise<{
|
|
57
|
+
id: string;
|
|
58
|
+
}>;
|
|
59
|
+
registerPreference(input: {
|
|
60
|
+
email: string;
|
|
61
|
+
purpose: "tester_program" | NewsletterMarketingPurpose;
|
|
62
|
+
state: "denied" | "suppressed";
|
|
63
|
+
}): Promise<{
|
|
64
|
+
updated: true;
|
|
65
|
+
email: string;
|
|
66
|
+
purpose: "tester_program" | NewsletterMarketingPurpose;
|
|
67
|
+
state: "denied" | "suppressed";
|
|
68
|
+
workId: string | null;
|
|
69
|
+
alreadySuppressed: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
close(): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
export declare const nativeSyncEventType: (binding: string) => string;
|
|
74
|
+
/** Trusted host transaction seam; registration validation remains shared with the standalone store. */
|
|
75
|
+
export declare function registerNativeSyncWorkInTransaction(db: SqlExecutor, options: Pick<NativeSyncOptions, "binding" | "providerKind">, input: NativeSyncRegistration): Promise<{
|
|
76
|
+
id: string;
|
|
77
|
+
}>;
|
|
78
|
+
/** No sidecar claim/lease/drainer. Only runCommunicationSyncDispatch executes membership effects. */
|
|
79
|
+
export declare function createPostgresCommunicationSyncStore(env: PostgresDataGatewayEnv, options: NativeSyncOptions): NativeCommunicationSyncStore;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { nativeEmail, nativeFingerprint, nativeInteger, nativeJson, nativeStamp, nativeText, nativeTransactions } from "./postgresNativeOperations.js";
|
|
2
|
+
export const nativeSyncEventType = (binding) => `communication.native.sync.${nativeFingerprint(nativeText(binding))}`;
|
|
3
|
+
function nativeSyncRegistration(options, input) {
|
|
4
|
+
const binding = nativeText(options.binding), provider = nativeText(options.providerKind), eventType = nativeSyncEventType(binding);
|
|
5
|
+
const email = nativeEmail(input.normalizedEmail), source = nativeText(input.sourceKey), contact = nativeText(input.contactId);
|
|
6
|
+
if (!["subscribe", "update", "unsubscribe", "suppress"].includes(input.eventType) || !["marketing_launch_offer", "marketing_newsletter"].includes(input.purpose))
|
|
7
|
+
throw new Error("native_sync_event_invalid");
|
|
8
|
+
const payload = nativeJson(input.payload ?? {});
|
|
9
|
+
const refs = [input.originProviderKind ?? null, input.originProviderEventId ?? null, input.remoteProfileId ?? null, input.remoteListId ?? null].map(value => value === null ? null : nativeText(value));
|
|
10
|
+
const fact = nativeFingerprint(JSON.stringify([provider, contact, email, input.eventType, input.purpose, payload, ...refs]));
|
|
11
|
+
// Reuse the rail's ordering barrier for successive preferences of one contact/target.
|
|
12
|
+
const aggregate = nativeFingerprint(JSON.stringify([binding, provider, contact])).slice(0, 32);
|
|
13
|
+
return async (db) => {
|
|
14
|
+
// One rail identity for each source event and exact target binding.
|
|
15
|
+
await db.query(`INSERT INTO public.outbox_events (aggregate_type,aggregate_id,event_type,idempotency_key,payload)
|
|
16
|
+
VALUES ('communication_native_sync',$4::uuid,$1,$2,$3::jsonb) ON CONFLICT (event_type,idempotency_key) DO NOTHING`, [eventType, source, payload, aggregate]);
|
|
17
|
+
const work = (await db.query("SELECT id FROM public.outbox_events WHERE event_type=$1 AND idempotency_key=$2 FOR UPDATE", [eventType, source])).rows[0];
|
|
18
|
+
await db.query(`INSERT INTO public.communication_native_sync_state
|
|
19
|
+
(work_id,binding,provider_kind,contact_id,normalized_email,purpose,event_kind,origin_provider_kind,origin_provider_event_id,remote_profile_id,remote_list_id,command_fingerprint)
|
|
20
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12) ON CONFLICT (work_id) DO NOTHING`, [work.id, binding, provider, contact, email, input.purpose, input.eventType, ...refs, fact]);
|
|
21
|
+
const state = (await db.query("SELECT command_fingerprint FROM public.communication_native_sync_state WHERE work_id=$1", [work.id])).rows[0];
|
|
22
|
+
if (state?.command_fingerprint !== fact)
|
|
23
|
+
throw new Error("native_sync_registration_conflict");
|
|
24
|
+
return { id: nativeText(work.id) };
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Trusted host transaction seam; registration validation remains shared with the standalone store. */
|
|
28
|
+
export async function registerNativeSyncWorkInTransaction(db, options, input) {
|
|
29
|
+
return nativeSyncRegistration(options, input)(db);
|
|
30
|
+
}
|
|
31
|
+
/** No sidecar claim/lease/drainer. Only runCommunicationSyncDispatch executes membership effects. */
|
|
32
|
+
export function createPostgresCommunicationSyncStore(env, options) {
|
|
33
|
+
const binding = nativeText(options.binding), provider = nativeText(options.providerKind), eventType = nativeSyncEventType(binding);
|
|
34
|
+
const lane = nativeTransactions(env, options, ["public.communication_native_sync_state", "public.outbox_events", "public.communication_recipient_consents"]);
|
|
35
|
+
const checkProvider = (value) => { if (value !== provider)
|
|
36
|
+
throw new Error("native_sync_binding_conflict"); };
|
|
37
|
+
return {
|
|
38
|
+
close: lane.close,
|
|
39
|
+
async registerWork(input) {
|
|
40
|
+
const register = nativeSyncRegistration(options, input);
|
|
41
|
+
return lane.run(db => register(db));
|
|
42
|
+
},
|
|
43
|
+
registerPreference(input) {
|
|
44
|
+
const email = nativeEmail(input.email), fingerprint = nativeFingerprint(email), purpose = nativeText(input.purpose);
|
|
45
|
+
if (!["tester_program", "marketing_launch_offer", "marketing_newsletter"].includes(purpose) || !["denied", "suppressed"].includes(input.state))
|
|
46
|
+
throw new Error("native_preference_invalid");
|
|
47
|
+
return lane.run(async (db) => {
|
|
48
|
+
await db.query("SELECT pg_advisory_xact_lock(hashtextextended($1,0))", [JSON.stringify([fingerprint, purpose])]);
|
|
49
|
+
const old = (await db.query("SELECT state,updated_at FROM public.communication_recipient_consents WHERE recipient_fingerprint=$1 AND purpose=$2 FOR UPDATE", [fingerprint, purpose])).rows[0];
|
|
50
|
+
const row = old?.state === input.state ? old : (await db.query(`INSERT INTO public.communication_recipient_consents (recipient_fingerprint,purpose,state)
|
|
51
|
+
VALUES ($1,$2,$3) ON CONFLICT (recipient_fingerprint,purpose) DO UPDATE SET state=excluded.state,updated_at=clock_timestamp() RETURNING state,updated_at`, [fingerprint, purpose, input.state])).rows[0];
|
|
52
|
+
let workId = null;
|
|
53
|
+
if (purpose !== "tester_program") {
|
|
54
|
+
const sourceKey = nativeFingerprint(JSON.stringify([fingerprint, purpose, input.state, nativeStamp(row.updated_at)]));
|
|
55
|
+
workId = (await registerNativeSyncWorkInTransaction(db, options, { sourceKey, contactId: fingerprint, normalizedEmail: email, eventType: input.state === "suppressed" ? "suppress" : "unsubscribe", purpose: purpose })).id;
|
|
56
|
+
}
|
|
57
|
+
return { updated: true, email, purpose: purpose, state: input.state, workId, alreadySuppressed: old?.state === input.state };
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
claimBatch(input) {
|
|
61
|
+
checkProvider(input.providerKind);
|
|
62
|
+
nativeInteger(input.batchSize, 1, 100);
|
|
63
|
+
nativeInteger(input.visibilitySeconds, 60, 3600);
|
|
64
|
+
nativeInteger(input.maxAttempts, 1, 20);
|
|
65
|
+
return lane.run(async (db) => {
|
|
66
|
+
const work = await options.rail(db).claimBatch({ eventTypes: [eventType], knownEventTypes: [eventType], batchSize: input.batchSize, visibilitySeconds: input.visibilitySeconds, maxAttempts: input.maxAttempts });
|
|
67
|
+
const events = [];
|
|
68
|
+
for (const row of work) {
|
|
69
|
+
const state = (await db.query("UPDATE public.communication_native_sync_state SET max_attempts=$4 WHERE work_id=$1 AND binding=$2 AND provider_kind=$3 RETURNING *", [row.id, binding, provider, input.maxAttempts])).rows[0];
|
|
70
|
+
if (!state)
|
|
71
|
+
throw new Error("native_sync_sidecar_missing");
|
|
72
|
+
const payload = (await db.query("SELECT payload FROM public.outbox_events WHERE id=$1", [row.id])).rows[0].payload;
|
|
73
|
+
nativeJson(payload);
|
|
74
|
+
events.push({ id: nativeText(row.id), claimToken: nativeText(row.metadata.claimToken), contactId: nativeText(state.contact_id), normalizedEmail: nativeEmail(state.normalized_email), eventType: state.event_kind,
|
|
75
|
+
purpose: state.purpose, payload: payload, attemptCount: nativeInteger(row.attempts - 1, 0, 19),
|
|
76
|
+
originProviderKind: state.origin_provider_kind, originProviderEventId: state.origin_provider_event_id, remoteProfileId: state.remote_profile_id, remoteListId: state.remote_list_id });
|
|
77
|
+
}
|
|
78
|
+
return events;
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
markSent(input) {
|
|
82
|
+
checkProvider(input.providerKind);
|
|
83
|
+
const summary = nativeJson(input.responseSummary ?? {}), remote = input.remoteProfileId == null ? null : nativeText(input.remoteProfileId);
|
|
84
|
+
return lane.run(async (db) => {
|
|
85
|
+
const row = (await db.query(`SELECT e.id FROM public.outbox_events e JOIN public.communication_native_sync_state s ON s.work_id=e.id
|
|
86
|
+
WHERE e.id=$1 AND s.binding=$2 AND s.provider_kind=$3 AND e.event_type=$4 AND e.status='processing' AND e.metadata->>'claimToken'=$5 FOR UPDATE OF e,s`, [input.eventId, binding, provider, eventType, input.claimToken])).rows[0];
|
|
87
|
+
if (!row)
|
|
88
|
+
return false;
|
|
89
|
+
if (!(await options.rail(db).markProcessed({ eventId: input.eventId, claimToken: input.claimToken })).applied)
|
|
90
|
+
throw new Error("native_sync_ack_lost");
|
|
91
|
+
await db.query("UPDATE public.communication_native_sync_state SET remote_profile_id=$2,response_summary=$3::jsonb WHERE work_id=$1", [input.eventId, remote, summary]);
|
|
92
|
+
return true;
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
markFailed(input) {
|
|
96
|
+
checkProvider(input.providerKind);
|
|
97
|
+
nativeInteger(input.backoffSeconds, 0, 86400);
|
|
98
|
+
return lane.run(async (db) => {
|
|
99
|
+
const row = (await db.query(`SELECT s.max_attempts FROM public.outbox_events e JOIN public.communication_native_sync_state s ON s.work_id=e.id
|
|
100
|
+
WHERE e.id=$1 AND s.binding=$2 AND s.provider_kind=$3 AND e.event_type=$4 AND e.status='processing' AND e.metadata->>'claimToken'=$5 FOR UPDATE OF e,s`, [input.eventId, binding, provider, eventType, input.claimToken])).rows[0];
|
|
101
|
+
if (!row)
|
|
102
|
+
return false;
|
|
103
|
+
const result = await options.rail(db).markFailed({ eventId: input.eventId, claimToken: input.claimToken, error: nativeText(input.error, 2000), outcome: input.retry ? "retry" : "discard", baseDelaySeconds: input.backoffSeconds, maxDelaySeconds: input.backoffSeconds, maxAttempts: nativeInteger(Number(row.max_attempts), 1, 20), snoozeSeconds: 300 });
|
|
104
|
+
if (!["failed", "discarded"].includes(result.status))
|
|
105
|
+
throw new Error("native_sync_ack_lost");
|
|
106
|
+
await db.query("UPDATE public.communication_native_sync_state SET response_summary=$2::jsonb WHERE work_id=$1", [input.eventId, JSON.stringify({ status: result.status })]);
|
|
107
|
+
return true;
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PostgresDataGatewayEnv, PostgresDataGatewayOptions } from "../data/index.js";
|
|
2
|
+
import type { CommunicationPurposeRegistry } from "./contracts/consent.js";
|
|
3
|
+
import { type NativeConsentDecision, type NativeConsentInput } from "./nativeOperations.js";
|
|
4
|
+
export interface NativeConsentOptions extends PostgresDataGatewayOptions {
|
|
5
|
+
registry?: CommunicationPurposeRegistry<string>;
|
|
6
|
+
/** Host-owned authoritative tester pause, read in the decision transaction. Missing means unpaused. */
|
|
7
|
+
testerPaused?: (db: import("../data/index.js").PgQueryExecutor, input: NativeConsentInput) => Promise<boolean>;
|
|
8
|
+
}
|
|
9
|
+
export interface NativeConsentEvaluator {
|
|
10
|
+
evaluate(input: NativeConsentInput): Promise<NativeConsentDecision>;
|
|
11
|
+
close(): Promise<void>;
|
|
12
|
+
readonly guarantees: {
|
|
13
|
+
readonly managedFrequencyCaps: false;
|
|
14
|
+
readonly legacyContactTouching: false;
|
|
15
|
+
readonly sendTimeFence: false;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** Bounded P4 policy, authoritative native permission and durable decision. Evaluation never sends. */
|
|
19
|
+
export declare function createPostgresConsentEvaluator(env: PostgresDataGatewayEnv, options?: NativeConsentOptions): NativeConsentEvaluator;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { evaluateCommunicationPolicy } from "./consentPolicy.js";
|
|
2
|
+
import { defaultCommunicationPurposeRegistry } from "./consentPurposeRegistry.js";
|
|
3
|
+
import { NativeConsentEvaluationUnavailableError } from "./nativeOperations.js";
|
|
4
|
+
import { nativeEmail, nativeFingerprint, nativeText, nativeTransactions } from "./postgresNativeOperations.js";
|
|
5
|
+
/** Bounded P4 policy, authoritative native permission and durable decision. Evaluation never sends. */
|
|
6
|
+
export function createPostgresConsentEvaluator(env, options = {}) {
|
|
7
|
+
const lane = nativeTransactions(env, options, ["public.communication_native_policy_decisions", "public.communication_recipient_consents", "public.notification_recipients"]);
|
|
8
|
+
const registry = options.registry ?? defaultCommunicationPurposeRegistry;
|
|
9
|
+
return {
|
|
10
|
+
close: lane.close,
|
|
11
|
+
guarantees: { managedFrequencyCaps: false, legacyContactTouching: false, sendTimeFence: false },
|
|
12
|
+
async evaluate(input) {
|
|
13
|
+
try {
|
|
14
|
+
const email = nativeEmail(input.email), fingerprint = nativeFingerprint(email), purpose = nativeText(input.purpose);
|
|
15
|
+
const recipientKind = input.recipientKind ?? "external_contact";
|
|
16
|
+
if (!["external_contact", "tester", "customer", "lead", "admin_internal"].includes(recipientKind))
|
|
17
|
+
throw new Error("native_recipient_kind_invalid");
|
|
18
|
+
return await lane.run(async (db) => {
|
|
19
|
+
const permission = (await db.query("SELECT state,captured_at,updated_at FROM public.communication_recipient_consents WHERE recipient_fingerprint=$1 AND purpose=$2 FOR SHARE", [fingerprint, purpose])).rows[0];
|
|
20
|
+
if (permission && !["granted", "denied", "suppressed"].includes(String(permission.state)))
|
|
21
|
+
throw new Error("native_permission_invalid");
|
|
22
|
+
const paused = purpose === "tester_program" && options.testerPaused ? await options.testerPaused(db, input) : false;
|
|
23
|
+
if (typeof paused !== "boolean")
|
|
24
|
+
throw new Error("native_pause_invalid");
|
|
25
|
+
let result = evaluateCommunicationPolicy({ purpose, recipientKind, permission: { state: permission ? permission.state : null, legacySequencePaused: paused } }, registry);
|
|
26
|
+
let activeRecipient = null;
|
|
27
|
+
if (purpose === "admin_notification") {
|
|
28
|
+
const rows = (await db.query("SELECT active FROM public.notification_recipients WHERE id=$1 AND email=$2 FOR SHARE", [input.sourceTable === "notification_recipients" ? input.sourceId ?? null : null, email])).rows;
|
|
29
|
+
activeRecipient = rows.length === 1 && rows[0].active === true;
|
|
30
|
+
if (!activeRecipient)
|
|
31
|
+
result = { decision: "blocked", reason: "notification_recipient_inactive" };
|
|
32
|
+
}
|
|
33
|
+
const row = (await db.query(`INSERT INTO public.communication_native_policy_decisions (recipient_fingerprint,purpose,allowed,reason,permission_snapshot,source_table,source_id)
|
|
34
|
+
VALUES ($1,$2,$3,$4,$5::jsonb,$6,$7) RETURNING id`, [fingerprint, purpose, result.decision === "allowed", result.reason, JSON.stringify({ permission: permission ?? null, legacySequencePaused: paused, activeRecipient, recipientKind }), input.sourceTable ?? null, input.sourceId ?? null])).rows[0];
|
|
35
|
+
return { allowed: result.decision === "allowed", reason: result.reason, decisionId: nativeText(row?.id) };
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new NativeConsentEvaluationUnavailableError(error);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { PostgresDataGatewayEnv } from "../data/index.js";
|
|
2
|
+
import type { NativeCommunicationsOptions, NativeDeliveryStore } from "./nativeOperations.js";
|
|
3
|
+
export declare function createPostgresDeliveryReconciliationPort(env: PostgresDataGatewayEnv, options: NativeCommunicationsOptions): NativeDeliveryStore;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { nativeEmail, nativeFingerprint, nativeInteger, nativeStamp, nativeText, nativeTime, nativeTransactions } from "./postgresNativeOperations.js";
|
|
2
|
+
const kinds = ["sent", "delayed", "delivered", "failed", "bounced", "complained"];
|
|
3
|
+
// Terminal/suppression precedence is monotonic; event chronology remains in the fact log.
|
|
4
|
+
const rank = (kind) => kind === null ? -1 : kinds.indexOf(kind);
|
|
5
|
+
export function createPostgresDeliveryReconciliationPort(env, options) {
|
|
6
|
+
const binding = nativeText(options.binding);
|
|
7
|
+
const lane = nativeTransactions(env, options, ["public.communication_native_sends", "public.communication_native_observations", "public.communication_recipient_consents"]);
|
|
8
|
+
const store = {
|
|
9
|
+
close: lane.close,
|
|
10
|
+
async registerNetworkTarget(input) {
|
|
11
|
+
if (input.evidence !== "network_accepted" || input.messageId.startsWith("captured:"))
|
|
12
|
+
throw new Error("native_network_acceptance_required");
|
|
13
|
+
const values = [binding, nativeText(input.sourceKey), nativeText(input.messageId), nativeFingerprint(nativeEmail(input.recipientEmail)), nativeText(input.templateReference), nativeTime(input.acceptedAt)];
|
|
14
|
+
return lane.run(async (db) => {
|
|
15
|
+
await db.query(`INSERT INTO public.communication_native_sends (binding,source_key,message_id,recipient_fingerprint,template_reference,accepted_at)
|
|
16
|
+
VALUES ($1,$2,$3,$4,$5,$6) ON CONFLICT (binding,source_key) DO NOTHING`, values);
|
|
17
|
+
const row = (await db.query(`SELECT * FROM public.communication_native_sends WHERE binding=$1 AND source_key=$2 FOR UPDATE`, values.slice(0, 2))).rows[0];
|
|
18
|
+
if (!row || row.message_id !== values[2] || row.recipient_fingerprint !== values[3] || row.template_reference !== values[4] || nativeStamp(row.accepted_at) !== values[5])
|
|
19
|
+
throw new Error("native_send_registration_conflict");
|
|
20
|
+
return { id: nativeText(row.id) };
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
findFrozenSends(input) {
|
|
24
|
+
const now = nativeTime(input.now), limit = nativeInteger(input.limit, 1, 100), grace = nativeInteger(input.graceMinutes, 0, 10080);
|
|
25
|
+
return lane.run(async (db) => (await db.query(`SELECT id,message_id FROM public.communication_native_sends
|
|
26
|
+
WHERE binding=$1 AND abandoned_at IS NULL AND (observed_state IS NULL OR observed_state IN ('sent','delayed'))
|
|
27
|
+
AND accepted_at <= $2::timestamptz - make_interval(mins => $3) ORDER BY last_poll_at NULLS FIRST, accepted_at,id LIMIT $4`, [binding, now, grace, limit])).rows.map(row => ({ id: nativeText(row.id), messageId: nativeText(row.message_id) })));
|
|
28
|
+
},
|
|
29
|
+
async applyObservation(input) {
|
|
30
|
+
const kind = input.kind;
|
|
31
|
+
if (!kinds.includes(kind) || !["poll", "callback"].includes(input.source))
|
|
32
|
+
throw new Error("native_observation_invalid");
|
|
33
|
+
const at = nativeTime(input.occurredAt), key = nativeText(input.observationKey), message = nativeText(input.messageId);
|
|
34
|
+
const fingerprint = input.recipientEmail === null ? null : nativeFingerprint(nativeEmail(input.recipientEmail));
|
|
35
|
+
await lane.run(async (db) => {
|
|
36
|
+
const send = (await db.query("SELECT * FROM public.communication_native_sends WHERE id=$1 AND binding=$2 FOR UPDATE", [input.sendId, binding])).rows[0];
|
|
37
|
+
if (!send || send.message_id !== message || (fingerprint !== null && send.recipient_fingerprint !== fingerprint))
|
|
38
|
+
throw new Error("native_observation_identity_conflict");
|
|
39
|
+
const fact = nativeFingerprint(JSON.stringify([input.sendId, message, kind, at, send.recipient_fingerprint]));
|
|
40
|
+
const inserted = await db.query(`INSERT INTO public.communication_native_observations (binding,observation_key,send_id,kind,occurred_at,source,fact_fingerprint)
|
|
41
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7) ON CONFLICT (binding,observation_key) DO NOTHING RETURNING observation_key`, [binding, key, input.sendId, kind, at, input.source, fact]);
|
|
42
|
+
if (!inserted.rows.length) {
|
|
43
|
+
const old = (await db.query("SELECT fact_fingerprint FROM public.communication_native_observations WHERE binding=$1 AND observation_key=$2", [binding, key])).rows[0];
|
|
44
|
+
if (old?.fact_fingerprint !== fact)
|
|
45
|
+
throw new Error("native_observation_replay_conflict");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (rank(kind) > rank(send.observed_state) || (kind === send.observed_state && at > nativeStamp(send.observed_at))) {
|
|
49
|
+
await db.query("UPDATE public.communication_native_sends SET observed_state=$3,observed_at=$4 WHERE id=$1 AND binding=$2", [input.sendId, binding, kind, at]);
|
|
50
|
+
}
|
|
51
|
+
if (kind === "bounced" || kind === "complained") {
|
|
52
|
+
for (const purpose of ["marketing_launch_offer", "marketing_newsletter", "tester_program"])
|
|
53
|
+
await db.query(`INSERT INTO public.communication_recipient_consents (recipient_fingerprint,purpose,state,captured_at,updated_at)
|
|
54
|
+
VALUES ($1,$2,'suppressed',$3,$3) ON CONFLICT (recipient_fingerprint,purpose) DO UPDATE SET state='suppressed',updated_at=greatest(communication_recipient_consents.updated_at,excluded.updated_at)`, [send.recipient_fingerprint, purpose, at]);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
applyPolledEvent(input) {
|
|
59
|
+
return store.applyObservation({ sendId: input.sendId, messageId: input.messageId, observationKey: nativeFingerprint(JSON.stringify([input.sendId, input.eventType, nativeTime(input.eventAt)])), kind: input.eventType, occurredAt: input.eventAt, recipientEmail: input.recipientEmail, source: "poll" });
|
|
60
|
+
},
|
|
61
|
+
async recordPollAttempt(input) {
|
|
62
|
+
await lane.run(async (db) => {
|
|
63
|
+
const result = await db.query("UPDATE public.communication_native_sends SET last_poll_at=greatest(last_poll_at,$3::timestamptz),not_found_count=0 WHERE id=$1 AND binding=$2 RETURNING id", [input.sendId, binding, nativeTime(input.attemptedAt)]);
|
|
64
|
+
if (!result.rows.length)
|
|
65
|
+
throw new Error("native_send_not_found");
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
recordSendNotFound(input) {
|
|
69
|
+
nativeInteger(input.threshold, 1, 100);
|
|
70
|
+
return lane.run(async (db) => {
|
|
71
|
+
const send = (await db.query("SELECT abandoned_at FROM public.communication_native_sends WHERE id=$1 AND binding=$2 FOR UPDATE", [input.sendId, binding])).rows[0];
|
|
72
|
+
if (!send)
|
|
73
|
+
throw new Error("native_send_not_found");
|
|
74
|
+
const result = (await db.query(`UPDATE public.communication_native_sends SET not_found_count=least(not_found_count,2147483646)+1,last_poll_at=clock_timestamp(),
|
|
75
|
+
abandoned_at=CASE WHEN not_found_count >= $3-1 THEN coalesce(abandoned_at,clock_timestamp()) ELSE abandoned_at END WHERE id=$1 AND binding=$2 RETURNING abandoned_at`, [input.sendId, binding, input.threshold])).rows[0];
|
|
76
|
+
return { abandoned: send.abandoned_at === null && result.abandoned_at !== null };
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
findByMessageId(messageId) {
|
|
80
|
+
const message = nativeText(messageId);
|
|
81
|
+
return lane.run(async (db) => {
|
|
82
|
+
const rows = (await db.query("SELECT id FROM public.communication_native_sends WHERE binding=$1 AND message_id=$2", [binding, message])).rows;
|
|
83
|
+
if (rows.length > 1)
|
|
84
|
+
throw new Error("native_message_identity_ambiguous");
|
|
85
|
+
return rows.length ? { id: nativeText(rows[0].id) } : null;
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
async listEvidence(input) {
|
|
89
|
+
const limit = nativeInteger(input.limit, 1, 100);
|
|
90
|
+
const ids = await lane.run(async (db) => (await db.query("SELECT id FROM public.communication_native_sends WHERE binding=$1 ORDER BY accepted_at DESC,id DESC LIMIT $2", [binding, limit])).rows.map(row => nativeText(row.id)));
|
|
91
|
+
const evidence = [];
|
|
92
|
+
for (const id of ids) {
|
|
93
|
+
const row = await store.readEvidence(id);
|
|
94
|
+
if (row)
|
|
95
|
+
evidence.push(row);
|
|
96
|
+
}
|
|
97
|
+
return evidence;
|
|
98
|
+
},
|
|
99
|
+
readEvidence(id) {
|
|
100
|
+
return lane.run(async (db) => {
|
|
101
|
+
const row = (await db.query("SELECT * FROM public.communication_native_sends WHERE id=$1 AND binding=$2", [id, binding])).rows[0];
|
|
102
|
+
if (!row)
|
|
103
|
+
return null;
|
|
104
|
+
const observations = (await db.query("SELECT observation_key,kind,occurred_at,source FROM public.communication_native_observations WHERE send_id=$1 AND binding=$2 ORDER BY occurred_at,observation_key", [id, binding])).rows;
|
|
105
|
+
return { id: nativeText(row.id), sourceKey: nativeText(row.source_key), messageId: nativeText(row.message_id), acceptedAt: nativeStamp(row.accepted_at),
|
|
106
|
+
observedState: row.observed_state, observedAt: row.observed_at === null ? null : nativeStamp(row.observed_at),
|
|
107
|
+
lastPollAt: row.last_poll_at === null ? null : nativeStamp(row.last_poll_at), notFoundCount: nativeInteger(Number(row.not_found_count), 0, 2147483647), abandonedAt: row.abandoned_at === null ? null : nativeStamp(row.abandoned_at),
|
|
108
|
+
observations: observations.map(fact => ({ key: nativeText(fact.observation_key), kind: fact.kind, occurredAt: nativeStamp(fact.occurred_at), source: fact.source })) };
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
return store;
|
|
113
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PgQueryExecutor, type PostgresDataGatewayEnv, type PostgresDataGatewayOptions } from "../data/index.js";
|
|
2
|
+
export declare const nativeFingerprint: (value: string) => string;
|
|
3
|
+
export declare function nativeText(value: unknown, max?: number): string;
|
|
4
|
+
export declare function nativeEmail(value: unknown): string;
|
|
5
|
+
export declare function nativeTime(value: unknown): string;
|
|
6
|
+
export declare function nativeInteger(value: number, min: number, max: number): number;
|
|
7
|
+
export declare function nativeJson(value: unknown): string;
|
|
8
|
+
export declare const nativeStamp: (value: unknown) => string;
|
|
9
|
+
/** Private capability-local helper. The host owns the connection authority; no SET ROLE or runtime DDL. */
|
|
10
|
+
export declare function nativeTransactions(env: PostgresDataGatewayEnv, options: PostgresDataGatewayOptions, tables: string[]): {
|
|
11
|
+
close: () => Promise<void>;
|
|
12
|
+
run: <T>(work: (db: PgQueryExecutor) => Promise<T>) => Promise<T>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createPostgresRoleFreeTransactionLane } from "../data/index.js";
|
|
3
|
+
export const nativeFingerprint = (value) => createHash("sha256").update(value).digest("hex");
|
|
4
|
+
export function nativeText(value, max = 256) {
|
|
5
|
+
if (typeof value !== "string" || !value.trim() || value.length > max || [...value].some(character => character.codePointAt(0) < 32 || character.codePointAt(0) === 127))
|
|
6
|
+
throw new Error("native_communications_text_invalid");
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
export function nativeEmail(value) {
|
|
10
|
+
const email = nativeText(value, 320).trim().toLowerCase();
|
|
11
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
|
|
12
|
+
throw new Error("native_communications_email_invalid");
|
|
13
|
+
return email;
|
|
14
|
+
}
|
|
15
|
+
export function nativeTime(value) {
|
|
16
|
+
const parts = typeof value === "string" ? /^\d{4}-\d{2}-\d{2}T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.(\d{1,6}))?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.exec(value) : null;
|
|
17
|
+
if (!parts || typeof value !== "string" || !Number.isFinite(Date.parse(value)))
|
|
18
|
+
throw new Error("native_communications_time_invalid");
|
|
19
|
+
if (new Date(value.slice(0, 10) + "T00:00:00Z").toISOString().slice(0, 10) !== value.slice(0, 10))
|
|
20
|
+
throw new Error("native_communications_time_invalid");
|
|
21
|
+
// PostgreSQL stores microseconds. Never collapse two distinct immutable facts to JS milliseconds.
|
|
22
|
+
return new Date(value).toISOString().replace(/\.\d{3}Z$/, `.${(parts[1] ?? "").padEnd(6, "0")}Z`);
|
|
23
|
+
}
|
|
24
|
+
export function nativeInteger(value, min, max) {
|
|
25
|
+
if (!Number.isInteger(value) || value < min || value > max)
|
|
26
|
+
throw new Error("native_communications_bound_invalid");
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
export function nativeJson(value) {
|
|
30
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
31
|
+
throw new Error("native_communications_object_invalid");
|
|
32
|
+
const text = JSON.stringify(value);
|
|
33
|
+
if (text.length > 4096)
|
|
34
|
+
throw new Error("native_communications_object_too_large");
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
export const nativeStamp = (value) => nativeTime(value instanceof Date ? value.toISOString() : value);
|
|
38
|
+
/** Private capability-local helper. The host owns the connection authority; no SET ROLE or runtime DDL. */
|
|
39
|
+
export function nativeTransactions(env, options, tables) {
|
|
40
|
+
if (!env.connectionString.trim())
|
|
41
|
+
throw new Error("communications_database_url_required");
|
|
42
|
+
const lane = createPostgresRoleFreeTransactionLane(env, options);
|
|
43
|
+
return {
|
|
44
|
+
close: lane.close,
|
|
45
|
+
run: (work) => lane.run(async (gateway) => {
|
|
46
|
+
const db = gateway;
|
|
47
|
+
// Effective privileges include PUBLIC, role membership and column/default grants.
|
|
48
|
+
// Missing relations, malformed responses and untrusted execution roles all refuse.
|
|
49
|
+
const row = (await db.query(`SELECT current_user IN ('anon','authenticated','authenticator') AS browser,
|
|
50
|
+
EXISTS (SELECT 1 FROM unnest($1::text[]) t(name), pg_roles r
|
|
51
|
+
WHERE r.rolname IN ('anon','authenticated','authenticator') AND
|
|
52
|
+
(has_table_privilege(r.oid, t.name, 'SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
|
|
53
|
+
OR has_any_column_privilege(r.oid, t.name, 'SELECT,INSERT,UPDATE,REFERENCES')))
|
|
54
|
+
OR EXISTS (SELECT 1 FROM unnest($1::text[]) t(name), pg_class c,
|
|
55
|
+
LATERAL aclexplode(coalesce(c.relacl, acldefault('r',c.relowner))) a WHERE c.oid = t.name::regclass AND a.grantee = 0)
|
|
56
|
+
OR EXISTS (SELECT 1 FROM unnest($1::text[]) t(name), pg_attribute c,
|
|
57
|
+
LATERAL aclexplode(c.attacl) a WHERE c.attrelid = t.name::regclass AND a.grantee = 0) AS unsafe`, [tables])).rows[0];
|
|
58
|
+
if (row?.browser !== false || row?.unsafe !== false)
|
|
59
|
+
throw new Error("native_communications_privileges_unsafe");
|
|
60
|
+
return work(db);
|
|
61
|
+
}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PostgresDataGatewayEnv, PostgresDataGatewayOptions } from "../data/index.js";
|
|
2
|
+
import type { NativeNotificationRecipient, NativeNotificationType } from "./nativeOperations.js";
|
|
3
|
+
export interface NativeNotificationRecipientsOptions extends PostgresDataGatewayOptions {
|
|
4
|
+
operatorId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface NativeNotificationRecipientsPort {
|
|
7
|
+
listNotificationRecipients(input: {
|
|
8
|
+
notification_type: NativeNotificationType;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
recipients: NativeNotificationRecipient[];
|
|
11
|
+
}>;
|
|
12
|
+
createNotificationRecipient(input: {
|
|
13
|
+
email: string;
|
|
14
|
+
name: string | null;
|
|
15
|
+
notification_type: NativeNotificationType;
|
|
16
|
+
active: true;
|
|
17
|
+
}): Promise<{
|
|
18
|
+
created: true;
|
|
19
|
+
email: string;
|
|
20
|
+
notification_type: NativeNotificationType;
|
|
21
|
+
}>;
|
|
22
|
+
updateNotificationRecipient(input: {
|
|
23
|
+
recipientId: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
updated: true;
|
|
27
|
+
recipientId: string;
|
|
28
|
+
}>;
|
|
29
|
+
deleteNotificationRecipient(input: {
|
|
30
|
+
recipientId: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
deleted: true;
|
|
33
|
+
recipientId: string;
|
|
34
|
+
}>;
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export declare function createPostgresNotificationRecipientsPort(env: PostgresDataGatewayEnv, options: NativeNotificationRecipientsOptions): NativeNotificationRecipientsPort;
|