@openlup/platform 0.15.0 → 0.17.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 +124 -0
- package/README.md +633 -6
- 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 +51 -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/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 +46 -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/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/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/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/adminAuthBinding.d.ts +28 -0
- package/dist/identity/adminAuthBinding.js +66 -0
- package/dist/identity/adminAuthorization.d.ts +34 -0
- package/dist/identity/adminAuthorization.js +72 -0
- package/dist/identity/adminContracts.d.ts +70 -0
- package/dist/identity/adminContracts.js +43 -0
- package/dist/identity/adminMagicLinkHandler.d.ts +39 -0
- package/dist/identity/adminMagicLinkHandler.js +94 -0
- package/dist/identity/adminMeHandler.d.ts +15 -0
- package/dist/identity/adminMeHandler.js +49 -0
- package/dist/identity/adminPreflight.d.ts +16 -0
- package/dist/identity/adminPreflight.js +38 -0
- package/dist/identity/adminUserActionPorts.d.ts +31 -0
- package/dist/identity/adminUserActionPorts.js +51 -0
- package/dist/identity/adminUserHandlers.d.ts +38 -0
- package/dist/identity/adminUserHandlers.js +140 -0
- package/dist/identity/authVerifyUrl.d.ts +6 -0
- package/dist/identity/authVerifyUrl.js +54 -0
- package/dist/identity/contracts/contracts.d.ts +8 -0
- package/dist/identity/contracts/contracts.js +2 -0
- package/dist/identity/contracts/emailTrust.d.ts +3 -0
- package/dist/identity/contracts/emailTrust.js +4 -0
- package/dist/identity/contracts/index.d.ts +8 -0
- package/dist/identity/contracts/index.js +8 -0
- package/dist/identity/contracts/oidc.d.ts +3 -0
- package/dist/identity/contracts/oidc.js +9 -0
- package/dist/identity/contracts/operatorAuth.d.ts +35 -0
- package/dist/identity/contracts/operatorAuth.js +53 -0
- package/dist/identity/contracts/operatorInvitations.d.ts +37 -0
- package/dist/identity/contracts/operatorInvitations.js +1 -0
- package/dist/identity/contracts/ports.d.ts +22 -0
- package/dist/identity/contracts/ports.js +1 -0
- package/dist/identity/contracts/privacy.d.ts +62 -0
- package/dist/identity/contracts/privacy.js +99 -0
- package/dist/identity/contracts/providerList.d.ts +3 -0
- package/dist/identity/contracts/providerList.js +11 -0
- package/dist/identity/contracts/types.d.ts +16 -0
- package/dist/identity/contracts/types.js +4 -0
- package/dist/identity/contribution.d.ts +8 -0
- package/dist/identity/contribution.js +22 -0
- package/dist/identity/customerAuth.d.ts +8 -0
- package/dist/identity/customerAuth.js +1 -0
- package/dist/identity/customerAuthorization.d.ts +5 -0
- package/dist/identity/customerAuthorization.js +22 -0
- package/dist/identity/customerContracts.d.ts +42 -0
- package/dist/identity/customerContracts.js +43 -0
- package/dist/identity/customerIdentityBinding.d.ts +44 -0
- package/dist/identity/customerIdentityBinding.js +60 -0
- package/dist/identity/customerIdentityVerifier.d.ts +8 -0
- package/dist/identity/customerIdentityVerifier.js +101 -0
- package/dist/identity/customerMagicLinkHandler.d.ts +38 -0
- package/dist/identity/customerMagicLinkHandler.js +115 -0
- package/dist/identity/customerMeHandler.d.ts +11 -0
- package/dist/identity/customerMeHandler.js +46 -0
- package/dist/identity/customerPorts.d.ts +4 -0
- package/dist/identity/customerPorts.js +1 -0
- package/dist/identity/customerSessionBinding.d.ts +38 -0
- package/dist/identity/customerSessionBinding.js +80 -0
- package/dist/identity/customerSessionIssuer.d.ts +10 -0
- package/dist/identity/customerSessionIssuer.js +57 -0
- package/dist/identity/customerVerifyOtpHandler.d.ts +8 -0
- package/dist/identity/customerVerifyOtpHandler.js +41 -0
- package/dist/identity/directOperatorInvitationStore.d.ts +19 -0
- package/dist/identity/directOperatorInvitationStore.js +193 -0
- package/dist/identity/emailTrustPolicy.d.ts +14 -0
- package/dist/identity/emailTrustPolicy.js +16 -0
- package/dist/identity/identityPersonalDataContributor.d.ts +7 -0
- package/dist/identity/identityPersonalDataContributor.js +46 -0
- package/dist/identity/identityReadiness.d.ts +10 -0
- package/dist/identity/identityReadiness.js +25 -0
- package/dist/identity/index.d.ts +67 -0
- package/dist/identity/index.js +66 -0
- package/dist/identity/inviteAdminUserUseCase.d.ts +89 -0
- package/dist/identity/inviteAdminUserUseCase.js +75 -0
- package/dist/identity/jwtLibrary.d.ts +54 -0
- package/dist/identity/jwtLibrary.js +1 -0
- package/dist/identity/machineActorWriteFence.d.ts +4 -0
- package/dist/identity/machineActorWriteFence.js +13 -0
- package/dist/identity/magicLinkPorts.d.ts +28 -0
- package/dist/identity/magicLinkPorts.js +1 -0
- package/dist/identity/managedAccountLinkStore.d.ts +2 -0
- package/dist/identity/managedAccountLinkStore.js +93 -0
- package/dist/identity/managedAdminAuthVerifier.d.ts +7 -0
- package/dist/identity/managedAdminAuthVerifier.js +27 -0
- package/dist/identity/managedAdminUserGateways.d.ts +123 -0
- package/dist/identity/managedAdminUserGateways.js +127 -0
- package/dist/identity/managedClient.d.ts +90 -0
- package/dist/identity/managedClient.js +10 -0
- package/dist/identity/managedClientAuthLink.d.ts +3 -0
- package/dist/identity/managedClientAuthLink.js +115 -0
- package/dist/identity/managedCustomerMe.d.ts +13 -0
- package/dist/identity/managedCustomerMe.js +30 -0
- package/dist/identity/managedEmailTrustPolicy.d.ts +11 -0
- package/dist/identity/managedEmailTrustPolicy.js +105 -0
- package/dist/identity/managedIdentityVerifier.d.ts +2 -0
- package/dist/identity/managedIdentityVerifier.js +16 -0
- package/dist/identity/managedPrivacy.d.ts +4 -0
- package/dist/identity/managedPrivacy.js +39 -0
- package/dist/identity/messages.d.ts +29 -0
- package/dist/identity/messages.js +39 -0
- package/dist/identity/oidcIdentityVerifier.d.ts +45 -0
- package/dist/identity/oidcIdentityVerifier.js +309 -0
- package/dist/identity/oidcPrincipal.d.ts +2 -0
- package/dist/identity/oidcPrincipal.js +10 -0
- package/dist/identity/operatorAdminAuth.d.ts +6 -0
- package/dist/identity/operatorAdminAuth.js +13 -0
- package/dist/identity/operatorAuthHandlers.d.ts +18 -0
- package/dist/identity/operatorAuthHandlers.js +71 -0
- package/dist/identity/operatorIdentityVerifier.d.ts +8 -0
- package/dist/identity/operatorIdentityVerifier.js +19 -0
- package/dist/identity/operatorInvitationLifecycle.d.ts +7 -0
- package/dist/identity/operatorInvitationLifecycle.js +15 -0
- package/dist/identity/operatorInvitationPorts.d.ts +31 -0
- package/dist/identity/operatorInvitationPorts.js +1 -0
- package/dist/identity/operatorPorts.d.ts +37 -0
- package/dist/identity/operatorPorts.js +1 -0
- package/dist/identity/operatorSession.d.ts +13 -0
- package/dist/identity/operatorSession.js +31 -0
- package/dist/identity/operatorTokenAdminAuth.d.ts +15 -0
- package/dist/identity/operatorTokenAdminAuth.js +50 -0
- package/dist/identity/personalDataRegistry.d.ts +4 -0
- package/dist/identity/personalDataRegistry.js +11 -0
- package/dist/identity/platformAdminAuth.d.ts +15 -0
- package/dist/identity/platformAdminAuth.js +1 -0
- package/dist/identity/ports.d.ts +127 -0
- package/dist/identity/ports.js +38 -0
- package/dist/identity/postgresAccountLinkStore.d.ts +7 -0
- package/dist/identity/postgresAccountLinkStore.js +52 -0
- package/dist/identity/postgresCustomerMe.d.ts +3 -0
- package/dist/identity/postgresCustomerMe.js +21 -0
- package/dist/identity/postgresCustomerRecovery.d.ts +11 -0
- package/dist/identity/postgresCustomerRecovery.js +57 -0
- package/dist/identity/postgresOperatorIdentity.d.ts +5 -0
- package/dist/identity/postgresOperatorIdentity.js +137 -0
- package/dist/identity/postgresPrivacy.d.ts +7 -0
- package/dist/identity/postgresPrivacy.js +126 -0
- package/dist/identity/privacyHandlers.d.ts +10 -0
- package/dist/identity/privacyHandlers.js +35 -0
- package/dist/identity/privacyPorts.d.ts +72 -0
- package/dist/identity/privacyPorts.js +8 -0
- package/dist/identity/privacyUseCases.d.ts +5 -0
- package/dist/identity/privacyUseCases.js +55 -0
- package/dist/identity/reconcileAccountForPrincipal.d.ts +20 -0
- package/dist/identity/reconcileAccountForPrincipal.js +66 -0
- package/dist/identity/reconcileAccountHandler.d.ts +11 -0
- package/dist/identity/reconcileAccountHandler.js +30 -0
- package/dist/identity/removeAdminUserUseCase.d.ts +31 -0
- package/dist/identity/removeAdminUserUseCase.js +60 -0
- package/dist/identity/response.d.ts +3 -0
- package/dist/identity/response.js +2 -0
- package/dist/identity/sql.d.ts +44 -0
- package/dist/identity/sql.js +10 -0
- package/package.json +22 -2
- package/release-gates.json +63 -8
- package/sql/20260807190000_comms_outbox_rail.sql +329 -0
- package/sql/20260810120001_transactional_delivery_receipts.sql +209 -0
- package/sql/20260810180001_self_host_actor_auth.sql +40 -0
- package/sql/20260810204057_customer_identity_read.sql +31 -0
- package/sql/20260813120000_communications_control_plane.sql +568 -0
- package/sql/20260814090000_customer_selfservice_recovery.sql +477 -0
- package/sql/20260901143000_admin_membership_authority_foundation.sql +234 -0
- package/sql/20261018120000_identity_operator_invitations.sql +42 -0
- package/sql/20261018180000_identity_operator_challenges.sql +56 -0
- package/sql/20261018190000_identity_privacy_erasures.sql +15 -0
- package/sql/20261019200000_communications_native_operations.sql +68 -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 +51 -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/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 +46 -0
- package/src/communications/integrationEventSignature.ts +49 -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/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/http/index.ts +1 -0
- package/src/http/webhookSignature.ts +96 -0
- package/src/identity/adminAuthBinding.ts +76 -0
- package/src/identity/adminAuthorization.ts +106 -0
- package/src/identity/adminContracts.ts +52 -0
- package/src/identity/adminMagicLinkHandler.ts +132 -0
- package/src/identity/adminMeHandler.ts +64 -0
- package/src/identity/adminPreflight.ts +46 -0
- package/src/identity/adminUserActionPorts.ts +78 -0
- package/src/identity/adminUserHandlers.ts +174 -0
- package/src/identity/authVerifyUrl.ts +56 -0
- package/src/identity/contracts/contracts.ts +15 -0
- package/src/identity/contracts/emailTrust.ts +5 -0
- package/src/identity/contracts/index.ts +8 -0
- package/src/identity/contracts/oidc.ts +10 -0
- package/src/identity/contracts/operatorAuth.ts +61 -0
- package/src/identity/contracts/operatorInvitations.ts +32 -0
- package/src/identity/contracts/ports.ts +25 -0
- package/src/identity/contracts/privacy.ts +86 -0
- package/src/identity/contracts/providerList.ts +13 -0
- package/src/identity/contracts/types.ts +25 -0
- package/src/identity/contribution.ts +29 -0
- package/src/identity/customerAuth.ts +3 -0
- package/src/identity/customerAuthorization.ts +38 -0
- package/src/identity/customerContracts.ts +52 -0
- package/src/identity/customerIdentityBinding.ts +125 -0
- package/src/identity/customerIdentityVerifier.ts +141 -0
- package/src/identity/customerMagicLinkHandler.ts +171 -0
- package/src/identity/customerMeHandler.ts +64 -0
- package/src/identity/customerPorts.ts +2 -0
- package/src/identity/customerSessionBinding.ts +114 -0
- package/src/identity/customerSessionIssuer.ts +71 -0
- package/src/identity/customerVerifyOtpHandler.ts +44 -0
- package/src/identity/directOperatorInvitationStore.ts +178 -0
- package/src/identity/emailTrustPolicy.ts +16 -0
- package/src/identity/identityPersonalDataContributor.ts +48 -0
- package/src/identity/identityReadiness.ts +26 -0
- package/src/identity/index.ts +69 -0
- package/src/identity/inviteAdminUserUseCase.ts +134 -0
- package/src/identity/jwtLibrary.ts +24 -0
- package/src/identity/machineActorWriteFence.ts +19 -0
- package/src/identity/magicLinkPorts.ts +7 -0
- package/src/identity/managedAccountLinkStore.ts +105 -0
- package/src/identity/managedAdminAuthVerifier.ts +40 -0
- package/src/identity/managedAdminUserGateways.ts +164 -0
- package/src/identity/managedClient.ts +58 -0
- package/src/identity/managedClientAuthLink.ts +120 -0
- package/src/identity/managedCustomerMe.ts +52 -0
- package/src/identity/managedEmailTrustPolicy.ts +90 -0
- package/src/identity/managedIdentityVerifier.ts +20 -0
- package/src/identity/managedPrivacy.ts +37 -0
- package/src/identity/messages.ts +41 -0
- package/src/identity/oidcIdentityVerifier.ts +229 -0
- package/src/identity/oidcPrincipal.ts +10 -0
- package/src/identity/operatorAdminAuth.ts +14 -0
- package/src/identity/operatorAuthHandlers.ts +52 -0
- package/src/identity/operatorIdentityVerifier.ts +19 -0
- package/src/identity/operatorInvitationLifecycle.ts +14 -0
- package/src/identity/operatorInvitationPorts.ts +11 -0
- package/src/identity/operatorPorts.ts +11 -0
- package/src/identity/operatorSession.ts +30 -0
- package/src/identity/operatorTokenAdminAuth.ts +79 -0
- package/src/identity/personalDataRegistry.ts +8 -0
- package/src/identity/platformAdminAuth.ts +7 -0
- package/src/identity/ports.ts +158 -0
- package/src/identity/postgresAccountLinkStore.ts +49 -0
- package/src/identity/postgresCustomerMe.ts +33 -0
- package/src/identity/postgresCustomerRecovery.ts +72 -0
- package/src/identity/postgresOperatorIdentity.ts +123 -0
- package/src/identity/postgresPrivacy.ts +117 -0
- package/src/identity/privacyHandlers.ts +33 -0
- package/src/identity/privacyPorts.ts +52 -0
- package/src/identity/privacyUseCases.ts +48 -0
- package/src/identity/reconcileAccountForPrincipal.ts +99 -0
- package/src/identity/reconcileAccountHandler.ts +36 -0
- package/src/identity/removeAdminUserUseCase.ts +85 -0
- package/src/identity/response.ts +3 -0
- package/src/identity/sql.ts +10 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { identityMessages } from "./messages.js";
|
|
2
|
+
export async function runRemoveAdminUserUseCase(request, gateway, messages = identityMessages.en, invitationStore) {
|
|
3
|
+
try {
|
|
4
|
+
if (!request.accessToken) {
|
|
5
|
+
return { status: 401, body: { code: "UNAUTHORIZED", error: messages.unauthorized } };
|
|
6
|
+
}
|
|
7
|
+
const { user, error: authError } = await gateway.getUser(request.accessToken);
|
|
8
|
+
if (authError || !user) {
|
|
9
|
+
return { status: 401, body: { code: "INVALID_TOKEN", error: messages.invalidToken } };
|
|
10
|
+
}
|
|
11
|
+
const callerAdmin = await gateway.findAdminUser(user.id);
|
|
12
|
+
if (!callerAdmin || callerAdmin.role !== "admin") {
|
|
13
|
+
return { status: 403, body: { code: "REMOVE_FORBIDDEN", error: messages.removeForbidden } };
|
|
14
|
+
}
|
|
15
|
+
if (!request.userId) {
|
|
16
|
+
return { status: 400, body: { code: "USER_ID_REQUIRED", error: messages.userIdRequired } };
|
|
17
|
+
}
|
|
18
|
+
if (request.userId === user.id) {
|
|
19
|
+
return { status: 403, body: { code: "SELF_REVOKE_FORBIDDEN", error: messages.selfRemoveForbidden } };
|
|
20
|
+
}
|
|
21
|
+
if (invitationStore) {
|
|
22
|
+
try {
|
|
23
|
+
await invitationStore.remove({ actorPrincipalId: user.id, targetPrincipalId: request.userId });
|
|
24
|
+
return { status: 200, body: { revoked: true } };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const failure = error;
|
|
28
|
+
if (failure.identityCode)
|
|
29
|
+
return { status: failure.bffCode === "FORBIDDEN" ? 403 : failure.bffCode === "BAD_REQUEST" ? 400 : 409, body: { code: failure.identityCode, error: failure.identityCode } };
|
|
30
|
+
return mapRevokeError(failure.message ?? "revoke_failed", messages);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const { error: revokeError } = await gateway.revokeAdminUser(request.userId);
|
|
34
|
+
if (revokeError) {
|
|
35
|
+
return mapRevokeError(revokeError.message, messages);
|
|
36
|
+
}
|
|
37
|
+
return { status: 200, body: { revoked: true } };
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
return { status: 500, body: { code: "IDENTITY_ACTION_FAILED", error: String(err) } };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function mapRevokeError(message, messages) {
|
|
44
|
+
if (message.includes("last_active_human_admin") || message.includes("last_admin_lockout")) {
|
|
45
|
+
return { status: 409, body: { code: "LAST_ACTIVE_HUMAN_ADMIN", error: messages.lastAdmin } };
|
|
46
|
+
}
|
|
47
|
+
if (message.includes("self_revoke_forbidden")) {
|
|
48
|
+
return { status: 403, body: { code: "SELF_REVOKE_FORBIDDEN", error: messages.selfRevoke } };
|
|
49
|
+
}
|
|
50
|
+
if (message.includes("machine_actor_revoke_forbidden")) {
|
|
51
|
+
return { status: 403, body: { code: "MACHINE_ACTOR_REVOKE_FORBIDDEN", error: messages.machineRevoke } };
|
|
52
|
+
}
|
|
53
|
+
if (message.includes("target_not_found") || message.includes("target_not_active")) {
|
|
54
|
+
return { status: 400, body: { code: "ADMIN_NOT_FOUND", error: messages.adminNotFound } };
|
|
55
|
+
}
|
|
56
|
+
if (message.includes("forbidden")) {
|
|
57
|
+
return { status: 403, body: { code: "ADMIN_REQUIRED", error: messages.adminRequired } };
|
|
58
|
+
}
|
|
59
|
+
return { status: 500, body: { code: "REVOKE_FAILED", error: messages.revokeFailed(message) } };
|
|
60
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** A projection of canonical migration units, never a second migration chain. */
|
|
2
|
+
export declare const IDENTITY_MIGRATIONS: readonly [{
|
|
3
|
+
readonly id: "20260810180001_self_host_actor_auth";
|
|
4
|
+
readonly catalogPath: "db/platform/migrations/20260810180001_self_host_actor_auth.sql";
|
|
5
|
+
readonly position: 11;
|
|
6
|
+
readonly sha256: "84c80d328785151f1fdb5fc4b69220469ffb9c8579054c473ead910a273dfe7b";
|
|
7
|
+
readonly url: URL;
|
|
8
|
+
}, {
|
|
9
|
+
readonly id: "20260810204057_customer_identity_read";
|
|
10
|
+
readonly catalogPath: "db/platform/migrations/20260810204057_customer_identity_read.sql";
|
|
11
|
+
readonly position: 12;
|
|
12
|
+
readonly sha256: "1aa626c0187a4ed9d08f152540e0d17c68cd678d2caf3e896ac444b5a38aafe3";
|
|
13
|
+
readonly url: URL;
|
|
14
|
+
}, {
|
|
15
|
+
readonly id: "20260814090000_customer_selfservice_recovery";
|
|
16
|
+
readonly catalogPath: "db/platform/migrations/20260814090000_customer_selfservice_recovery.sql";
|
|
17
|
+
readonly position: 29;
|
|
18
|
+
readonly sha256: "ca7f58994533727eb58da148d549ff986fe8f55bb2ffc9eaf61e7d239675ba2e";
|
|
19
|
+
readonly url: URL;
|
|
20
|
+
}, {
|
|
21
|
+
readonly id: "20260901143000_admin_membership_authority_foundation";
|
|
22
|
+
readonly catalogPath: "db/platform/migrations/20260901143000_admin_membership_authority_foundation.sql";
|
|
23
|
+
readonly position: 60;
|
|
24
|
+
readonly sha256: "bb4703b669d17e5a0eb4d9a4e8889d12e5286d4b5a813226a77ef2b71df8281f";
|
|
25
|
+
readonly url: URL;
|
|
26
|
+
}, {
|
|
27
|
+
readonly id: "20261018120000_identity_operator_invitations";
|
|
28
|
+
readonly catalogPath: "db/platform/migrations/20261018120000_identity_operator_invitations.sql";
|
|
29
|
+
readonly position: 67;
|
|
30
|
+
readonly sha256: "b73034908bd5e27819bcd421d17037a0f00a24aa3df1be1f8f9ca411bf984349";
|
|
31
|
+
readonly url: URL;
|
|
32
|
+
}, {
|
|
33
|
+
readonly id: "20261018180000_identity_operator_challenges";
|
|
34
|
+
readonly catalogPath: "db/platform/migrations/20261018180000_identity_operator_challenges.sql";
|
|
35
|
+
readonly position: 68;
|
|
36
|
+
readonly sha256: "191cf0c151a5882ad20d6043624da50afad799df739fff326d67560d3e00a031";
|
|
37
|
+
readonly url: URL;
|
|
38
|
+
}, {
|
|
39
|
+
readonly id: "20261018190000_identity_privacy_erasures";
|
|
40
|
+
readonly catalogPath: "db/platform/migrations/20261018190000_identity_privacy_erasures.sql";
|
|
41
|
+
readonly position: 69;
|
|
42
|
+
readonly sha256: "f39b691cb14c0e9ec1a7460d77dc46e16bca4d2448838e4882f78885a6d92351";
|
|
43
|
+
readonly url: URL;
|
|
44
|
+
}];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A projection of canonical migration units, never a second migration chain. */
|
|
2
|
+
export const IDENTITY_MIGRATIONS = [
|
|
3
|
+
{ id: "20260810180001_self_host_actor_auth", catalogPath: "db/platform/migrations/20260810180001_self_host_actor_auth.sql", position: 11, sha256: "84c80d328785151f1fdb5fc4b69220469ffb9c8579054c473ead910a273dfe7b", url: new URL("../../sql/20260810180001_self_host_actor_auth.sql", import.meta.url) },
|
|
4
|
+
{ id: "20260810204057_customer_identity_read", catalogPath: "db/platform/migrations/20260810204057_customer_identity_read.sql", position: 12, sha256: "1aa626c0187a4ed9d08f152540e0d17c68cd678d2caf3e896ac444b5a38aafe3", url: new URL("../../sql/20260810204057_customer_identity_read.sql", import.meta.url) },
|
|
5
|
+
{ id: "20260814090000_customer_selfservice_recovery", catalogPath: "db/platform/migrations/20260814090000_customer_selfservice_recovery.sql", position: 29, sha256: "ca7f58994533727eb58da148d549ff986fe8f55bb2ffc9eaf61e7d239675ba2e", url: new URL("../../sql/20260814090000_customer_selfservice_recovery.sql", import.meta.url) },
|
|
6
|
+
{ id: "20260901143000_admin_membership_authority_foundation", catalogPath: "db/platform/migrations/20260901143000_admin_membership_authority_foundation.sql", position: 60, sha256: "bb4703b669d17e5a0eb4d9a4e8889d12e5286d4b5a813226a77ef2b71df8281f", url: new URL("../../sql/20260901143000_admin_membership_authority_foundation.sql", import.meta.url) },
|
|
7
|
+
{ id: "20261018120000_identity_operator_invitations", catalogPath: "db/platform/migrations/20261018120000_identity_operator_invitations.sql", position: 67, sha256: "b73034908bd5e27819bcd421d17037a0f00a24aa3df1be1f8f9ca411bf984349", url: new URL("../../sql/20261018120000_identity_operator_invitations.sql", import.meta.url) },
|
|
8
|
+
{ id: "20261018180000_identity_operator_challenges", catalogPath: "db/platform/migrations/20261018180000_identity_operator_challenges.sql", position: 68, sha256: "191cf0c151a5882ad20d6043624da50afad799df739fff326d67560d3e00a031", url: new URL("../../sql/20261018180000_identity_operator_challenges.sql", import.meta.url) },
|
|
9
|
+
{ id: "20261018190000_identity_privacy_erasures", catalogPath: "db/platform/migrations/20261018190000_identity_privacy_erasures.sql", position: 69, sha256: "f39b691cb14c0e9ec1a7460d77dc46e16bca4d2448838e4882f78885a6d92351", url: new URL("../../sql/20261018190000_identity_privacy_erasures.sql", import.meta.url) },
|
|
10
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlup/platform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Runnable server substrate: Node HTTP runtime, BFF dispatch, scheduler, storage, data gateways and bundle composition; development preview.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"api:update": "npm run build && node --experimental-strip-types ./scripts/api-contract.ts --update"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@openlup/core": "0.
|
|
34
|
+
"@openlup/core": "0.17.0",
|
|
35
35
|
"pg": "^8.22.0",
|
|
36
36
|
"@aws-sdk/client-s3": "^3.1144.0",
|
|
37
37
|
"@types/pg": "^8.20.0"
|
|
@@ -95,6 +95,26 @@
|
|
|
95
95
|
"types": "./dist/composition/index.d.ts",
|
|
96
96
|
"import": "./dist/composition/index.js",
|
|
97
97
|
"default": "./dist/composition/index.js"
|
|
98
|
+
},
|
|
99
|
+
"./identity": {
|
|
100
|
+
"types": "./dist/identity/index.d.ts",
|
|
101
|
+
"import": "./dist/identity/index.js",
|
|
102
|
+
"default": "./dist/identity/index.js"
|
|
103
|
+
},
|
|
104
|
+
"./identity/contracts": {
|
|
105
|
+
"types": "./dist/identity/contracts/index.d.ts",
|
|
106
|
+
"import": "./dist/identity/contracts/index.js",
|
|
107
|
+
"default": "./dist/identity/contracts/index.js"
|
|
108
|
+
},
|
|
109
|
+
"./communications": {
|
|
110
|
+
"types": "./dist/communications/index.d.ts",
|
|
111
|
+
"import": "./dist/communications/index.js",
|
|
112
|
+
"default": "./dist/communications/index.js"
|
|
113
|
+
},
|
|
114
|
+
"./communications/contracts": {
|
|
115
|
+
"types": "./dist/communications/contracts/index.d.ts",
|
|
116
|
+
"import": "./dist/communications/contracts/index.js",
|
|
117
|
+
"default": "./dist/communications/contracts/index.js"
|
|
98
118
|
}
|
|
99
119
|
},
|
|
100
120
|
"repository": {
|
package/release-gates.json
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"compatibilityPolicy": "internal-candidate",
|
|
12
12
|
"packageSmokeEvidence": [
|
|
13
13
|
"test/packageBoundary.test.ts",
|
|
14
|
-
"test/http/runtime.test.ts"
|
|
14
|
+
"test/http/runtime.test.ts",
|
|
15
|
+
"test/http/webhookSignature.test.ts"
|
|
15
16
|
],
|
|
16
17
|
"entrypoint": "dist/http/index.d.ts",
|
|
17
18
|
"snapshot": "api/http.api.md"
|
|
@@ -103,19 +104,73 @@
|
|
|
103
104
|
],
|
|
104
105
|
"entrypoint": "dist/composition/index.d.ts",
|
|
105
106
|
"snapshot": "api/composition.api.md"
|
|
107
|
+
},
|
|
108
|
+
"./identity": {
|
|
109
|
+
"role": "capability",
|
|
110
|
+
"maturity": "experimental",
|
|
111
|
+
"compatibilityPolicy": "internal-candidate",
|
|
112
|
+
"packageSmokeEvidence": [
|
|
113
|
+
"test/packageBoundary.test.ts",
|
|
114
|
+
"test/identity/adminConformance.test.ts"
|
|
115
|
+
],
|
|
116
|
+
"entrypoint": "dist/identity/index.d.ts",
|
|
117
|
+
"snapshot": "api/identity.api.md"
|
|
118
|
+
},
|
|
119
|
+
"./identity/contracts": {
|
|
120
|
+
"role": "capability",
|
|
121
|
+
"maturity": "experimental",
|
|
122
|
+
"compatibilityPolicy": "internal-candidate",
|
|
123
|
+
"packageSmokeEvidence": [
|
|
124
|
+
"test/packageBoundary.test.ts",
|
|
125
|
+
"test/identity/contracts.test.ts"
|
|
126
|
+
],
|
|
127
|
+
"entrypoint": "dist/identity/contracts/index.d.ts",
|
|
128
|
+
"snapshot": "api/identity-contracts.api.md"
|
|
129
|
+
},
|
|
130
|
+
"./communications": {
|
|
131
|
+
"role": "capability",
|
|
132
|
+
"maturity": "experimental",
|
|
133
|
+
"compatibilityPolicy": "internal-candidate",
|
|
134
|
+
"packageSmokeEvidence": [
|
|
135
|
+
"test/packageBoundary.test.ts",
|
|
136
|
+
"test/communications/sql.test.ts",
|
|
137
|
+
"test/communications/contribution.test.ts",
|
|
138
|
+
"test/communications/transportConformance.test.ts"
|
|
139
|
+
],
|
|
140
|
+
"entrypoint": "dist/communications/index.d.ts",
|
|
141
|
+
"snapshot": "api/communications.api.md"
|
|
142
|
+
},
|
|
143
|
+
"./communications/contracts": {
|
|
144
|
+
"role": "capability",
|
|
145
|
+
"maturity": "experimental",
|
|
146
|
+
"compatibilityPolicy": "internal-candidate",
|
|
147
|
+
"packageSmokeEvidence": [
|
|
148
|
+
"test/packageBoundary.test.ts",
|
|
149
|
+
"test/communications/contracts.test.ts"
|
|
150
|
+
],
|
|
151
|
+
"entrypoint": "dist/communications/contracts/index.d.ts",
|
|
152
|
+
"snapshot": "api/communications-contracts.api.md"
|
|
106
153
|
}
|
|
107
154
|
},
|
|
108
155
|
"pack": {
|
|
109
156
|
"code": {
|
|
110
|
-
"maxPackedBytes":
|
|
111
|
-
"maxFiles":
|
|
157
|
+
"maxPackedBytes": 440320,
|
|
158
|
+
"maxFiles": 800
|
|
112
159
|
},
|
|
113
160
|
"docs": {
|
|
114
|
-
"maxPackedBytes":
|
|
115
|
-
"maxFiles":
|
|
161
|
+
"maxPackedBytes": 40960,
|
|
162
|
+
"maxFiles": 10
|
|
163
|
+
},
|
|
164
|
+
"maxPackedBytes": 522240,
|
|
165
|
+
"maxUnpackedBytes": 2088960,
|
|
166
|
+
"maxFiles": 800,
|
|
167
|
+
"baseline": {
|
|
168
|
+
"version": "0.16.0",
|
|
169
|
+
"packedBytes": 256973
|
|
116
170
|
},
|
|
117
|
-
"
|
|
118
|
-
|
|
119
|
-
|
|
171
|
+
"browserEntries": {
|
|
172
|
+
"./communications/contracts": 11776,
|
|
173
|
+
"./identity/contracts": 4800
|
|
174
|
+
}
|
|
120
175
|
}
|
|
121
176
|
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
-- Public platform communications outbox rail: the queue table, the dormant-event-type
|
|
2
|
+
-- allowlist, and the claim/ack protocol that drains them.
|
|
3
|
+
--
|
|
4
|
+
-- WHAT THIS FORWARD SHIPS, AND WHY IT IS THE FIRST ONE CARRYING FUNCTIONS.
|
|
5
|
+
-- The baseline and the read-parity forward both hold `grep -c 'CREATE FUNCTION'` = 0 on
|
|
6
|
+
-- purpose. This migration breaks that property deliberately, because the dispatch rail
|
|
7
|
+
-- has no non-RPC surface: claim is an atomic `UPDATE ... FOR UPDATE SKIP LOCKED` that
|
|
8
|
+
-- hands back a claim token and evaluates a per-aggregate ordering barrier inside the same
|
|
9
|
+
-- statement. Expressing it through the gateway's query builder would mean reimplementing
|
|
10
|
+
-- pessimistic locking in the application, i.e. a second and divergent rail. Four functions
|
|
11
|
+
-- is the whole crossing: no privilege model, no `private` schema, no queue statistics, no
|
|
12
|
+
-- pruning, no preview-matrix claim scope, and above all no enqueue -- rows are written by
|
|
13
|
+
-- capabilities that own their own business logic, and none of them is authored here.
|
|
14
|
+
--
|
|
15
|
+
-- AUTHORED, NOT COPIED. The protocol below was written for this migration against the
|
|
16
|
+
-- observable contract the platform outbox store port issues (five named RPC arguments sets,
|
|
17
|
+
-- a boolean/text/integer/SETOF return shape). It is not a cut of any historical migration:
|
|
18
|
+
-- the provider-specific idempotency window and the hardcoded product event-type vocabulary
|
|
19
|
+
-- that the managed implementation calls into are absent, the preview-matrix claim scope is
|
|
20
|
+
-- absent, row-level security and role grants are absent because this kernel creates no
|
|
21
|
+
-- roles to grant to, `SECURITY DEFINER` is absent for the same reason, every constraint is
|
|
22
|
+
-- named rather than left to a generated identifier, and `CREATE` is unconditional because a
|
|
23
|
+
-- manifest-ordered forward runs exactly once against a known prefix -- `IF NOT EXISTS` there
|
|
24
|
+
-- would hide the drift the migration ledger exists to catch. `SET search_path` is kept: it
|
|
25
|
+
-- is a real injection-hardening property that does not depend on a role model.
|
|
26
|
+
|
|
27
|
+
CREATE TABLE public.outbox_events (
|
|
28
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
29
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
30
|
+
available_at timestamptz NOT NULL DEFAULT now(),
|
|
31
|
+
processed_at timestamptz,
|
|
32
|
+
aggregate_type text NOT NULL,
|
|
33
|
+
aggregate_id uuid NOT NULL,
|
|
34
|
+
event_type text NOT NULL,
|
|
35
|
+
idempotency_key text NOT NULL,
|
|
36
|
+
status text NOT NULL DEFAULT 'pending',
|
|
37
|
+
attempts integer NOT NULL DEFAULT 0,
|
|
38
|
+
payload jsonb NOT NULL,
|
|
39
|
+
error text,
|
|
40
|
+
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
41
|
+
CONSTRAINT outbox_events_aggregate_type_nonempty_check CHECK (btrim(aggregate_type) <> ''),
|
|
42
|
+
CONSTRAINT outbox_events_event_type_nonempty_check CHECK (btrim(event_type) <> ''),
|
|
43
|
+
CONSTRAINT outbox_events_idempotency_key_nonempty_check CHECK (btrim(idempotency_key) <> ''),
|
|
44
|
+
CONSTRAINT outbox_events_attempts_check CHECK (attempts >= 0),
|
|
45
|
+
CONSTRAINT outbox_events_status_check
|
|
46
|
+
CHECK (status IN ('pending', 'processing', 'processed', 'failed', 'discarded')),
|
|
47
|
+
CONSTRAINT outbox_events_event_type_idempotency_key_key UNIQUE (event_type, idempotency_key)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE INDEX idx_outbox_events_status_available
|
|
51
|
+
ON public.outbox_events (status, available_at);
|
|
52
|
+
|
|
53
|
+
CREATE INDEX idx_outbox_events_aggregate
|
|
54
|
+
ON public.outbox_events (aggregate_type, aggregate_id);
|
|
55
|
+
|
|
56
|
+
-- The claim barrier below refuses to skip an older unprocessed row for the same aggregate,
|
|
57
|
+
-- INCLUDING one whose event type the caller does not know about. Without a way to declare a
|
|
58
|
+
-- type intentionally unconsumed, a single retired producer would stall its aggregate
|
|
59
|
+
-- forever. This table is that declaration, and it ships empty: which types are dormant is
|
|
60
|
+
-- operator data, not platform content.
|
|
61
|
+
CREATE TABLE public.outbox_dormant_event_types (
|
|
62
|
+
event_type text PRIMARY KEY,
|
|
63
|
+
owner text NOT NULL,
|
|
64
|
+
reason text NOT NULL,
|
|
65
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
66
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
67
|
+
CONSTRAINT outbox_dormant_event_types_event_type_nonempty_check CHECK (btrim(event_type) <> ''),
|
|
68
|
+
CONSTRAINT outbox_dormant_event_types_owner_nonempty_check CHECK (btrim(owner) <> ''),
|
|
69
|
+
CONSTRAINT outbox_dormant_event_types_reason_nonempty_check CHECK (btrim(reason) <> '')
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
-- Claim a batch for one allowlist of event types.
|
|
73
|
+
--
|
|
74
|
+
-- Three properties make this more than a SELECT, and each is load-bearing:
|
|
75
|
+
-- 1. an empty allowlist is refused, never widened -- a caller that forgot its filter must
|
|
76
|
+
-- not drain every event type on the instance;
|
|
77
|
+
-- 2. rows whose attempts already reached the ceiling are discarded before the scan, so an
|
|
78
|
+
-- exhausted row cannot be re-selected on every tick;
|
|
79
|
+
-- 3. per aggregate, an older unprocessed row blocks the newer one. A prior of an event
|
|
80
|
+
-- type the caller neither claims nor knows also blocks, unless it has been declared
|
|
81
|
+
-- dormant -- ordering within an aggregate is the guarantee producers rely on.
|
|
82
|
+
-- The claim token written into metadata is the authorization for every later acknowledgement:
|
|
83
|
+
-- knowing the row id is not enough, which is what makes a stale ack detectable rather than
|
|
84
|
+
-- destructive.
|
|
85
|
+
CREATE FUNCTION public.outbox_claim_batch(
|
|
86
|
+
p_event_types text[],
|
|
87
|
+
p_known_event_types text[] DEFAULT ARRAY[]::text[],
|
|
88
|
+
p_batch_size integer DEFAULT 25,
|
|
89
|
+
p_visibility_seconds integer DEFAULT 300,
|
|
90
|
+
p_max_attempts integer DEFAULT 8
|
|
91
|
+
)
|
|
92
|
+
RETURNS SETOF public.outbox_events
|
|
93
|
+
LANGUAGE plpgsql
|
|
94
|
+
SET search_path = public, pg_catalog
|
|
95
|
+
AS $$
|
|
96
|
+
DECLARE
|
|
97
|
+
v_batch integer := LEAST(GREATEST(COALESCE(p_batch_size, 25), 1), 100);
|
|
98
|
+
v_visibility integer := LEAST(GREATEST(COALESCE(p_visibility_seconds, 300), 300), 3600);
|
|
99
|
+
v_max integer := LEAST(GREATEST(COALESCE(p_max_attempts, 8), 1), 20);
|
|
100
|
+
v_known text[];
|
|
101
|
+
BEGIN
|
|
102
|
+
IF p_event_types IS NULL OR cardinality(p_event_types) = 0 THEN
|
|
103
|
+
RAISE EXCEPTION 'outbox_claim_allowlist_required' USING ERRCODE = '22023';
|
|
104
|
+
END IF;
|
|
105
|
+
|
|
106
|
+
-- Everything the caller can recognise: what it claims now, plus what it declares it knows
|
|
107
|
+
-- about. A prior outside this set is treated as foreign, and only the dormant table can
|
|
108
|
+
-- release it.
|
|
109
|
+
SELECT array_agg(DISTINCT event_type)
|
|
110
|
+
INTO v_known
|
|
111
|
+
FROM unnest(COALESCE(p_known_event_types, ARRAY[]::text[]) || p_event_types) AS known(event_type)
|
|
112
|
+
WHERE event_type IS NOT NULL AND btrim(event_type) <> '';
|
|
113
|
+
|
|
114
|
+
WITH exhausted AS (
|
|
115
|
+
SELECT event.id
|
|
116
|
+
FROM public.outbox_events event
|
|
117
|
+
WHERE event.event_type = ANY (p_event_types)
|
|
118
|
+
AND event.status IN ('pending', 'failed', 'processing')
|
|
119
|
+
AND event.available_at <= now()
|
|
120
|
+
AND event.attempts >= v_max
|
|
121
|
+
ORDER BY event.created_at, event.id
|
|
122
|
+
LIMIT 100
|
|
123
|
+
FOR UPDATE SKIP LOCKED
|
|
124
|
+
)
|
|
125
|
+
UPDATE public.outbox_events event
|
|
126
|
+
SET status = 'discarded',
|
|
127
|
+
error = left(COALESCE(event.error, '') || ' | max_attempts_exhausted_at_claim', 2000),
|
|
128
|
+
metadata = event.metadata || jsonb_build_object(
|
|
129
|
+
'discardReason', 'max_attempts',
|
|
130
|
+
'discardedAt', now(),
|
|
131
|
+
'finalAttempts', event.attempts)
|
|
132
|
+
FROM exhausted
|
|
133
|
+
WHERE event.id = exhausted.id;
|
|
134
|
+
|
|
135
|
+
RETURN QUERY
|
|
136
|
+
WITH candidates AS (
|
|
137
|
+
SELECT event.id
|
|
138
|
+
FROM public.outbox_events event
|
|
139
|
+
WHERE event.event_type = ANY (p_event_types)
|
|
140
|
+
AND event.available_at <= now()
|
|
141
|
+
AND event.status IN ('pending', 'failed', 'processing')
|
|
142
|
+
AND event.attempts < v_max
|
|
143
|
+
AND NOT EXISTS (
|
|
144
|
+
SELECT 1
|
|
145
|
+
FROM public.outbox_events prior
|
|
146
|
+
WHERE prior.aggregate_type = event.aggregate_type
|
|
147
|
+
AND prior.aggregate_id = event.aggregate_id
|
|
148
|
+
AND prior.status IN ('pending', 'failed', 'processing')
|
|
149
|
+
AND (prior.created_at, prior.id) < (event.created_at, event.id)
|
|
150
|
+
AND (
|
|
151
|
+
prior.event_type = ANY (p_event_types)
|
|
152
|
+
OR (
|
|
153
|
+
prior.event_type <> ALL (COALESCE(v_known, ARRAY[]::text[]))
|
|
154
|
+
AND NOT EXISTS (
|
|
155
|
+
SELECT 1
|
|
156
|
+
FROM public.outbox_dormant_event_types dormant
|
|
157
|
+
WHERE dormant.event_type = prior.event_type
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
))
|
|
161
|
+
ORDER BY event.created_at, event.id
|
|
162
|
+
LIMIT v_batch
|
|
163
|
+
FOR UPDATE SKIP LOCKED
|
|
164
|
+
)
|
|
165
|
+
UPDATE public.outbox_events event
|
|
166
|
+
SET status = 'processing',
|
|
167
|
+
attempts = event.attempts + 1,
|
|
168
|
+
available_at = now() + make_interval(secs => v_visibility),
|
|
169
|
+
metadata = event.metadata || jsonb_build_object(
|
|
170
|
+
'lastClaimedAt', now(),
|
|
171
|
+
'claimToken', gen_random_uuid()::text)
|
|
172
|
+
FROM candidates
|
|
173
|
+
WHERE event.id = candidates.id
|
|
174
|
+
RETURNING event.*;
|
|
175
|
+
END;
|
|
176
|
+
$$;
|
|
177
|
+
|
|
178
|
+
-- Acknowledge success. Returns false rather than raising when the row is no longer the
|
|
179
|
+
-- caller's: a lease that expired and was re-claimed elsewhere is an ordinary race, and the
|
|
180
|
+
-- caller logs it instead of aborting a batch.
|
|
181
|
+
CREATE FUNCTION public.outbox_mark_processed(
|
|
182
|
+
p_event_id uuid,
|
|
183
|
+
p_claim_token text,
|
|
184
|
+
p_metadata jsonb DEFAULT '{}'::jsonb
|
|
185
|
+
)
|
|
186
|
+
RETURNS boolean
|
|
187
|
+
LANGUAGE sql
|
|
188
|
+
SET search_path = public, pg_catalog
|
|
189
|
+
AS $$
|
|
190
|
+
WITH updated AS (
|
|
191
|
+
UPDATE public.outbox_events
|
|
192
|
+
SET status = 'processed',
|
|
193
|
+
processed_at = now(),
|
|
194
|
+
error = NULL,
|
|
195
|
+
metadata = metadata || COALESCE(p_metadata, '{}'::jsonb)
|
|
196
|
+
WHERE id = p_event_id
|
|
197
|
+
AND status = 'processing'
|
|
198
|
+
AND metadata->>'claimToken' = p_claim_token
|
|
199
|
+
RETURNING id
|
|
200
|
+
)
|
|
201
|
+
SELECT EXISTS (SELECT 1 FROM updated);
|
|
202
|
+
$$;
|
|
203
|
+
|
|
204
|
+
-- Acknowledge failure. The outcome the handler asks for is a request, not a verdict: a
|
|
205
|
+
-- 'retry' on a row that has already spent its attempts becomes a discard, so the ceiling is
|
|
206
|
+
-- enforced in one place instead of in every caller.
|
|
207
|
+
--
|
|
208
|
+
-- 'snooze' means the downstream is unavailable rather than the row being bad, so the attempt
|
|
209
|
+
-- taken at claim is refunded -- an outage must not consume the DLQ budget of the events it
|
|
210
|
+
-- happened to touch. Retry delay is exponential with equal jitter in [d/2, d]: without the
|
|
211
|
+
-- jitter every row that failed in the same tick returns in the same later tick, and the
|
|
212
|
+
-- convoy reforms on each retry instead of dispersing.
|
|
213
|
+
CREATE FUNCTION public.outbox_mark_failed(
|
|
214
|
+
p_event_id uuid,
|
|
215
|
+
p_claim_token text,
|
|
216
|
+
p_error text,
|
|
217
|
+
p_outcome text DEFAULT 'retry',
|
|
218
|
+
p_base_delay_seconds integer DEFAULT 60,
|
|
219
|
+
p_max_delay_seconds integer DEFAULT 3600,
|
|
220
|
+
p_max_attempts integer DEFAULT 8,
|
|
221
|
+
p_snooze_seconds integer DEFAULT 300
|
|
222
|
+
)
|
|
223
|
+
RETURNS text
|
|
224
|
+
LANGUAGE plpgsql
|
|
225
|
+
SET search_path = public, pg_catalog
|
|
226
|
+
AS $$
|
|
227
|
+
DECLARE
|
|
228
|
+
v_row public.outbox_events%ROWTYPE;
|
|
229
|
+
v_base integer := LEAST(GREATEST(COALESCE(p_base_delay_seconds, 60), 5), 3600);
|
|
230
|
+
v_cap integer;
|
|
231
|
+
v_max integer := LEAST(GREATEST(COALESCE(p_max_attempts, 8), 1), 20);
|
|
232
|
+
v_snooze integer := LEAST(GREATEST(COALESCE(p_snooze_seconds, 300), 60), 3600);
|
|
233
|
+
v_delay double precision;
|
|
234
|
+
BEGIN
|
|
235
|
+
IF p_outcome IS NULL OR p_outcome NOT IN ('retry', 'discard', 'snooze') THEN
|
|
236
|
+
RAISE EXCEPTION 'outbox_mark_failed_invalid_outcome' USING ERRCODE = '22023';
|
|
237
|
+
END IF;
|
|
238
|
+
|
|
239
|
+
v_cap := LEAST(GREATEST(v_base, COALESCE(p_max_delay_seconds, 3600)), 86400);
|
|
240
|
+
|
|
241
|
+
SELECT *
|
|
242
|
+
INTO v_row
|
|
243
|
+
FROM public.outbox_events
|
|
244
|
+
WHERE id = p_event_id
|
|
245
|
+
AND status = 'processing'
|
|
246
|
+
AND metadata->>'claimToken' = p_claim_token
|
|
247
|
+
FOR UPDATE;
|
|
248
|
+
|
|
249
|
+
IF NOT FOUND THEN
|
|
250
|
+
RETURN 'missed';
|
|
251
|
+
END IF;
|
|
252
|
+
|
|
253
|
+
IF p_outcome = 'discard' OR (p_outcome = 'retry' AND v_row.attempts >= v_max) THEN
|
|
254
|
+
UPDATE public.outbox_events
|
|
255
|
+
SET status = 'discarded',
|
|
256
|
+
error = left(p_error, 2000),
|
|
257
|
+
metadata = metadata || jsonb_build_object(
|
|
258
|
+
'discardReason',
|
|
259
|
+
CASE WHEN p_outcome = 'discard' THEN 'permanent_error' ELSE 'max_attempts' END,
|
|
260
|
+
'discardedAt', now(),
|
|
261
|
+
'finalAttempts', v_row.attempts)
|
|
262
|
+
WHERE id = v_row.id;
|
|
263
|
+
RETURN 'discarded';
|
|
264
|
+
END IF;
|
|
265
|
+
|
|
266
|
+
IF p_outcome = 'snooze' THEN
|
|
267
|
+
UPDATE public.outbox_events
|
|
268
|
+
SET status = 'failed',
|
|
269
|
+
attempts = GREATEST(v_row.attempts - 1, 0),
|
|
270
|
+
available_at = now() + make_interval(secs => v_snooze),
|
|
271
|
+
error = left(p_error, 2000),
|
|
272
|
+
metadata = metadata || jsonb_build_object(
|
|
273
|
+
'snoozeCount', COALESCE((metadata->>'snoozeCount')::integer, 0) + 1,
|
|
274
|
+
'lastSnoozedAt', now())
|
|
275
|
+
WHERE id = v_row.id;
|
|
276
|
+
RETURN 'snoozed';
|
|
277
|
+
END IF;
|
|
278
|
+
|
|
279
|
+
v_delay := LEAST(
|
|
280
|
+
v_cap::double precision,
|
|
281
|
+
v_base::double precision * power(2, LEAST(GREATEST(v_row.attempts - 1, 0), 16))
|
|
282
|
+
) * (0.5 + random() * 0.5);
|
|
283
|
+
|
|
284
|
+
UPDATE public.outbox_events
|
|
285
|
+
SET status = 'failed',
|
|
286
|
+
available_at = now() + make_interval(secs => v_delay),
|
|
287
|
+
error = left(p_error, 2000)
|
|
288
|
+
WHERE id = v_row.id;
|
|
289
|
+
RETURN 'failed';
|
|
290
|
+
END;
|
|
291
|
+
$$;
|
|
292
|
+
|
|
293
|
+
-- Hand back rows the caller claimed but never ran -- a drain loop that aborts mid-batch, or
|
|
294
|
+
-- one handler reporting the downstream is out. The attempt taken at claim is refunded for
|
|
295
|
+
-- exactly the same reason as in 'snooze': nothing was tried, so nothing was spent. Ids and
|
|
296
|
+
-- tokens are supplied as parallel arrays and must agree in length, because a mismatch means
|
|
297
|
+
-- the caller lost track of which token belongs to which row and releasing the wrong pairing
|
|
298
|
+
-- would silently release nothing.
|
|
299
|
+
CREATE FUNCTION public.outbox_release_unprocessed(
|
|
300
|
+
p_event_ids uuid[],
|
|
301
|
+
p_claim_tokens text[],
|
|
302
|
+
p_delay_seconds integer DEFAULT 0
|
|
303
|
+
)
|
|
304
|
+
RETURNS integer
|
|
305
|
+
LANGUAGE plpgsql
|
|
306
|
+
SET search_path = public, pg_catalog
|
|
307
|
+
AS $$
|
|
308
|
+
DECLARE
|
|
309
|
+
v_delay integer := LEAST(GREATEST(COALESCE(p_delay_seconds, 0), 0), 3600);
|
|
310
|
+
v_count integer;
|
|
311
|
+
BEGIN
|
|
312
|
+
IF p_event_ids IS NULL OR p_claim_tokens IS NULL
|
|
313
|
+
OR cardinality(p_event_ids) <> cardinality(p_claim_tokens) THEN
|
|
314
|
+
RAISE EXCEPTION 'outbox_release_invalid_input' USING ERRCODE = '22023';
|
|
315
|
+
END IF;
|
|
316
|
+
|
|
317
|
+
UPDATE public.outbox_events event
|
|
318
|
+
SET status = 'pending',
|
|
319
|
+
available_at = now() + make_interval(secs => v_delay),
|
|
320
|
+
attempts = GREATEST(event.attempts - 1, 0)
|
|
321
|
+
FROM unnest(p_event_ids, p_claim_tokens) AS released(id, token)
|
|
322
|
+
WHERE event.id = released.id
|
|
323
|
+
AND event.status = 'processing'
|
|
324
|
+
AND event.metadata->>'claimToken' = released.token;
|
|
325
|
+
|
|
326
|
+
GET DIAGNOSTICS v_count = ROW_COUNT;
|
|
327
|
+
RETURN v_count;
|
|
328
|
+
END;
|
|
329
|
+
$$;
|