@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,99 @@
|
|
|
1
|
+
function invalid() { throw new Error("privacy_contract_invalid"); }
|
|
2
|
+
function schema(parse) {
|
|
3
|
+
return { parse, safeParse(value) { try {
|
|
4
|
+
return { success: true, data: parse(value) };
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return { success: false, error: new Error("privacy_contract_invalid") };
|
|
8
|
+
} } };
|
|
9
|
+
}
|
|
10
|
+
function fields(value, keys) {
|
|
11
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || Object.getPrototypeOf(value) !== Object.prototype
|
|
12
|
+
|| Object.keys(value).length !== keys.length || !keys.every(key => Object.hasOwn(value, key)))
|
|
13
|
+
invalid();
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function text(value, max = 200) {
|
|
17
|
+
if (typeof value !== "string" || !value.length || value.length > max)
|
|
18
|
+
invalid();
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function uuid(value) {
|
|
22
|
+
const result = text(value, 36);
|
|
23
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(result))
|
|
24
|
+
invalid();
|
|
25
|
+
return result.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
function timestamp(value) {
|
|
28
|
+
const result = text(value, 30);
|
|
29
|
+
if (!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d{3})?Z$/.test(result) || !Number.isFinite(Date.parse(result))
|
|
30
|
+
|| new Date(result).toISOString() !== result.replace(/Z$/, result.length === 20 ? ".000Z" : "Z"))
|
|
31
|
+
invalid();
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
function list(value, parse) {
|
|
35
|
+
if (!Array.isArray(value) || value.length > 10000)
|
|
36
|
+
invalid();
|
|
37
|
+
return value.map(element => parse(element));
|
|
38
|
+
}
|
|
39
|
+
function boolean(value) { if (typeof value !== "boolean")
|
|
40
|
+
invalid(); return value; }
|
|
41
|
+
function choice(value, allowed) { if (!allowed.includes(value))
|
|
42
|
+
invalid(); return value; }
|
|
43
|
+
function json(value, depth = 0) {
|
|
44
|
+
if (depth > 32)
|
|
45
|
+
invalid();
|
|
46
|
+
if (value === null || typeof value === "boolean" || typeof value === "string") {
|
|
47
|
+
if (typeof value === "string" && value.length > 1000000)
|
|
48
|
+
invalid();
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
52
|
+
return value;
|
|
53
|
+
if (Array.isArray(value))
|
|
54
|
+
return list(value, element => json(element, depth + 1));
|
|
55
|
+
if (!value || typeof value !== "object" || Object.getPrototypeOf(value) !== Object.prototype)
|
|
56
|
+
invalid();
|
|
57
|
+
const forbidden = new Set(["__proto__", "constructor", "prototype", "password", "password_hash", "token_hash", "access_token", "refresh_token", "accessToken", "refreshToken", "secret", "credentials"]);
|
|
58
|
+
const entries = Object.entries(value);
|
|
59
|
+
if (entries.length > 10000 || entries.some(([key]) => forbidden.has(key)))
|
|
60
|
+
invalid();
|
|
61
|
+
return Object.fromEntries(entries.map(([key, child]) => [key, json(child, depth + 1)]));
|
|
62
|
+
}
|
|
63
|
+
export const privacySubjectSchema = schema(value => {
|
|
64
|
+
if (!value || typeof value !== "object" || !("kind" in value))
|
|
65
|
+
invalid();
|
|
66
|
+
if (value.kind === "contact") {
|
|
67
|
+
const row = fields(value, ["kind", "contactId"]);
|
|
68
|
+
return { kind: "contact", contactId: uuid(row.contactId) };
|
|
69
|
+
}
|
|
70
|
+
const row = fields(value, ["kind", "principalId"]);
|
|
71
|
+
return { kind: choice(row.kind, ["principal"]), principalId: uuid(row.principalId) };
|
|
72
|
+
});
|
|
73
|
+
export const personalDataObligationSchema = schema(value => {
|
|
74
|
+
const row = fields(value, ["owner", "resource", "disposition", "reasonCode", "remote"]);
|
|
75
|
+
return { owner: text(row.owner, 100), resource: text(row.resource), disposition: choice(row.disposition, ["erase", "retain", "unresolved"]), reasonCode: text(row.reasonCode, 100), remote: boolean(row.remote) };
|
|
76
|
+
});
|
|
77
|
+
export const personalDataDocumentSchema = schema(value => {
|
|
78
|
+
const row = fields(value, ["contributorId", "version", "data", "coverage", "obligations"]), coverage = fields(row.coverage, ["complete", "included", "unavailable"]);
|
|
79
|
+
const contributorId = text(row.contributorId, 100), version = text(row.version);
|
|
80
|
+
if (!/^[a-z][a-z0-9.-]{0,99}$/.test(contributorId) || !/^[a-z][a-z0-9.-]*\.v[1-9][0-9]*$/.test(version))
|
|
81
|
+
invalid();
|
|
82
|
+
return { contributorId, version, data: json(row.data), coverage: { complete: boolean(coverage.complete), included: list(coverage.included, text), unavailable: list(coverage.unavailable, text) }, obligations: list(row.obligations, personalDataObligationSchema.parse) };
|
|
83
|
+
});
|
|
84
|
+
export const erasureReceiptSchema = schema(value => {
|
|
85
|
+
const row = fields(value, ["version", "erasureId", "completedAt", "outcome", "obligations"]);
|
|
86
|
+
return { version: choice(row.version, ["identity.erasure.v1"]), erasureId: uuid(row.erasureId), completedAt: timestamp(row.completedAt), outcome: choice(row.outcome, ["ERASED", "ALREADY_ERASED"]), obligations: list(row.obligations, personalDataObligationSchema.parse) };
|
|
87
|
+
});
|
|
88
|
+
export const privacyExportRequestSchema = schema(value => ({ subject: privacySubjectSchema.parse(fields(value, ["subject"]).subject) }));
|
|
89
|
+
export const privacyEraseRequestSchema = schema(value => {
|
|
90
|
+
const row = fields(value, ["subject", "idempotencyKey"]);
|
|
91
|
+
return { subject: privacySubjectSchema.parse(row.subject), idempotencyKey: uuid(row.idempotencyKey) };
|
|
92
|
+
});
|
|
93
|
+
export const privacyExportResponseSchema = schema(value => {
|
|
94
|
+
const row = fields(value, ["format", "generatedAt", "subject", "documents", "missingContributors", "erasure"]);
|
|
95
|
+
return { format: choice(row.format, ["personal-data.v1"]), generatedAt: timestamp(row.generatedAt), subject: privacySubjectSchema.parse(row.subject), documents: list(row.documents, personalDataDocumentSchema.parse), missingContributors: list(row.missingContributors, text), erasure: row.erasure === null ? null : erasureReceiptSchema.parse(row.erasure) };
|
|
96
|
+
});
|
|
97
|
+
export const privacyEraseResponseSchema = erasureReceiptSchema;
|
|
98
|
+
const refusalCodes = ["PRIVACY_SUBJECT_NOT_FOUND", "PRIVACY_CONTRIBUTOR_DUPLICATE", "PRIVACY_CONTRIBUTOR_MISSING", "PRIVACY_ASSESSMENT_UNAVAILABLE", "PRIVACY_OWNERSHIP_UNDECLARED", "PRIVACY_ACTIVE_SUBSCRIPTION", "PRIVACY_RESUMABLE_SUBSCRIPTION", "PRIVACY_PROTECTED_OPERATOR", "PRIVACY_IDEMPOTENCY_CONFLICT", "PRIVACY_SUBJECT_ERASED", "PRIVACY_STORE_PRIVILEGES_UNSAFE", "MANAGED_PRIVACY_ERASURE_UNAVAILABLE"];
|
|
99
|
+
export const privacyRefusalCodeSchema = schema(value => choice(value, refusalCodes));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { isOAuthProviderKind } from "./types.js";
|
|
2
|
+
export const DEFAULT_SOCIAL_PROVIDERS = ["google"];
|
|
3
|
+
export function parseSocialProviders(raw) {
|
|
4
|
+
if (raw === undefined)
|
|
5
|
+
return [...DEFAULT_SOCIAL_PROVIDERS];
|
|
6
|
+
const kinds = raw
|
|
7
|
+
.split(",")
|
|
8
|
+
.map((token) => token.trim().toLowerCase())
|
|
9
|
+
.filter((token) => isOAuthProviderKind(token));
|
|
10
|
+
return [...new Set(kinds)];
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const OAUTH_PROVIDER_KINDS: readonly ["google", "apple", "facebook"];
|
|
2
|
+
export type OAuthProviderKind = (typeof OAUTH_PROVIDER_KINDS)[number];
|
|
3
|
+
export declare function isOAuthProviderKind(value: string): value is OAuthProviderKind;
|
|
4
|
+
export interface AuthUser {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface AuthSession {
|
|
9
|
+
accessToken: string;
|
|
10
|
+
user: AuthUser;
|
|
11
|
+
}
|
|
12
|
+
export type AuthStateListener = (session: AuthSession | null) => void;
|
|
13
|
+
export type Unsubscribe = () => void;
|
|
14
|
+
export interface AuthActionResult {
|
|
15
|
+
error: string | null;
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Contribution, RequiredSchema } from "@openlup/core/readiness";
|
|
2
|
+
/** Host-selected schema inventory: managed and direct installations have different objects. */
|
|
3
|
+
export declare function createIdentityContribution(options: {
|
|
4
|
+
version: string;
|
|
5
|
+
requiredSchema: RequiredSchema;
|
|
6
|
+
routes?: Contribution["routes"];
|
|
7
|
+
requiredPorts?: readonly string[];
|
|
8
|
+
}): Contribution;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Host-selected schema inventory: managed and direct installations have different objects. */
|
|
2
|
+
export function createIdentityContribution(options) {
|
|
3
|
+
const routes = options.routes ?? [];
|
|
4
|
+
return {
|
|
5
|
+
manifest: {
|
|
6
|
+
name: "@openlup/platform", version: options.version, kind: "rail",
|
|
7
|
+
module: {
|
|
8
|
+
id: "identity", kind: "capability", provides: ["./identity", "./identity/contracts"],
|
|
9
|
+
dependsOn: [
|
|
10
|
+
{ module: "bff", entries: ["./bff"] },
|
|
11
|
+
{ module: "data", entries: ["./data"] },
|
|
12
|
+
{ module: "kernel", entries: ["./kernel"] },
|
|
13
|
+
{ module: "http", entries: ["./http"] },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
requiredSchema: options.requiredSchema,
|
|
17
|
+
emits: [], handles: [], schedules: [], routes: routes.map((route) => route.id),
|
|
18
|
+
requiredPorts: [...new Set(["emailTrustPolicy", ...(options.requiredPorts ?? [])])], env: [],
|
|
19
|
+
},
|
|
20
|
+
handlers: [], schedules: [], routes,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CustomerUserAuthenticationResult } from "./customerAuth.js";
|
|
2
|
+
import type { IdentityVerifierPort } from "./ports.js";
|
|
3
|
+
export declare function authenticateCustomerUserWith(verifier: IdentityVerifierPort, accessToken: string | null): Promise<CustomerUserAuthenticationResult>;
|
|
4
|
+
export declare function optionalCustomerSubject(rawClient: unknown, accessToken: string | null): Promise<string | null>;
|
|
5
|
+
export declare function authenticateCustomerUser(rawClient: unknown, accessToken: string | null): Promise<CustomerUserAuthenticationResult>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createSupabaseIdentityVerifier } from "./managedIdentityVerifier.js";
|
|
2
|
+
export async function authenticateCustomerUserWith(verifier, accessToken) {
|
|
3
|
+
if (!accessToken) {
|
|
4
|
+
return { ok: false, code: "UNAUTHORIZED", message: "Customer session required" };
|
|
5
|
+
}
|
|
6
|
+
const principal = await verifier.verifyAccessToken(accessToken);
|
|
7
|
+
if (!principal) {
|
|
8
|
+
return { ok: false, code: "UNAUTHORIZED", message: "Customer session required" };
|
|
9
|
+
}
|
|
10
|
+
return { ok: true, userId: principal.principalId };
|
|
11
|
+
}
|
|
12
|
+
export async function optionalCustomerSubject(rawClient, accessToken) {
|
|
13
|
+
const client = rawClient;
|
|
14
|
+
if (!accessToken)
|
|
15
|
+
return null;
|
|
16
|
+
const result = await authenticateCustomerUser(client, accessToken);
|
|
17
|
+
return result.ok ? result.userId : null;
|
|
18
|
+
}
|
|
19
|
+
export async function authenticateCustomerUser(rawClient, accessToken) {
|
|
20
|
+
const client = rawClient;
|
|
21
|
+
return authenticateCustomerUserWith(createSupabaseIdentityVerifier(client), accessToken);
|
|
22
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const customerLifecycleStageSchema: z.ZodEnum<{
|
|
3
|
+
lead: "lead";
|
|
4
|
+
tester: "tester";
|
|
5
|
+
customer: "customer";
|
|
6
|
+
inactive: "inactive";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const customerMeRequestSchema: z.ZodObject<{}, z.core.$strict>;
|
|
9
|
+
export declare const customerMeResponseSchema: z.ZodObject<{
|
|
10
|
+
clientId: z.ZodString;
|
|
11
|
+
email: z.ZodString;
|
|
12
|
+
firstName: z.ZodNullable<z.ZodString>;
|
|
13
|
+
lastName: z.ZodNullable<z.ZodString>;
|
|
14
|
+
lifecycleStage: z.ZodEnum<{
|
|
15
|
+
lead: "lead";
|
|
16
|
+
tester: "tester";
|
|
17
|
+
customer: "customer";
|
|
18
|
+
inactive: "inactive";
|
|
19
|
+
}>;
|
|
20
|
+
subscriptions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
21
|
+
subscriptionId: z.ZodGUID;
|
|
22
|
+
status: z.ZodString;
|
|
23
|
+
cadenceDays: z.ZodNumber;
|
|
24
|
+
nextCycleAt: z.ZodNullable<z.ZodString>;
|
|
25
|
+
paymentMethodKind: z.ZodNullable<z.ZodString>;
|
|
26
|
+
}, z.core.$strict>>>;
|
|
27
|
+
recentOrders: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
28
|
+
orderId: z.ZodGUID;
|
|
29
|
+
orderRef: z.ZodString;
|
|
30
|
+
status: z.ZodString;
|
|
31
|
+
mode: z.ZodEnum<{
|
|
32
|
+
one_time: "one_time";
|
|
33
|
+
subscription_cycle: "subscription_cycle";
|
|
34
|
+
}>;
|
|
35
|
+
total: z.ZodObject<{
|
|
36
|
+
amountMinor: z.ZodNumber;
|
|
37
|
+
currency: z.ZodString;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
createdAt: z.ZodString;
|
|
40
|
+
}, z.core.$strict>>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export type CustomerMeResponse = z.infer<typeof customerMeResponseSchema>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
z.config({ jitless: true });
|
|
3
|
+
const platformCurrencySchema = z.string().regex(/^[A-Z]{3}$/);
|
|
4
|
+
export const customerLifecycleStageSchema = z.enum([
|
|
5
|
+
"lead",
|
|
6
|
+
"tester",
|
|
7
|
+
"customer",
|
|
8
|
+
"inactive",
|
|
9
|
+
]);
|
|
10
|
+
export const customerMeRequestSchema = z.object({}).strict();
|
|
11
|
+
export const customerMeResponseSchema = z.object({
|
|
12
|
+
clientId: z.string().min(1),
|
|
13
|
+
email: z.string().min(1),
|
|
14
|
+
firstName: z.string().nullable(),
|
|
15
|
+
lastName: z.string().nullable(),
|
|
16
|
+
lifecycleStage: customerLifecycleStageSchema,
|
|
17
|
+
subscriptions: z
|
|
18
|
+
.array(z
|
|
19
|
+
.object({
|
|
20
|
+
subscriptionId: z.guid(),
|
|
21
|
+
status: z.string().min(1),
|
|
22
|
+
cadenceDays: z.number().int().positive(),
|
|
23
|
+
nextCycleAt: z.string().datetime({ offset: true }).nullable(),
|
|
24
|
+
paymentMethodKind: z.string().nullable(),
|
|
25
|
+
})
|
|
26
|
+
.strict())
|
|
27
|
+
.optional(),
|
|
28
|
+
recentOrders: z
|
|
29
|
+
.array(z
|
|
30
|
+
.object({
|
|
31
|
+
orderId: z.guid(),
|
|
32
|
+
orderRef: z.string().regex(/^order_[a-z0-9-]+$/),
|
|
33
|
+
status: z.string().min(1),
|
|
34
|
+
mode: z.enum(["one_time", "subscription_cycle"]),
|
|
35
|
+
total: z.object({
|
|
36
|
+
amountMinor: z.number().int().nonnegative(),
|
|
37
|
+
currency: platformCurrencySchema,
|
|
38
|
+
}),
|
|
39
|
+
createdAt: z.string().datetime({ offset: true }),
|
|
40
|
+
})
|
|
41
|
+
.strict())
|
|
42
|
+
.optional(),
|
|
43
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { IdentityJwtLibraryLoader } from "./jwtLibrary.js";
|
|
2
|
+
import { authenticateCustomerUser } from "./customerAuthorization.js";
|
|
3
|
+
import { readBearerToken } from "./adminAuthorization.js";
|
|
4
|
+
import { createPostgresCustomerMePort } from "./postgresCustomerMe.js";
|
|
5
|
+
import { createSupabaseCustomerMePort as createManagedCustomerMePort } from "./managedCustomerMe.js";
|
|
6
|
+
import { createCustomerIdentityVerifier } from "./customerIdentityVerifier.js";
|
|
7
|
+
import type { CustomerMeDeps } from "./customerMeHandler.js";
|
|
8
|
+
import { resolveBundleId } from "../kernel/index.js";
|
|
9
|
+
type Env = Record<string, string | undefined>;
|
|
10
|
+
type CustomerRequest = Parameters<typeof readBearerToken>[0];
|
|
11
|
+
type ManagedReadEnv = {
|
|
12
|
+
url: string;
|
|
13
|
+
anonKey: string;
|
|
14
|
+
};
|
|
15
|
+
type CreateCustomerClient = (env: ManagedReadEnv, token: string | null) => unknown;
|
|
16
|
+
type ActorGateway = {
|
|
17
|
+
asActor<T>(claims: {
|
|
18
|
+
role: "authenticated";
|
|
19
|
+
sub: string;
|
|
20
|
+
}, work: (gateway: unknown) => Promise<T>): Promise<T>;
|
|
21
|
+
};
|
|
22
|
+
export type CustomerIdentityBindingOptions = {
|
|
23
|
+
authenticateManaged?: typeof authenticateCustomerUser;
|
|
24
|
+
createManagedClient?: CreateCustomerClient;
|
|
25
|
+
createManagedPort?: typeof createManagedCustomerMePort;
|
|
26
|
+
readManagedEnv?: () => ManagedReadEnv | null;
|
|
27
|
+
readToken?: typeof readBearerToken;
|
|
28
|
+
createPostgresGateway?: (env: Env) => ActorGateway;
|
|
29
|
+
createPostgresPort?: typeof createPostgresCustomerMePort;
|
|
30
|
+
createVerifier?: (config: Parameters<typeof createCustomerIdentityVerifier>[0]) => ReturnType<typeof createCustomerIdentityVerifier>;
|
|
31
|
+
resolveBundle?: typeof resolveBundleId;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Select the customer identity/read composition for one request. The direct
|
|
35
|
+
* path constructs its profile port only inside one actor-scoped transaction;
|
|
36
|
+
* it never uses a generic service lane or caller-provided token role.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createCustomerIdentityBindingFactory(defaults: {
|
|
39
|
+
loadJwt: IdentityJwtLibraryLoader;
|
|
40
|
+
createManagedClient: CreateCustomerClient;
|
|
41
|
+
readManagedEnv: (env: Env) => ManagedReadEnv | null;
|
|
42
|
+
bindRequestActorDataPort: (token: string, env: Env) => ActorGateway | null;
|
|
43
|
+
}): (req: CustomerRequest, env: Env, options?: CustomerIdentityBindingOptions) => Omit<CustomerMeDeps, "responseSchema"> | null;
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { authenticateCustomerUser, authenticateCustomerUserWith, } from "./customerAuthorization.js";
|
|
2
|
+
import { readBearerToken, } from "./adminAuthorization.js";
|
|
3
|
+
import { createPostgresCustomerMePort } from "./postgresCustomerMe.js";
|
|
4
|
+
import { createSupabaseCustomerMePort as createManagedCustomerMePort } from "./managedCustomerMe.js";
|
|
5
|
+
import { createCustomerIdentityVerifier } from "./customerIdentityVerifier.js";
|
|
6
|
+
import { resolveBundleId } from "../kernel/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* Select the customer identity/read composition for one request. The direct
|
|
9
|
+
* path constructs its profile port only inside one actor-scoped transaction;
|
|
10
|
+
* it never uses a generic service lane or caller-provided token role.
|
|
11
|
+
*/
|
|
12
|
+
export function createCustomerIdentityBindingFactory(defaults) {
|
|
13
|
+
return function createCustomerIdentityBinding(req, env, options = {}) {
|
|
14
|
+
const accessToken = (options.readToken ?? readBearerToken)(req);
|
|
15
|
+
const bundleId = (options.resolveBundle ?? resolveBundleId)(env);
|
|
16
|
+
if (bundleId !== "node-postgres") {
|
|
17
|
+
const readEnv = options.readManagedEnv ?? (() => defaults.readManagedEnv(env));
|
|
18
|
+
const managedEnv = readEnv();
|
|
19
|
+
if (!managedEnv)
|
|
20
|
+
return null;
|
|
21
|
+
const client = (options.createManagedClient ?? defaults.createManagedClient)(managedEnv, accessToken);
|
|
22
|
+
return {
|
|
23
|
+
authenticateUser: () => (options.authenticateManaged ?? authenticateCustomerUser)(client, accessToken),
|
|
24
|
+
mePort: (options.createManagedPort ?? createManagedCustomerMePort)(client),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const gateway = (options.createPostgresGateway ?? createActorGateway)(env);
|
|
28
|
+
const createPort = options.createPostgresPort ?? createPostgresCustomerMePort;
|
|
29
|
+
const createVerifier = options.createVerifier ?? ((config) => createCustomerIdentityVerifier(config, defaults.loadJwt));
|
|
30
|
+
const verifierConfig = {
|
|
31
|
+
audience: env.CUSTOMER_IDENTITY_AUDIENCE ?? "",
|
|
32
|
+
issuer: env.CUSTOMER_IDENTITY_ISSUER ?? "",
|
|
33
|
+
jwks: env.CUSTOMER_IDENTITY_JWKS ?? "",
|
|
34
|
+
};
|
|
35
|
+
let verifiedPrincipalId = null;
|
|
36
|
+
const mePort = {
|
|
37
|
+
getCustomerMe: (principalId) => {
|
|
38
|
+
if (principalId !== verifiedPrincipalId) {
|
|
39
|
+
return Promise.reject(new Error("customer_principal_mismatch"));
|
|
40
|
+
}
|
|
41
|
+
return gateway.asActor({ role: "authenticated", sub: verifiedPrincipalId }, (actorGateway) => createPort(actorGateway).getCustomerMe(principalId));
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
async authenticateUser() {
|
|
46
|
+
const authentication = await authenticateCustomerUserWith(createVerifier(verifierConfig), accessToken);
|
|
47
|
+
if (authentication.ok)
|
|
48
|
+
verifiedPrincipalId = authentication.userId;
|
|
49
|
+
return authentication;
|
|
50
|
+
},
|
|
51
|
+
mePort,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
function createActorGateway(env) {
|
|
55
|
+
const gateway = defaults.bindRequestActorDataPort("", env);
|
|
56
|
+
if (!gateway)
|
|
57
|
+
throw new Error("customer identity data gateway is unavailable");
|
|
58
|
+
return gateway;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IdentityJwtLibraryLoader } from "./jwtLibrary.js";
|
|
2
|
+
import type { IdentityVerifierPort } from "./ports.js";
|
|
3
|
+
export interface CustomerIdentityVerifierConfig {
|
|
4
|
+
audience: string;
|
|
5
|
+
issuer: string;
|
|
6
|
+
jwks: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function createCustomerIdentityVerifier(config: CustomerIdentityVerifierConfig, loadJwt: IdentityJwtLibraryLoader): IdentityVerifierPort;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const MAX_JWKS_BYTES = 12_288;
|
|
2
|
+
const MAX_TOKEN_BYTES = 8_192;
|
|
3
|
+
const MAX_CLAIM_BYTES = 256;
|
|
4
|
+
const KID = /^[A-Za-z0-9._-]{1,64}$/;
|
|
5
|
+
const BASE64URL_COORDINATE = /^[A-Za-z0-9_-]{43}$/;
|
|
6
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
7
|
+
const JWK_FIELDS = new Set(["alg", "crv", "kid", "kty", "use", "x", "y"]);
|
|
8
|
+
export function createCustomerIdentityVerifier(config, loadJwt) {
|
|
9
|
+
const issuer = readClaim(config.issuer, "issuer");
|
|
10
|
+
const audience = readClaim(config.audience, "audience");
|
|
11
|
+
const jwks = readJwks(config.jwks);
|
|
12
|
+
let keys = null;
|
|
13
|
+
let library;
|
|
14
|
+
const getLibrary = () => library ??= loadJwt();
|
|
15
|
+
const importedKeys = () => keys ??= getLibrary().then(({ importJWK }) => Promise.all(jwks.map(async (jwk) => [jwk.kid, await importJWK(jwk, "ES256")]))).then((entries) => new Map(entries));
|
|
16
|
+
return {
|
|
17
|
+
async verifyAccessToken(accessToken) {
|
|
18
|
+
if (typeof accessToken !== "string" || accessToken.length === 0 || accessToken.length > MAX_TOKEN_BYTES) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const resolvedKeys = await importedKeys();
|
|
22
|
+
const { jwtVerify } = await getLibrary();
|
|
23
|
+
try {
|
|
24
|
+
const verified = await jwtVerify(accessToken, async (header) => {
|
|
25
|
+
if (header.alg !== "ES256" || typeof header.kid !== "string" || !KID.test(header.kid)) {
|
|
26
|
+
throw new Error("customer identity token header rejected");
|
|
27
|
+
}
|
|
28
|
+
const key = resolvedKeys.get(header.kid);
|
|
29
|
+
if (!key)
|
|
30
|
+
throw new Error("customer identity token key rejected");
|
|
31
|
+
return key;
|
|
32
|
+
}, { algorithms: ["ES256"], audience, issuer });
|
|
33
|
+
if (typeof verified.payload.sub !== "string" || !UUID.test(verified.payload.sub))
|
|
34
|
+
return null;
|
|
35
|
+
return { email: null, emailVerified: false, principalId: verified.payload.sub };
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function readClaim(value, label) {
|
|
44
|
+
if (typeof value !== "string"
|
|
45
|
+
|| value.length === 0
|
|
46
|
+
|| value.length > MAX_CLAIM_BYTES
|
|
47
|
+
|| value.trim() !== value
|
|
48
|
+
|| [...value].some((character) => {
|
|
49
|
+
const code = character.charCodeAt(0);
|
|
50
|
+
return code <= 0x1f || code === 0x7f;
|
|
51
|
+
})) {
|
|
52
|
+
throw new Error(`customer identity ${label} configuration is invalid`);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
function readJwks(value) {
|
|
57
|
+
if (typeof value !== "string" || value.length === 0 || value.length > MAX_JWKS_BYTES) {
|
|
58
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
59
|
+
}
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(value);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
66
|
+
}
|
|
67
|
+
if (!isRecord(parsed) || !hasOnlyFields(parsed, new Set(["keys"])) || !Array.isArray(parsed.keys)) {
|
|
68
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
69
|
+
}
|
|
70
|
+
if (parsed.keys.length < 1 || parsed.keys.length > 2) {
|
|
71
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
72
|
+
}
|
|
73
|
+
const keys = parsed.keys.map(readJwk);
|
|
74
|
+
if (new Set(keys.map((key) => key.kid)).size !== keys.length) {
|
|
75
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
76
|
+
}
|
|
77
|
+
return keys;
|
|
78
|
+
}
|
|
79
|
+
function readJwk(value) {
|
|
80
|
+
if (!isRecord(value)
|
|
81
|
+
|| !hasOnlyFields(value, JWK_FIELDS)
|
|
82
|
+
|| value.kty !== "EC"
|
|
83
|
+
|| value.crv !== "P-256"
|
|
84
|
+
|| value.alg !== "ES256"
|
|
85
|
+
|| value.use !== "sig"
|
|
86
|
+
|| typeof value.kid !== "string"
|
|
87
|
+
|| !KID.test(value.kid)
|
|
88
|
+
|| typeof value.x !== "string"
|
|
89
|
+
|| !BASE64URL_COORDINATE.test(value.x)
|
|
90
|
+
|| typeof value.y !== "string"
|
|
91
|
+
|| !BASE64URL_COORDINATE.test(value.y)) {
|
|
92
|
+
throw new Error("customer identity JWKS configuration is invalid");
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
function isRecord(value) {
|
|
97
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
98
|
+
}
|
|
99
|
+
function hasOnlyFields(value, fields) {
|
|
100
|
+
return Object.keys(value).every((field) => fields.has(field));
|
|
101
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type IdentityResponseOptions } from "./response.js";
|
|
2
|
+
import type { HttpRequest, HttpResponse } from "../http/index.js";
|
|
3
|
+
import type { MagicLinkAuthClient, MagicLinkRateLimitClient, MagicLinkDecision } from "./magicLinkPorts.js";
|
|
4
|
+
import { resolveCustomerSessionBinding } from "./customerSessionBinding.js";
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
export type CustomerMagicLinkEnvironment = {
|
|
7
|
+
url: string;
|
|
8
|
+
anonKey: string;
|
|
9
|
+
serviceRoleKey: string;
|
|
10
|
+
};
|
|
11
|
+
export interface CustomerMagicLinkHandlerOptions<E extends CustomerMagicLinkEnvironment = CustomerMagicLinkEnvironment> extends IdentityResponseOptions {
|
|
12
|
+
enabled: () => boolean;
|
|
13
|
+
env: Record<string, string | undefined>;
|
|
14
|
+
disabledDetails?: Record<string, unknown>;
|
|
15
|
+
requestSchema: z.ZodType<{
|
|
16
|
+
email: string;
|
|
17
|
+
locale: "pl" | "en";
|
|
18
|
+
returnTo?: string;
|
|
19
|
+
}>;
|
|
20
|
+
responseSchema: z.ZodType<{
|
|
21
|
+
accepted: true;
|
|
22
|
+
}>;
|
|
23
|
+
readEnvironment: () => E | null;
|
|
24
|
+
createCustomerClient: (env: E, token: null) => MagicLinkAuthClient;
|
|
25
|
+
createCustomerServiceClient: (env: E) => unknown;
|
|
26
|
+
checkAttempt: (input: {
|
|
27
|
+
client: MagicLinkRateLimitClient;
|
|
28
|
+
ip: string;
|
|
29
|
+
email: string;
|
|
30
|
+
}) => Promise<MagicLinkDecision>;
|
|
31
|
+
extractClientIp: (headers: HttpRequest["headers"]) => string;
|
|
32
|
+
padResponseTime: (startedAt: number, floor: number) => Promise<void>;
|
|
33
|
+
redirectOrigins?: readonly string[];
|
|
34
|
+
resolveOrigin?: (req: HttpRequest) => string | null;
|
|
35
|
+
callbackPath: (locale: "pl" | "en") => string;
|
|
36
|
+
resolveSession: typeof resolveCustomerSessionBinding;
|
|
37
|
+
}
|
|
38
|
+
export declare function createCustomerMagicLinkHandler<E extends CustomerMagicLinkEnvironment>(options: CustomerMagicLinkHandlerOptions<E>): (req: HttpRequest, res: HttpResponse) => Promise<void>;
|