@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,40 @@
|
|
|
1
|
+
import type { SupabaseCreateClient } from "../data/index.js";
|
|
2
|
+
import type { ManagedIdentityClient } from "./managedClient.js";
|
|
3
|
+
import type { AdminAuthPort, AdminAuthorizationResult, AdminPrincipalRole } from "./ports.js";
|
|
4
|
+
import { authorizeAdminWithUser, type AdminAuthorization } from "./adminAuthorization.js";
|
|
5
|
+
|
|
6
|
+
export function createSupabaseAdminAuth(rawClient: unknown): AdminAuthPort {
|
|
7
|
+
const client = rawClient as ManagedIdentityClient;
|
|
8
|
+
return {
|
|
9
|
+
async authorize(
|
|
10
|
+
accessToken: string | null,
|
|
11
|
+
options?: { allowedRoles?: readonly AdminPrincipalRole[] },
|
|
12
|
+
): Promise<AdminAuthorizationResult> {
|
|
13
|
+
const authz: AdminAuthorization = await authorizeAdminWithUser(client, accessToken, options);
|
|
14
|
+
if (authz.ok === false) {
|
|
15
|
+
return { ok: false, code: authz.code, message: authz.message };
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
ok: true,
|
|
19
|
+
principalId: authz.userId,
|
|
20
|
+
role: authz.role,
|
|
21
|
+
isMachineActor: authz.isMachineActor,
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
export function createSupabaseAdminAuthFromEnv(
|
|
29
|
+
env: { url: string; anonKey: string },
|
|
30
|
+
accessToken: string | null,
|
|
31
|
+
createClient: SupabaseCreateClient,
|
|
32
|
+
): AdminAuthPort {
|
|
33
|
+
const client = createClient(env.url, env.anonKey, {
|
|
34
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
35
|
+
global: {
|
|
36
|
+
headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return createSupabaseAdminAuth(client as ManagedIdentityClient);
|
|
40
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import type { AdminUserInviteRole } from "./inviteAdminUserUseCase.js";
|
|
2
|
+
import type { ManagedOperatorMembershipResult, OperatorInvitationConflict } from "./contracts/operatorInvitations.js";
|
|
3
|
+
import type { ManagedIdentityClient } from "./managedClient.js";
|
|
4
|
+
import type { InviteAdminUserGateway } from "./inviteAdminUserUseCase.js";
|
|
5
|
+
import type { RemoveAdminUserGateway } from "./removeAdminUserUseCase.js";
|
|
6
|
+
interface InviteAdminUserQuery {
|
|
7
|
+
insert(row: { id: string; email: string; role: AdminUserInviteRole; membership_state: "active"; membership_provenance: "invitation"; membership_accepted_at: string }): PromiseLike<{ error: { code?: string; message?: string } | null }>;
|
|
8
|
+
select(columns: string): { eq(column: string, value: string): {
|
|
9
|
+
maybeSingle(): PromiseLike<{ data: { id: string; role?: string; membership_state?: string; is_machine_actor?: boolean | null } | null; error?: unknown }>;
|
|
10
|
+
} };
|
|
11
|
+
}
|
|
12
|
+
export interface InviteAdminUserClient {
|
|
13
|
+
auth: {
|
|
14
|
+
getUser(token: string): PromiseLike<{ data: { user: { id: string } | null }; error: unknown }>;
|
|
15
|
+
admin: {
|
|
16
|
+
listUsers(options: { page: number; perPage: number }): PromiseLike<{ data: { users: Array<{ id: string; email?: string | null }>; nextPage?: number | null } | null; error: unknown }>;
|
|
17
|
+
inviteUserByEmail(email: string, options: { redirectTo: string }): PromiseLike<{
|
|
18
|
+
data: { user: { id: string } | null }; error: { message: string } | null;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
from(table: "admin_users"): InviteAdminUserQuery;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface RemoveAdminUserQuery {
|
|
26
|
+
select(columns: string): {
|
|
27
|
+
eq(column: string, value: string): RemoveAdminUserQueryResult;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface RemoveAdminUserQueryResult {
|
|
32
|
+
eq(column: string, value: string): RemoveAdminUserQueryResult;
|
|
33
|
+
maybeSingle(): PromiseLike<{ data: { id: string; role: string } | null; error: { message: string } | null }>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface RemoveAdminUserClient {
|
|
37
|
+
auth: {
|
|
38
|
+
getUser(token: string): PromiseLike<{ data: { user: { id: string } | null }; error: unknown }>;
|
|
39
|
+
};
|
|
40
|
+
from(table: "admin_users"): RemoveAdminUserQuery;
|
|
41
|
+
rpc(
|
|
42
|
+
fn: "admin_revoke_admin_user",
|
|
43
|
+
args: { p_target: string; p_reason: string | null },
|
|
44
|
+
): PromiseLike<{ error: { message: string } | null }>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function createInviteAdminUserGateway(clientFactory: () => InviteAdminUserClient): InviteAdminUserGateway & {
|
|
48
|
+
activateMembership(input: { principalId: string; email: string; role: AdminUserInviteRole }): Promise<ManagedOperatorMembershipResult | { code: OperatorInvitationConflict }>;
|
|
49
|
+
} {
|
|
50
|
+
let client: InviteAdminUserClient | null = null;
|
|
51
|
+
const getClient = (): InviteAdminUserClient => client ??= clientFactory();
|
|
52
|
+
|
|
53
|
+
async function membership(principalId: string) {
|
|
54
|
+
const { data, error } = await getClient().from("admin_users").select("id, role, membership_state, is_machine_actor").eq("id", principalId).maybeSingle();
|
|
55
|
+
if (error) throw error;
|
|
56
|
+
return data;
|
|
57
|
+
}
|
|
58
|
+
function existing(row: NonNullable<Awaited<ReturnType<typeof membership>>>, role: AdminUserInviteRole): ManagedOperatorMembershipResult | { code: OperatorInvitationConflict } {
|
|
59
|
+
if (row.is_machine_actor !== false) return { code: "IDENTITY_CONFLICT" };
|
|
60
|
+
if (row.membership_state === "revoked") return { code: "MANAGED_REINVITE_UNSUPPORTED" };
|
|
61
|
+
if (row.membership_state !== "active") return { code: "IDENTITY_CONFLICT" };
|
|
62
|
+
if (row.role !== role) return { code: "INVITATION_ROLE_CONFLICT" };
|
|
63
|
+
return { principalId: row.id, role, membershipState: "active", code: "ALREADY_ACTIVE" };
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
async activateMembership(input) {
|
|
67
|
+
const before = await membership(input.principalId);
|
|
68
|
+
if (before) return existing(before, input.role);
|
|
69
|
+
const { error } = await getClient().from("admin_users").insert({ id: input.principalId, email: input.email, role: input.role,
|
|
70
|
+
membership_state: "active", membership_provenance: "invitation", membership_accepted_at: new Date().toISOString() });
|
|
71
|
+
if (error) {
|
|
72
|
+
if (error.code !== "23505") throw error;
|
|
73
|
+
const raced = await membership(input.principalId);
|
|
74
|
+
if (!raced) throw error;
|
|
75
|
+
return existing(raced, input.role);
|
|
76
|
+
}
|
|
77
|
+
return { principalId: input.principalId, role: input.role, membershipState: "active", code: "MEMBERSHIP_CREATED" };
|
|
78
|
+
},
|
|
79
|
+
async getUser(accessToken) {
|
|
80
|
+
const { data, error } = await getClient().auth.getUser(accessToken);
|
|
81
|
+
return { user: data?.user ?? null, error };
|
|
82
|
+
},
|
|
83
|
+
async findAdminUser(userId) {
|
|
84
|
+
const { data, error } = await getClient()
|
|
85
|
+
.from("admin_users")
|
|
86
|
+
.select("id, role, membership_state, is_machine_actor")
|
|
87
|
+
.eq("id", userId)
|
|
88
|
+
.maybeSingle();
|
|
89
|
+
if (error) throw error;
|
|
90
|
+
return data && typeof data.role === "string" && typeof data.membership_state === "string" ? { id: data.id, role: data.role, membership_state: data.membership_state, is_machine_actor: data.is_machine_actor !== false } : null;
|
|
91
|
+
},
|
|
92
|
+
async findAdminUserByEmail(email) {
|
|
93
|
+
const { data, error } = await getClient()
|
|
94
|
+
.from("admin_users")
|
|
95
|
+
.select("id")
|
|
96
|
+
.eq("email", email)
|
|
97
|
+
.maybeSingle();
|
|
98
|
+
if (error) throw error;
|
|
99
|
+
return data ? { id: data.id } : null;
|
|
100
|
+
},
|
|
101
|
+
async findAuthUserByEmail(email) {
|
|
102
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
103
|
+
const perPage = 1000;
|
|
104
|
+
const maxUsers = 5000;
|
|
105
|
+
let page = 1;
|
|
106
|
+
let scanned = 0;
|
|
107
|
+
while (scanned < maxUsers) {
|
|
108
|
+
const { data, error } = await getClient().auth.admin.listUsers({ page, perPage });
|
|
109
|
+
if (error) throw error;
|
|
110
|
+
const users = data?.users ?? [];
|
|
111
|
+
const match = users.find((user) => (user.email ?? "").trim().toLowerCase() === normalizedEmail);
|
|
112
|
+
if (match) return { id: match.id, email: match.email };
|
|
113
|
+
scanned += users.length;
|
|
114
|
+
if (!data?.nextPage) return null;
|
|
115
|
+
page = data.nextPage;
|
|
116
|
+
}
|
|
117
|
+
throw new Error("auth_user_lookup_cap_exceeded");
|
|
118
|
+
},
|
|
119
|
+
async inviteAuthUser(input) {
|
|
120
|
+
const { data, error } = await getClient().auth.admin.inviteUserByEmail(input.email, {
|
|
121
|
+
redirectTo: input.redirectTo,
|
|
122
|
+
});
|
|
123
|
+
return { user: data.user, error };
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function createRemoveAdminUserGateway(clientFactory: () => RemoveAdminUserClient): RemoveAdminUserGateway {
|
|
129
|
+
let client: RemoveAdminUserClient | null = null;
|
|
130
|
+
const getClient = (): RemoveAdminUserClient => client ??= clientFactory();
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
async getUser(accessToken) {
|
|
134
|
+
const { data, error } = await getClient().auth.getUser(accessToken);
|
|
135
|
+
return { user: data?.user ?? null, error };
|
|
136
|
+
},
|
|
137
|
+
async findAdminUser(userId) {
|
|
138
|
+
const { data, error } = await getClient()
|
|
139
|
+
.from("admin_users")
|
|
140
|
+
.select("id, role")
|
|
141
|
+
.eq("id", userId)
|
|
142
|
+
.eq("membership_state", "active")
|
|
143
|
+
.maybeSingle();
|
|
144
|
+
if (error) throw error;
|
|
145
|
+
return data;
|
|
146
|
+
},
|
|
147
|
+
async revokeAdminUser(userId) {
|
|
148
|
+
return await getClient().rpc("admin_revoke_admin_user", {
|
|
149
|
+
p_target: userId,
|
|
150
|
+
p_reason: null,
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
/** Managed eligibility depends only on active native membership and known roles. */
|
|
158
|
+
export async function managedOperatorMagicLinkEligibility(rawClient: unknown, email: string): Promise<"eligible" | "not_allowlisted" | "role_not_allowed"> {
|
|
159
|
+
const client = rawClient as ManagedIdentityClient;
|
|
160
|
+
const { data, error } = await client.from("admin_users").select("id, role").eq("email", email.trim().toLowerCase()).eq("membership_state", "active").maybeSingle();
|
|
161
|
+
if (error) throw error;
|
|
162
|
+
if (!data) return "not_allowlisted";
|
|
163
|
+
return data.role === "admin" || data.role === "distributor" ? "eligible" : "role_not_allowed";
|
|
164
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { SupabaseCreateClient } from "../data/index.js";
|
|
2
|
+
|
|
3
|
+
export interface ManagedIdentityUser {
|
|
4
|
+
id: string;
|
|
5
|
+
email?: string | null;
|
|
6
|
+
email_confirmed_at?: string | null;
|
|
7
|
+
user_metadata?: Record<string, unknown> | null;
|
|
8
|
+
}
|
|
9
|
+
export interface ManagedIdentityRow {
|
|
10
|
+
id: string;
|
|
11
|
+
email?: string | null;
|
|
12
|
+
auth_user_id?: string | null;
|
|
13
|
+
role?: string | null;
|
|
14
|
+
is_machine_actor?: boolean | null;
|
|
15
|
+
membership_state?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ManagedIdentityQuery extends PromiseLike<{ data: ManagedIdentityRow[] | null; error: unknown }> {
|
|
18
|
+
select(columns: string): ManagedIdentityQuery;
|
|
19
|
+
eq(column: string, value: string): ManagedIdentityQuery;
|
|
20
|
+
filter(column: string, operator: "imatch", value: string): ManagedIdentityQuery;
|
|
21
|
+
is(column: string, value: null): ManagedIdentityQuery;
|
|
22
|
+
order(column: string, options: { ascending: boolean }): ManagedIdentityQuery;
|
|
23
|
+
limit(count: number): ManagedIdentityQuery;
|
|
24
|
+
maybeSingle(): PromiseLike<{ data: ManagedIdentityRow | null; error: unknown }>;
|
|
25
|
+
single(): PromiseLike<{ data: ManagedIdentityRow | null; error: unknown }>;
|
|
26
|
+
}
|
|
27
|
+
export interface ManagedIdentityTable {
|
|
28
|
+
select(columns: string): ManagedIdentityQuery;
|
|
29
|
+
update(value: Record<string, unknown>): ManagedIdentityQuery;
|
|
30
|
+
insert(value: Record<string, unknown>): ManagedIdentityQuery;
|
|
31
|
+
}
|
|
32
|
+
/** Only the methods consumed by the identity adapters; the host owns the SDK. */
|
|
33
|
+
export interface ManagedIdentityClient {
|
|
34
|
+
from(table: string): ManagedIdentityTable;
|
|
35
|
+
auth: {
|
|
36
|
+
getUser(token: string): PromiseLike<{ data: { user: ManagedIdentityUser | null }; error: unknown }>;
|
|
37
|
+
admin: {
|
|
38
|
+
listUsers(options: { page: number; perPage: number }): PromiseLike<{
|
|
39
|
+
data: { users: ManagedIdentityUser[]; nextPage?: number | null }; error: unknown;
|
|
40
|
+
}>;
|
|
41
|
+
getUserById(id: string): PromiseLike<{ data: { user: ManagedIdentityUser | null }; error: unknown }>;
|
|
42
|
+
createUser(input: { email: string; email_confirm: boolean }): PromiseLike<{ data: { user: ManagedIdentityUser | null }; error: unknown }>;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function createManagedIdentityClients(createClient: SupabaseCreateClient) {
|
|
48
|
+
const actor = (env: { url: string; anonKey: string }, accessToken: string | null): ManagedIdentityClient =>
|
|
49
|
+
createClient(env.url, env.anonKey, {
|
|
50
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
51
|
+
global: { headers: accessToken ? { Authorization: `Bearer ${accessToken}` } : {} },
|
|
52
|
+
}) as ManagedIdentityClient;
|
|
53
|
+
const service = (env: { url: string; serviceRoleKey: string }): ManagedIdentityClient =>
|
|
54
|
+
createClient(env.url, env.serviceRoleKey, {
|
|
55
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
56
|
+
}) as ManagedIdentityClient;
|
|
57
|
+
return { actor, service };
|
|
58
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { EmailTrustPolicy } from "./emailTrustPolicy.js";
|
|
2
|
+
import type { ManagedIdentityClient, ManagedIdentityRow, ManagedIdentityUser } from "./managedClient.js";
|
|
3
|
+
import type { ClientAuthLinkStore } from "./ports.js";
|
|
4
|
+
export function createSupabaseClientAuthLinkStore(rawClient: unknown, emailTrustPolicy: EmailTrustPolicy): ClientAuthLinkStore {
|
|
5
|
+
const client = rawClient as ManagedIdentityClient;
|
|
6
|
+
return {
|
|
7
|
+
emailTrustPolicy,
|
|
8
|
+
async findClientByEmail(email) {
|
|
9
|
+
const rows = await findManagedContactsByEmail(client, email, true);
|
|
10
|
+
const row = rows[0];
|
|
11
|
+
if (!row) return null;
|
|
12
|
+
return { id: row.id, authUserId: row.auth_user_id ?? null };
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
async findAuthUserIdByEmail(email) {
|
|
16
|
+
const perPage = 1000;
|
|
17
|
+
const maxUsers = 5000;
|
|
18
|
+
let page = 1;
|
|
19
|
+
let scanned = 0;
|
|
20
|
+
|
|
21
|
+
while (scanned < maxUsers) {
|
|
22
|
+
const { data, error } = await client.auth.admin.listUsers({ page, perPage });
|
|
23
|
+
if (error) throw error;
|
|
24
|
+
const users: ManagedIdentityUser[] = data.users;
|
|
25
|
+
const match = users.find(
|
|
26
|
+
(u) => (u.email ?? "").trim().toLowerCase() === email,
|
|
27
|
+
);
|
|
28
|
+
if (match) return match.id;
|
|
29
|
+
scanned += users.length;
|
|
30
|
+
const nextPage = "nextPage" in data ? data.nextPage : null;
|
|
31
|
+
if (!nextPage) return null;
|
|
32
|
+
page = nextPage;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
throw new Error("auth_user_lookup_cap_exceeded");
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async findAuthUserEmailById(authUserId) {
|
|
39
|
+
const { data, error } = await client.auth.admin.getUserById(authUserId);
|
|
40
|
+
if (error) throw error;
|
|
41
|
+
return data.user?.email ?? null;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
async createAuthUser(email) {
|
|
45
|
+
const { data, error } = await client.auth.admin.createUser({
|
|
46
|
+
email,
|
|
47
|
+
email_confirm: false,
|
|
48
|
+
});
|
|
49
|
+
if (error && isAlreadyRegistered(error)) return null;
|
|
50
|
+
if (error) throw error;
|
|
51
|
+
if (!data.user) throw new Error("createUser returned no user");
|
|
52
|
+
return data.user.id;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
async findAdminIdentity(authUserId) {
|
|
56
|
+
const { data, error } = await client
|
|
57
|
+
.from("admin_users")
|
|
58
|
+
.select("id, is_machine_actor")
|
|
59
|
+
.eq("id", authUserId)
|
|
60
|
+
.maybeSingle();
|
|
61
|
+
if (error) throw error;
|
|
62
|
+
if (!data) return null;
|
|
63
|
+
return { isMachineActor: data.is_machine_actor !== false };
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
async setClientAuthUserId(clientId, authUserId) {
|
|
67
|
+
const { data, error } = await client
|
|
68
|
+
.from("clients")
|
|
69
|
+
.update({ auth_user_id: authUserId })
|
|
70
|
+
.eq("id", clientId)
|
|
71
|
+
.is("auth_user_id", null)
|
|
72
|
+
.select("auth_user_id")
|
|
73
|
+
.maybeSingle();
|
|
74
|
+
if (error) throw error;
|
|
75
|
+
if (data?.auth_user_id === authUserId) {
|
|
76
|
+
return { ok: true, alreadyLinked: false };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { data: current, error: currentError } = await client
|
|
80
|
+
.from("clients")
|
|
81
|
+
.select("auth_user_id")
|
|
82
|
+
.eq("id", clientId)
|
|
83
|
+
.maybeSingle();
|
|
84
|
+
if (currentError) throw currentError;
|
|
85
|
+
if (current?.auth_user_id === authUserId) {
|
|
86
|
+
return { ok: true, alreadyLinked: true };
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
code: "CLIENT_AUTH_LINK_CONFLICT",
|
|
91
|
+
existingAuthUserId: current?.auth_user_id ?? null,
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
function isAlreadyRegistered(error: unknown): boolean {
|
|
99
|
+
const failure = (error ?? {}) as { code?: unknown; status?: unknown; message?: unknown };
|
|
100
|
+
if (failure.code === "email_exists" || failure.code === "user_already_exists") return true;
|
|
101
|
+
return failure.status === 422 && typeof failure.message === "string"
|
|
102
|
+
&& /already (been )?registered/i.test(failure.message);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function findManagedContactsByEmail(
|
|
106
|
+
client: ManagedIdentityClient,
|
|
107
|
+
email: string,
|
|
108
|
+
oldestFirst: boolean,
|
|
109
|
+
): Promise<ManagedIdentityRow[]> {
|
|
110
|
+
const normalized = email.trim().toLowerCase();
|
|
111
|
+
// Escaping bounds the database prefilter; Unicode regex folding can still
|
|
112
|
+
// widen it, so only exact normalized addresses may cross this boundary.
|
|
113
|
+
let query = client.from("clients")
|
|
114
|
+
.select("id, email, auth_user_id")
|
|
115
|
+
.filter("email", "imatch", `^${normalized.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&")}$`);
|
|
116
|
+
if (oldestFirst) query = query.order("created_at", { ascending: true });
|
|
117
|
+
const { data, error } = await query.limit(10);
|
|
118
|
+
if (error) throw error;
|
|
119
|
+
return (data ?? []).filter((row) => row.email?.trim().toLowerCase() === normalized);
|
|
120
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ManagedIdentityClient } from "./managedClient.js";
|
|
2
|
+
import type { CustomerMeResponse } from "./customerContracts.js";
|
|
3
|
+
import type { CustomerMePort } from "./customerPorts.js";
|
|
4
|
+
|
|
5
|
+
type ManagedCustomerClient = ManagedIdentityClient;
|
|
6
|
+
type LinkedCustomerRow = {
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
first_name: string | null;
|
|
10
|
+
last_name: string | null;
|
|
11
|
+
phone: string | null;
|
|
12
|
+
lifecycle_stage: CustomerMeResponse["lifecycleStage"];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function readLinkedCustomer(
|
|
16
|
+
rawClient: unknown,
|
|
17
|
+
userId: string,
|
|
18
|
+
includePhone = false,
|
|
19
|
+
): Promise<LinkedCustomerRow | null> {
|
|
20
|
+
const client = rawClient as ManagedCustomerClient;
|
|
21
|
+
const { data, error } = await client
|
|
22
|
+
.from("clients")
|
|
23
|
+
.select(includePhone
|
|
24
|
+
? "id, email, first_name, last_name, phone, lifecycle_stage"
|
|
25
|
+
: "id, email, first_name, last_name, lifecycle_stage")
|
|
26
|
+
.eq("auth_user_id", userId)
|
|
27
|
+
.maybeSingle();
|
|
28
|
+
if (error) throw error;
|
|
29
|
+
return data as unknown as LinkedCustomerRow | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export function createSupabaseCustomerMePort(
|
|
34
|
+
rawClient: unknown,
|
|
35
|
+
): CustomerMePort {
|
|
36
|
+
const client = rawClient as ManagedCustomerClient;
|
|
37
|
+
return {
|
|
38
|
+
async getCustomerMe(userId): Promise<CustomerMeResponse | null> {
|
|
39
|
+
const data = await readLinkedCustomer(client, userId);
|
|
40
|
+
if (!data) return null;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
clientId: data.id,
|
|
44
|
+
email: data.email,
|
|
45
|
+
firstName: data.first_name,
|
|
46
|
+
lastName: data.last_name,
|
|
47
|
+
lifecycleStage:
|
|
48
|
+
data.lifecycle_stage as CustomerMeResponse["lifecycleStage"],
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { EmailTrustAssessment, EmailTrustPolicy } from "./emailTrustPolicy.js";
|
|
2
|
+
|
|
3
|
+
const unavailable: EmailTrustAssessment = { trusted: false, code: "EMAIL_TRUST_SETTINGS_UNAVAILABLE" };
|
|
4
|
+
const refused: EmailTrustAssessment = { trusted: false, code: "EMAIL_TRUST_ENVELOPE_REFUSED" };
|
|
5
|
+
const providerId = /^[a-z][a-z0-9_-]*$/;
|
|
6
|
+
/** Server-side assertion by the adopter, never a provider certification. */
|
|
7
|
+
export function parseEmailVerifyingProviders(value: string): readonly string[] {
|
|
8
|
+
if (!value.trim()) return [];
|
|
9
|
+
const entries = value.split(",").map(entry => entry.trim().toLowerCase());
|
|
10
|
+
if (entries.some(entry => !providerId.test(entry))) throw new Error("Invalid email-verifying provider declaration");
|
|
11
|
+
return [...new Set(entries)].sort();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** One immutable origin/key/allowlist binding; import and construction perform no I/O. */
|
|
15
|
+
export function createManagedEmailTrustPolicy(options: {
|
|
16
|
+
authBaseUrl: string;
|
|
17
|
+
publicKey: string;
|
|
18
|
+
emailVerifyingProviders?: readonly string[];
|
|
19
|
+
fetch?: typeof globalThis.fetch;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
}): EmailTrustPolicy {
|
|
22
|
+
const origin = new URL(options.authBaseUrl);
|
|
23
|
+
if (!["http:", "https:"].includes(origin.protocol) || origin.username || origin.password
|
|
24
|
+
|| origin.pathname !== "/" || origin.search || origin.hash || !options.publicKey.trim()) {
|
|
25
|
+
throw new Error("Invalid identity email-trust configuration");
|
|
26
|
+
}
|
|
27
|
+
const url = new URL("/auth/v1/settings", origin);
|
|
28
|
+
const publicKey = options.publicKey;
|
|
29
|
+
const allowed = new Set(parseEmailVerifyingProviders((options.emailVerifyingProviders ?? []).join(",")));
|
|
30
|
+
const fetchSettings = options.fetch ?? globalThis.fetch;
|
|
31
|
+
const now = options.now ?? Date.now;
|
|
32
|
+
let cached: { result: EmailTrustAssessment; expires: number } | undefined;
|
|
33
|
+
let inFlight: Promise<EmailTrustAssessment> | undefined;
|
|
34
|
+
|
|
35
|
+
function decode(value: unknown): EmailTrustAssessment {
|
|
36
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return unavailable;
|
|
37
|
+
const { mailer_autoconfirm: automatic, external } = value as Record<string, unknown>;
|
|
38
|
+
if (typeof automatic !== "boolean" || !external || typeof external !== "object" || Array.isArray(external)) return unavailable;
|
|
39
|
+
const entries = Object.entries(external);
|
|
40
|
+
if (entries.some(([key, enabled]) => !providerId.test(key) || typeof enabled !== "boolean")) return unavailable;
|
|
41
|
+
if (automatic || entries.some(([key, enabled]) => enabled && key !== "email" && !allowed.has(key))) return refused;
|
|
42
|
+
return { trusted: true };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function load(): Promise<EmailTrustAssessment> {
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
48
|
+
const deadline = new Promise<never>((_, reject) => {
|
|
49
|
+
timer = setTimeout(() => { controller.abort(); reject(new Error("Identity settings deadline")); }, 3000);
|
|
50
|
+
});
|
|
51
|
+
async function read(): Promise<EmailTrustAssessment> {
|
|
52
|
+
const response = await fetchSettings(url, {
|
|
53
|
+
headers: { apikey: publicKey }, redirect: "error", signal: controller.signal,
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok || response.redirected || !response.body) return unavailable;
|
|
56
|
+
const reader = response.body.getReader();
|
|
57
|
+
let bytes = 0;
|
|
58
|
+
const chunks: Uint8Array[] = [];
|
|
59
|
+
try {
|
|
60
|
+
while (true) {
|
|
61
|
+
const chunk = await reader.read();
|
|
62
|
+
if (chunk.done) break;
|
|
63
|
+
bytes += chunk.value.byteLength;
|
|
64
|
+
if (bytes > 65536) { controller.abort(); void reader.cancel().catch(() => {}); return unavailable; }
|
|
65
|
+
chunks.push(chunk.value);
|
|
66
|
+
}
|
|
67
|
+
} finally { reader.releaseLock(); }
|
|
68
|
+
const body = new Uint8Array(bytes);
|
|
69
|
+
let offset = 0;
|
|
70
|
+
for (const chunk of chunks) { body.set(chunk, offset); offset += chunk.byteLength; }
|
|
71
|
+
return decode(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(body)));
|
|
72
|
+
}
|
|
73
|
+
try { return await Promise.race([read(), deadline]); }
|
|
74
|
+
catch { return unavailable; }
|
|
75
|
+
finally { controller.abort(); clearTimeout(timer); }
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
async assess() {
|
|
79
|
+
if (cached && now() < cached.expires) return cached.result;
|
|
80
|
+
if (!inFlight) {
|
|
81
|
+
inFlight = load().then(result => {
|
|
82
|
+
const ttl = !result.trusted && result.code === "EMAIL_TRUST_SETTINGS_UNAVAILABLE" ? 5000 : 60000;
|
|
83
|
+
cached = { result, expires: now() + ttl };
|
|
84
|
+
return result;
|
|
85
|
+
}).finally(() => { inFlight = undefined; });
|
|
86
|
+
}
|
|
87
|
+
return inFlight;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ManagedIdentityClient } from "./managedClient.js";
|
|
2
|
+
import type { IdentityVerifierPort, VerifiedPrincipal } from "./ports.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export function createSupabaseIdentityVerifier(rawClient: unknown): IdentityVerifierPort {
|
|
6
|
+
const client = rawClient as ManagedIdentityClient;
|
|
7
|
+
return {
|
|
8
|
+
async verifyAccessToken(accessToken: string): Promise<VerifiedPrincipal | null> {
|
|
9
|
+
const { data, error } = await client.auth.getUser(accessToken);
|
|
10
|
+
if (error || !data.user) return null;
|
|
11
|
+
|
|
12
|
+
const user = data.user;
|
|
13
|
+
return {
|
|
14
|
+
principalId: user.id,
|
|
15
|
+
email: user.email ?? null,
|
|
16
|
+
emailVerified: Boolean(user.email_confirmed_at),
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ManagedIdentityClient } from "./managedClient.js";
|
|
2
|
+
import { PrivacyRefusal, type PrivacyStore } from "./privacyPorts.js";
|
|
3
|
+
import type { PrivacyJson } from "./contracts/privacy.js";
|
|
4
|
+
|
|
5
|
+
/** Reads only committed service projections. No managed write or provider delete is composed. */
|
|
6
|
+
export function createManagedPrivacyStore(): PrivacyStore<ManagedIdentityClient> {
|
|
7
|
+
const refuse = async (): Promise<never> => { throw new PrivacyRefusal("MANAGED_PRIVACY_ERASURE_UNAVAILABLE"); };
|
|
8
|
+
return {
|
|
9
|
+
erasureSupported: false, prepareErasure: refuse, authorizeErasure: refuse, eraseIdentity: refuse, saveReceipt: refuse,
|
|
10
|
+
async findReceipt() { return null; },
|
|
11
|
+
async resolve(client, ref) {
|
|
12
|
+
const query = client.from("clients").select("id, email, auth_user_id, first_name, last_name, phone");
|
|
13
|
+
const { data: contact, error } = await query.eq(ref.kind === "contact" ? "id" : "auth_user_id", ref.kind === "contact" ? ref.contactId : ref.principalId).maybeSingle();
|
|
14
|
+
if (error) throw new PrivacyRefusal("PRIVACY_ASSESSMENT_UNAVAILABLE");
|
|
15
|
+
const principalId = ref.kind === "principal" ? ref.principalId : contact?.auth_user_id ?? null;
|
|
16
|
+
let principal: PrivacyJson = null;
|
|
17
|
+
let membership: PrivacyJson = null;
|
|
18
|
+
if (principalId) {
|
|
19
|
+
const result = await client.auth.admin.getUserById(principalId);
|
|
20
|
+
if (result.error) {
|
|
21
|
+
const failure = result.error as { status?: unknown; code?: unknown };
|
|
22
|
+
if (!contact && (failure.status === 404 || failure.code === "user_not_found")) return null;
|
|
23
|
+
throw new PrivacyRefusal("PRIVACY_ASSESSMENT_UNAVAILABLE");
|
|
24
|
+
}
|
|
25
|
+
if (result.data.user) principal = { principal_id: result.data.user.id, email: result.data.user.email ?? null, email_confirmed_at: result.data.user.email_confirmed_at ?? null };
|
|
26
|
+
const read = await client.from("admin_users").select("id, membership_state, role, is_machine_actor").eq("id", principalId).maybeSingle();
|
|
27
|
+
if (read.error) throw new PrivacyRefusal("PRIVACY_ASSESSMENT_UNAVAILABLE");
|
|
28
|
+
membership = read.data ? JSON.parse(JSON.stringify(read.data)) as PrivacyJson : null;
|
|
29
|
+
}
|
|
30
|
+
if (!contact && !principal) return null;
|
|
31
|
+
return { contactId: contact?.id ?? null, principalId, identity: {
|
|
32
|
+
contact: contact ? JSON.parse(JSON.stringify(contact)) as PrivacyJson : null, principal, membership,
|
|
33
|
+
unavailable: ["contact.country", "identity.audit-history", "identity.invitation-history", "identity.erasure-receipts"],
|
|
34
|
+
} };
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
type Role = "admin" | "distributor";
|
|
2
|
+
const roleName = (role: Role) => role === "admin" ? "Admin" : "Dystrybutor";
|
|
3
|
+
const en = {
|
|
4
|
+
unauthorized: "Unauthorized", invalidToken: "Invalid token",
|
|
5
|
+
inviteForbidden: "Only admins may invite users", emailRequired: "Email required",
|
|
6
|
+
invalidRole: "Invalid role", alreadyAdded: "This user is already added",
|
|
7
|
+
addFailed: (detail: string) => `Adding user failed: ${detail}`,
|
|
8
|
+
notificationFailed: (detail: string) => `Role added, but notification failed: ${detail}`,
|
|
9
|
+
roleAddedDisabled: (email: string, role: Role) => `User ${email} already had an account; added role ${role}, but notification was disabled and not sent.`,
|
|
10
|
+
roleAddedSuppressed: (email: string, role: Role) => `User ${email} already had an account; added role ${role}, but notification was suppressed and not sent.`,
|
|
11
|
+
roleAdded: (email: string, role: Role) => `User ${email} already had an account; added role ${role} and sent a notification.`,
|
|
12
|
+
inviteFailed: (detail: string) => `Invitation failed: ${detail}`,
|
|
13
|
+
roleInsertFailed: (detail: string) => `Account created, but adding role failed: ${detail}`,
|
|
14
|
+
invited: (email: string, role: Role) => `Invitation with role ${role} sent to ${email}`,
|
|
15
|
+
removeForbidden: "Only admins may revoke user access", userIdRequired: "User ID required",
|
|
16
|
+
selfRemoveForbidden: "You cannot revoke your own access",
|
|
17
|
+
lastAdmin: "At least one active human admin must remain.",
|
|
18
|
+
selfRevoke: "You cannot revoke your own access.",
|
|
19
|
+
machineRevoke: "Machine actors cannot be revoked through this route.",
|
|
20
|
+
adminNotFound: "Admin user not found.", adminRequired: "Admin role required.",
|
|
21
|
+
revokeFailed: (detail: string) => `Admin access revoke failed: ${detail}`,
|
|
22
|
+
};
|
|
23
|
+
export type IdentityMessages = typeof en;
|
|
24
|
+
export const identityMessages: Readonly<Record<"en" | "pl", IdentityMessages>> = {
|
|
25
|
+
en,
|
|
26
|
+
pl: {
|
|
27
|
+
...en,
|
|
28
|
+
inviteForbidden: "Tylko admini mogą zapraszać użytkowników", emailRequired: "Brak emaila",
|
|
29
|
+
invalidRole: "Nieprawidłowa rola", alreadyAdded: "Ten użytkownik jest już dodany",
|
|
30
|
+
addFailed: (detail) => `Błąd dodawania: ${detail}`,
|
|
31
|
+
notificationFailed: (detail) => `Rola dodana, ale nie udało się wysłać powiadomienia: ${detail}`,
|
|
32
|
+
roleAddedDisabled: (email, role) => `Użytkownik ${email} już miał konto — dodano rolę ${roleName(role)}, ale powiadomienie było wyłączone i nie zostało wysłane.`,
|
|
33
|
+
roleAddedSuppressed: (email, role) => `Użytkownik ${email} już miał konto — dodano rolę ${roleName(role)}, ale wysłanie powiadomienia zostało zablokowane i nie zostało wysłane.`,
|
|
34
|
+
roleAdded: (email, role) => `Użytkownik ${email} już miał konto — dodano rolę ${roleName(role)} i wysłano powiadomienie.`,
|
|
35
|
+
inviteFailed: (detail) => `Błąd zaproszenia: ${detail}`,
|
|
36
|
+
roleInsertFailed: (detail) => `Konto utworzone, ale błąd dodawania roli: ${detail}`,
|
|
37
|
+
invited: (email, role) => `Zaproszenie z rolą ${roleName(role)} wysłane na ${email}`,
|
|
38
|
+
removeForbidden: "Tylko administratorzy mogą odbierać dostęp użytkownikom",
|
|
39
|
+
userIdRequired: "Brak ID użytkownika", selfRemoveForbidden: "Nie możesz odebrać sobie dostępu",
|
|
40
|
+
},
|
|
41
|
+
};
|