@cosmicdrift/kumiko-bundled-features 0.369.0 → 0.370.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/dist/account-security/constants.d.ts +4 -0
- package/dist/account-security/constants.js +5 -0
- package/dist/account-security/feature.d.ts +14 -0
- package/dist/account-security/feature.js +62 -0
- package/dist/account-security/i18n.d.ts +6 -0
- package/dist/account-security/i18n.js +6 -0
- package/dist/account-security/index.d.ts +3 -0
- package/dist/account-security/index.js +3 -0
- package/dist/admin-shell/feature.d.ts +1 -1
- package/dist/admin-shell/index.d.ts +4 -4
- package/dist/admin-shell/overview-panels.d.ts +1 -1
- package/dist/admin-shell/web/index.d.ts +1 -1
- package/dist/agent-tools/agent-manifest.d.ts +1 -1
- package/dist/agent-tools/index.d.ts +8 -8
- package/dist/agent-tools/manifest-deny-qns.d.ts +1 -1
- package/dist/agent-tools/tool-catalog.d.ts +1 -1
- package/dist/agent-tools/tool-dispatch.d.ts +1 -1
- package/dist/audit/handlers/resolve-audit-tenant.d.ts +1 -1
- package/dist/audit/index.d.ts +3 -3
- package/dist/audit/web/index.d.ts +1 -1
- package/dist/auth-email-password/bootstrap.d.ts +1 -1
- package/dist/auth-email-password/feature.d.ts +7 -6
- package/dist/auth-email-password/feature.js +3 -1
- package/dist/auth-email-password/handlers/confirm-token-flow.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/token-request-handler.d.ts +2 -2
- package/dist/auth-email-password/index.d.ts +13 -13
- package/dist/auth-email-password/lockout-store.d.ts +1 -1
- package/dist/auth-email-password/magic-link-mail.d.ts +1 -1
- package/dist/auth-email-password/seeding.d.ts +3 -3
- package/dist/auth-email-password/signed-token.d.ts +1 -1
- package/dist/auth-email-password/signup-token-store.d.ts +1 -1
- package/dist/auth-email-password/testing.d.ts +1 -1
- package/dist/auth-email-password/web/auth-gate.d.ts +1 -1
- package/dist/auth-email-password/web/client-plugin.d.ts +2 -2
- package/dist/auth-email-password/web/index.d.ts +42 -42
- package/dist/auth-email-password/web/session-bootstrap-error.d.ts +1 -1
- package/dist/auth-email-password/web/session.d.ts +1 -1
- package/dist/auth-email-password/web/signup-complete-screen.d.ts +1 -1
- package/dist/auth-foundation/feature.d.ts +2 -6
- package/dist/auth-foundation/feature.js +0 -2
- package/dist/auth-foundation/index.d.ts +3 -3
- package/dist/auth-foundation/index.js +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-mfa/env.d.ts +13 -0
- package/dist/auth-mfa/env.js +24 -0
- package/dist/auth-mfa/errors.d.ts +1 -1
- package/dist/auth-mfa/feature-exports.d.ts +12 -0
- package/dist/auth-mfa/feature-exports.js +72 -0
- package/dist/auth-mfa/feature.d.ts +6 -12
- package/dist/auth-mfa/feature.js +53 -70
- package/dist/auth-mfa/handlers/reencrypt.job.d.ts +1 -1
- package/dist/auth-mfa/index.d.ts +12 -9
- package/dist/auth-mfa/index.js +4 -2
- package/dist/auth-mfa/mfa-challenge-token.d.ts +1 -1
- package/dist/auth-mfa/mfa-preauth-setup-token.d.ts +1 -1
- package/dist/auth-mfa/mfa-status-checker.d.ts +1 -1
- package/dist/auth-mfa/mfa-verify-attempts.d.ts +1 -1
- package/dist/auth-mfa/testing.d.ts +1 -1
- package/dist/auth-mfa/token-secrets.d.ts +7 -0
- package/dist/auth-mfa/token-secrets.js +13 -0
- package/dist/auth-mfa/verify-factor.d.ts +1 -1
- package/dist/auth-mfa/web/index.d.ts +15 -15
- package/dist/auth-mfa/web/mfa-client.d.ts +1 -1
- package/dist/auth-mfa-user-data/index.d.ts +0 -4
- package/dist/auth-mfa-user-data/index.js +0 -2
- package/dist/billing-foundation/checkout-core.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/confirmation-mail.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/consent-text.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/issue-confirmation.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/register-consent.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/register-termination.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +3 -3
- package/dist/billing-foundation/consumer-protection/termination-notify.d.ts +5 -5
- package/dist/billing-foundation/consumer-protection/termination-pages.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +3 -3
- package/dist/billing-foundation/consumer-protection/termination-request.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +2 -2
- package/dist/billing-foundation/feature.d.ts +1 -3
- package/dist/billing-foundation/feature.js +0 -2
- package/dist/billing-foundation/handlers/billing-plans.query.d.ts +1 -1
- package/dist/billing-foundation/handlers/create-checkout-session.write.d.ts +1 -1
- package/dist/billing-foundation/handlers/create-portal-session.write.d.ts +1 -1
- package/dist/billing-foundation/handlers/start-plan-checkout.write.d.ts +1 -1
- package/dist/billing-foundation/handlers/switch-plan.write.d.ts +1 -1
- package/dist/billing-foundation/index.d.ts +16 -16
- package/dist/billing-foundation/index.js +1 -1
- package/dist/billing-foundation/plan-catalog.d.ts +1 -1
- package/dist/billing-foundation/subscription-tier-sync.d.ts +3 -1
- package/dist/billing-foundation/subscription-tier-sync.js +3 -2
- package/dist/billing-foundation/types.d.ts +3 -3
- package/dist/billing-foundation/validate-options.d.ts +1 -1
- package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +1 -1
- package/dist/billing-foundation/web/index.d.ts +6 -6
- package/dist/cap-counter/calendar-cap-usage-reservation.d.ts +4 -4
- package/dist/cap-counter/cap-reservation.d.ts +1 -1
- package/dist/cap-counter/enforce-cap.d.ts +1 -1
- package/dist/cap-counter/feature.d.ts +0 -4
- package/dist/cap-counter/feature.js +0 -2
- package/dist/cap-counter/index.d.ts +13 -13
- package/dist/cap-counter/index.js +1 -1
- package/dist/cap-counter/value-cap-guard.d.ts +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +1 -1
- package/dist/cap-overview/feature.d.ts +1 -1
- package/dist/cap-overview/handlers/caps-usage.query.d.ts +1 -1
- package/dist/cap-overview/handlers/tenant-caps-list.query.d.ts +1 -1
- package/dist/cap-overview/index.d.ts +6 -6
- package/dist/cap-overview/screens.d.ts +1 -1
- package/dist/cap-overview/types.d.ts +1 -1
- package/dist/cap-overview/usage-math.d.ts +1 -1
- package/dist/cap-overview/web/cap-usage-bar.d.ts +1 -1
- package/dist/cap-overview/web/index.d.ts +4 -4
- package/dist/channel-discord/discord-channel.d.ts +1 -1
- package/dist/channel-discord/feature.d.ts +1 -1
- package/dist/channel-discord/index.d.ts +2 -2
- package/dist/channel-email/email-channel.d.ts +2 -2
- package/dist/channel-email/env.d.ts +14 -0
- package/dist/channel-email/env.js +27 -0
- package/dist/channel-email/feature.d.ts +14 -3
- package/dist/channel-email/feature.js +5 -1
- package/dist/channel-email/index.d.ts +6 -5
- package/dist/channel-email/index.js +1 -0
- package/dist/channel-email/pii-guard.d.ts +1 -1
- package/dist/channel-email/smtp-transport.d.ts +1 -1
- package/dist/channel-email/types.d.ts +1 -1
- package/dist/channel-in-app/in-app-channel.d.ts +1 -1
- package/dist/channel-in-app/index.d.ts +4 -4
- package/dist/channel-push/feature.d.ts +1 -1
- package/dist/channel-push/index.d.ts +3 -3
- package/dist/channel-push/push-channel.d.ts +2 -2
- package/dist/channel-slack/feature.d.ts +1 -1
- package/dist/channel-slack/index.d.ts +2 -2
- package/dist/channel-slack/slack-channel.d.ts +1 -1
- package/dist/channel-teams/feature.d.ts +1 -1
- package/dist/channel-teams/index.d.ts +2 -2
- package/dist/channel-teams/teams-channel.d.ts +1 -1
- package/dist/channel-telegram/feature.d.ts +1 -1
- package/dist/channel-telegram/index.d.ts +2 -2
- package/dist/channel-telegram/telegram-channel.d.ts +1 -1
- package/dist/compliance-profiles/feature.d.ts +1 -1
- package/dist/compliance-profiles/index.d.ts +3 -3
- package/dist/compliance-profiles/web/index.d.ts +2 -2
- package/dist/compliance-profiles-ops/index.d.ts +0 -8
- package/dist/compliance-profiles-ops/index.js +0 -2
- package/dist/config/feature.d.ts +1 -1
- package/dist/config/handlers/reencrypt.job.d.ts +1 -1
- package/dist/config/index.d.ts +8 -8
- package/dist/config/web/client-plugin.d.ts +1 -1
- package/dist/config/web/index.d.ts +2 -2
- package/dist/crypto-shredding/env/index.d.ts +21 -0
- package/dist/crypto-shredding/env/index.js +78 -0
- package/dist/crypto-shredding/feature.d.ts +17 -2
- package/dist/crypto-shredding/feature.js +5 -1
- package/dist/crypto-shredding/index.d.ts +4 -3
- package/dist/crypto-shredding/index.js +1 -0
- package/dist/custom-fields/feature.d.ts +0 -17
- package/dist/custom-fields/feature.js +0 -2
- package/dist/custom-fields/index.d.ts +10 -10
- package/dist/custom-fields/index.js +1 -1
- package/dist/custom-fields/lib/define-or-resurrect.d.ts +2 -2
- package/dist/custom-fields/lib/field-access.d.ts +1 -1
- package/dist/custom-fields/lib/field-definition-row.d.ts +1 -1
- package/dist/custom-fields/lib/quota.d.ts +1 -1
- package/dist/custom-fields/web/index.d.ts +3 -3
- package/dist/data-retention/_internal/parse-override.d.ts +1 -1
- package/dist/data-retention/feature.d.ts +7 -7
- package/dist/data-retention/handlers/policy-for.query.d.ts +1 -1
- package/dist/data-retention/index.d.ts +3 -3
- package/dist/data-retention/resolve-for-tenant.d.ts +2 -2
- package/dist/data-retention/resolve-tenant-preset.d.ts +1 -1
- package/dist/data-retention/resolver.d.ts +1 -1
- package/dist/data-retention/run-retention-cleanup.d.ts +2 -2
- package/dist/delivery/attachment-ref.d.ts +1 -1
- package/dist/delivery/attempt-log.d.ts +1 -1
- package/dist/delivery/channel-context.d.ts +2 -2
- package/dist/delivery/chat-webhook-channel.d.ts +2 -2
- package/dist/delivery/constants.d.ts +1 -1
- package/dist/delivery/delivery-service.d.ts +2 -2
- package/dist/delivery/feature.js +2 -0
- package/dist/delivery/handlers/log.query.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-page-chrome.query.d.ts +5 -0
- package/dist/delivery/handlers/unsubscribe-page-chrome.query.js +44 -0
- package/dist/delivery/index.d.ts +20 -20
- package/dist/delivery/notify-factory.d.ts +1 -1
- package/dist/delivery/public-names.d.ts +1 -0
- package/dist/delivery/public-names.js +1 -0
- package/dist/delivery/testing.d.ts +3 -3
- package/dist/delivery/types.d.ts +3 -3
- package/dist/delivery/unsubscribe-link.d.ts +1 -1
- package/dist/delivery/unsubscribe-page-strings.d.ts +4 -0
- package/dist/delivery/unsubscribe-page-strings.js +4 -0
- package/dist/delivery/unsubscribe-page.d.ts +27 -0
- package/dist/delivery/unsubscribe-page.js +192 -0
- package/dist/delivery/unsubscribe.d.ts +11 -3
- package/dist/delivery/unsubscribe.js +146 -64
- package/dist/delivery/web/index.d.ts +2 -2
- package/dist/derivatives-sharp/feature.d.ts +0 -4
- package/dist/derivatives-sharp/feature.js +0 -2
- package/dist/derivatives-sharp/index.d.ts +2 -2
- package/dist/derivatives-sharp/index.js +1 -1
- package/dist/document-ingest-foundation/feature.d.ts +0 -7
- package/dist/document-ingest-foundation/feature.js +0 -2
- package/dist/document-ingest-foundation/index.d.ts +7 -7
- package/dist/document-ingest-foundation/index.js +1 -1
- package/dist/document-ingest-foundation/pages.d.ts +1 -1
- package/dist/document-ingest-foundation/providers.d.ts +1 -1
- package/dist/document-ingest-foundation/write-document-extract.d.ts +1 -1
- package/dist/feature-toggles/compose-tier-resolver.d.ts +1 -1
- package/dist/feature-toggles/feature.d.ts +5 -5
- package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
- package/dist/feature-toggles/index.d.ts +3 -3
- package/dist/feature-toggles/toggle-sync-signal.d.ts +1 -1
- package/dist/feature-toggles/web/index.d.ts +1 -1
- package/dist/file-derivatives/feature.d.ts +0 -2
- package/dist/file-derivatives/feature.js +0 -2
- package/dist/file-derivatives/index.d.ts +4 -4
- package/dist/file-derivatives/index.js +1 -1
- package/dist/file-foundation/feature.d.ts +0 -6
- package/dist/file-foundation/feature.js +0 -2
- package/dist/file-foundation/index.d.ts +2 -2
- package/dist/file-foundation/index.js +1 -1
- package/dist/file-provider-inmemory/feature.d.ts +0 -4
- package/dist/file-provider-inmemory/feature.js +0 -2
- package/dist/file-provider-inmemory/index.d.ts +1 -1
- package/dist/file-provider-inmemory/index.js +1 -1
- package/dist/file-provider-s3/env-feature.d.ts +12 -2
- package/dist/file-provider-s3/env-feature.js +9 -6
- package/dist/file-provider-s3/env-schema.d.ts +38 -0
- package/dist/file-provider-s3/env-schema.js +51 -0
- package/dist/file-provider-s3/feature.d.ts +1 -14
- package/dist/file-provider-s3/feature.js +0 -2
- package/dist/file-provider-s3/index.d.ts +2 -1
- package/dist/file-provider-s3/index.js +2 -1
- package/dist/file-provider-s3/lib/env-helper.d.ts +1 -1
- package/dist/file-provider-s3/lib/index.d.ts +3 -3
- package/dist/files/index.d.ts +1 -1
- package/dist/files-tenant-data/index.d.ts +2 -2
- package/dist/folders/feature.d.ts +0 -4
- package/dist/folders/feature.js +0 -2
- package/dist/folders/index.d.ts +7 -7
- package/dist/folders/index.js +1 -1
- package/dist/folders/web/folder-manager.d.ts +1 -1
- package/dist/folders/web/index.d.ts +5 -5
- package/dist/folders-user-data/index.d.ts +0 -4
- package/dist/folders-user-data/index.js +0 -2
- package/dist/form-draft/db/queries/cleanup.d.ts +1 -1
- package/dist/form-draft/feature.d.ts +0 -4
- package/dist/form-draft/feature.js +0 -2
- package/dist/form-draft/handlers/cleanup.job.d.ts +1 -1
- package/dist/form-draft/handlers/get.query.d.ts +1 -1
- package/dist/form-draft/index.d.ts +10 -10
- package/dist/form-draft/index.js +1 -1
- package/dist/form-draft/lookup.d.ts +1 -1
- package/dist/form-draft/release-file-refs.d.ts +1 -1
- package/dist/form-draft-user-data/index.d.ts +0 -4
- package/dist/form-draft-user-data/index.js +0 -2
- package/dist/foundation-shared/build-info-env.d.ts +7 -0
- package/dist/foundation-shared/build-info-env.js +15 -0
- package/dist/foundation-shared/demo-admin-env.d.ts +12 -0
- package/dist/foundation-shared/demo-admin-env.js +21 -0
- package/dist/foundation-shared/index.d.ts +5 -3
- package/dist/foundation-shared/index.js +2 -0
- package/dist/host-routing/constants.d.ts +8 -0
- package/dist/host-routing/constants.js +19 -0
- package/dist/host-routing/dispatch.d.ts +24 -0
- package/dist/host-routing/dispatch.js +102 -0
- package/dist/host-routing/feature.d.ts +3 -0
- package/dist/host-routing/feature.js +102 -0
- package/dist/host-routing/host.d.ts +14 -0
- package/dist/host-routing/host.js +37 -0
- package/dist/host-routing/index.d.ts +5 -0
- package/dist/host-routing/index.js +4 -0
- package/dist/host-routing/options.d.ts +27 -0
- package/dist/host-routing/options.js +1 -0
- package/dist/host-routing/validate-options.d.ts +2 -0
- package/dist/host-routing/validate-options.js +29 -0
- package/dist/inbound-mail-foundation/connect-routes.d.ts +2 -2
- package/dist/inbound-mail-foundation/feature.d.ts +0 -4
- package/dist/inbound-mail-foundation/feature.js +0 -2
- package/dist/inbound-mail-foundation/handlers/account-state.d.ts +1 -1
- package/dist/inbound-mail-foundation/index.d.ts +12 -12
- package/dist/inbound-mail-foundation/index.js +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.d.ts +1 -1
- package/dist/inbound-mail-foundation/provider-factory.d.ts +1 -1
- package/dist/inbound-mail-foundation/types.d.ts +1 -1
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.d.ts +1 -5
- package/dist/inbound-provider-imap/feature.js +0 -2
- package/dist/inbound-provider-imap/imap-client.d.ts +1 -1
- package/dist/inbound-provider-imap/index.d.ts +3 -3
- package/dist/inbound-provider-imap/index.js +1 -1
- package/dist/inbound-provider-inmemory/feature.d.ts +0 -4
- package/dist/inbound-provider-inmemory/feature.js +0 -2
- package/dist/inbound-provider-inmemory/index.d.ts +1 -1
- package/dist/inbound-provider-inmemory/index.js +1 -1
- package/dist/jobs/handlers/tenant-runs.query.d.ts +1 -1
- package/dist/jobs/index.d.ts +9 -9
- package/dist/jobs/web/index.d.ts +1 -1
- package/dist/ledger/feature.d.ts +0 -4
- package/dist/ledger/feature.js +0 -2
- package/dist/ledger/index.d.ts +10 -10
- package/dist/ledger/index.js +1 -1
- package/dist/ledger/recurring.d.ts +2 -2
- package/dist/ledger/reports.d.ts +2 -2
- package/dist/ledger/web/index.d.ts +3 -3
- package/dist/legal-pages/constants.d.ts +12 -0
- package/dist/legal-pages/constants.js +16 -0
- package/dist/legal-pages/feature.d.ts +6 -3
- package/dist/legal-pages/feature.js +5 -2
- package/dist/legal-pages/index.d.ts +5 -3
- package/dist/legal-pages/index.js +3 -1
- package/dist/legal-pages/layout.d.ts +10 -0
- package/dist/legal-pages/layout.js +32 -0
- package/dist/legal-pages/lib/boot-check.d.ts +1 -1
- package/dist/legal-pages/lib/validate-routes.d.ts +1 -1
- package/dist/legal-pages/markdown.d.ts +2 -2
- package/dist/legal-pages/seed.d.ts +12 -0
- package/dist/legal-pages/seed.js +38 -0
- package/dist/legal-pages/web/index.d.ts +1 -1
- package/dist/mail-foundation/feature.d.ts +0 -7
- package/dist/mail-foundation/feature.js +0 -2
- package/dist/mail-foundation/index.d.ts +1 -1
- package/dist/mail-foundation/index.js +1 -1
- package/dist/mail-transport-inmemory/feature.d.ts +0 -4
- package/dist/mail-transport-inmemory/feature.js +0 -2
- package/dist/mail-transport-inmemory/index.d.ts +1 -1
- package/dist/mail-transport-inmemory/index.js +1 -1
- package/dist/mail-transport-smtp/feature.d.ts +0 -16
- package/dist/mail-transport-smtp/feature.js +0 -2
- package/dist/mail-transport-smtp/index.d.ts +1 -1
- package/dist/mail-transport-smtp/index.js +1 -1
- package/dist/managed-pages/branding.d.ts +1 -1
- package/dist/managed-pages/feature.d.ts +1 -1
- package/dist/managed-pages/handlers/branding.query.d.ts +1 -1
- package/dist/managed-pages/index.d.ts +5 -5
- package/dist/managed-pages/web/index.d.ts +2 -2
- package/dist/metrics/compute.d.ts +2 -2
- package/dist/metrics/default-metrics.d.ts +9 -9
- package/dist/metrics/feature.d.ts +1 -1
- package/dist/metrics/filters.d.ts +1 -1
- package/dist/metrics/index.d.ts +5 -5
- package/dist/metrics/types.d.ts +1 -1
- package/dist/metrics/validate.d.ts +1 -1
- package/dist/metrics/window.d.ts +2 -2
- package/dist/notes-history/feature.d.ts +0 -4
- package/dist/notes-history/feature.js +0 -2
- package/dist/notes-history/handlers/add-note.write.d.ts +1 -1
- package/dist/notes-history/index.d.ts +6 -6
- package/dist/notes-history/index.js +1 -1
- package/dist/notes-history/web/index.d.ts +3 -3
- package/dist/notes-history-user-data/index.d.ts +1 -5
- package/dist/notes-history-user-data/index.js +0 -2
- package/dist/page-render/index.d.ts +7 -7
- package/dist/page-render/layout.d.ts +1 -1
- package/dist/page-render/web.d.ts +5 -5
- package/dist/personal-access-tokens/feature.d.ts +3 -3
- package/dist/personal-access-tokens/handlers/available-scopes.query.d.ts +1 -1
- package/dist/personal-access-tokens/i18n.d.ts +1 -1
- package/dist/personal-access-tokens/index.d.ts +13 -13
- package/dist/personal-access-tokens/resolver.d.ts +1 -1
- package/dist/personal-access-tokens/screens.d.ts +1 -1
- package/dist/presets/dsgvo-self-service.d.ts +3 -1
- package/dist/presets/dsgvo-self-service.js +2 -0
- package/dist/presets/index.d.ts +2 -2
- package/dist/presets/security-baseline.d.ts +2 -0
- package/dist/presets/security-baseline.js +2 -0
- package/dist/rate-limiting/index.d.ts +2 -2
- package/dist/readiness/feature.d.ts +0 -8
- package/dist/readiness/feature.js +0 -2
- package/dist/readiness/index.d.ts +3 -3
- package/dist/readiness/index.js +1 -1
- package/dist/renderer-foundation/api.d.ts +2 -2
- package/dist/renderer-foundation/constants.d.ts +2 -2
- package/dist/renderer-foundation/feature.d.ts +1 -1
- package/dist/renderer-foundation/index.d.ts +5 -5
- package/dist/renderer-foundation/types.d.ts +24 -2
- package/dist/renderer-pdf/feature.d.ts +1 -1
- package/dist/renderer-pdf/index.d.ts +2 -2
- package/dist/renderer-pdf/render-table-pdf.d.ts +1 -1
- package/dist/secrets/constants.d.ts +7 -0
- package/dist/secrets/constants.js +7 -0
- package/dist/secrets/db/queries/read.d.ts +1 -1
- package/dist/secrets/feature.d.ts +4 -3
- package/dist/secrets/feature.js +4 -2
- package/dist/secrets/handlers/delete.write.js +2 -2
- package/dist/secrets/handlers/rotate.job.d.ts +1 -1
- package/dist/secrets/handlers/set.write.js +2 -2
- package/dist/secrets/index.d.ts +7 -7
- package/dist/secrets/index.js +1 -1
- package/dist/secrets/secrets-context.d.ts +1 -1
- package/dist/seo/feature.d.ts +3 -3
- package/dist/seo/index.d.ts +6 -6
- package/dist/sessions/feature.d.ts +1 -1
- package/dist/sessions/index.d.ts +8 -8
- package/dist/sessions/session-callbacks.d.ts +1 -1
- package/dist/sessions/testing.d.ts +1 -1
- package/dist/shared/index.d.ts +31 -31
- package/dist/step-dispatcher/dispatch-payload.d.ts +2 -2
- package/dist/step-dispatcher/index.d.ts +3 -3
- package/dist/subscription-mollie/feature.d.ts +2 -2
- package/dist/subscription-mollie/index.d.ts +3 -3
- package/dist/subscription-mollie/verify-webhook.d.ts +1 -1
- package/dist/subscription-stripe/feature.d.ts +17 -1
- package/dist/subscription-stripe/feature.js +19 -1
- package/dist/subscription-stripe/index.d.ts +2 -2
- package/dist/subscription-stripe/index.js +1 -1
- package/dist/subscription-stripe/plugin-methods.d.ts +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +1 -1
- package/dist/tags/feature.d.ts +0 -4
- package/dist/tags/feature.js +0 -2
- package/dist/tags/handlers/assign-tag.write.d.ts +1 -1
- package/dist/tags/handlers/remove-tag.write.d.ts +1 -1
- package/dist/tags/index.d.ts +11 -11
- package/dist/tags/index.js +1 -1
- package/dist/tags/web/index.d.ts +9 -9
- package/dist/template-resolver/api.d.ts +4 -4
- package/dist/template-resolver/constants.d.ts +1 -1
- package/dist/template-resolver/document-sanitizer.d.ts +1 -1
- package/dist/template-resolver/handlers/bundle-import.d.ts +3 -3
- package/dist/template-resolver/handlers/collection-shared.d.ts +2 -2
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +1 -1
- package/dist/template-resolver/handlers/diff-to-system.query.d.ts +1 -1
- package/dist/template-resolver/handlers/find-by-id.query.d.ts +1 -1
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +1 -1
- package/dist/template-resolver/handlers/layout-source.query.d.ts +3 -3
- package/dist/template-resolver/handlers/override-diff.d.ts +2 -2
- package/dist/template-resolver/handlers/overview.query.d.ts +3 -3
- package/dist/template-resolver/handlers/preview.query.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +1 -1
- package/dist/template-resolver/handlers/send-test.write.d.ts +1 -1
- package/dist/template-resolver/handlers/shared.d.ts +1 -1
- package/dist/template-resolver/handlers/template-gates.d.ts +4 -4
- package/dist/template-resolver/handlers/template-write.d.ts +4 -4
- package/dist/template-resolver/handlers/tenant-overrides.query.d.ts +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +1 -1
- package/dist/template-resolver/handlers/upsert-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +1 -1
- package/dist/template-resolver/handlers/usage.query.d.ts +1 -1
- package/dist/template-resolver/handlers/validate.query.d.ts +3 -3
- package/dist/template-resolver/index.d.ts +25 -25
- package/dist/template-resolver/layout-appearance.d.ts +1 -1
- package/dist/template-resolver/layout-regions.d.ts +2 -2
- package/dist/template-resolver/linked-resources.d.ts +1 -1
- package/dist/template-resolver/preview-display-html.d.ts +1 -1
- package/dist/template-resolver/resource-image.d.ts +1 -1
- package/dist/template-resolver/seeding.d.ts +2 -2
- package/dist/template-resolver/store-template-resource.d.ts +1 -1
- package/dist/template-resolver/template-draft.d.ts +2 -2
- package/dist/template-resolver/template-meta.d.ts +2 -2
- package/dist/template-resolver/template-preview.d.ts +7 -6
- package/dist/template-resolver/template-preview.js +19 -12
- package/dist/template-resolver/template-resources.d.ts +1 -1
- package/dist/template-resolver/template-usage.d.ts +3 -1
- package/dist/template-resolver/template-usage.js +1 -0
- package/dist/template-resolver/template-validation.d.ts +1 -1
- package/dist/template-resolver/testing.d.ts +1 -1
- package/dist/template-resolver/user-content-table.d.ts +1 -1
- package/dist/template-resolver/web/document-editor-extensions.d.ts +1 -1
- package/dist/template-resolver/web/document-editor-extensions.js +6 -2
- package/dist/template-resolver/web/document-editor.d.ts +1 -1
- package/dist/template-resolver/web/document-tiptap-editor.d.ts +1 -1
- package/dist/template-resolver/web/document-tiptap-editor.js +13 -10
- package/dist/template-resolver/web/editor-handle.d.ts +1 -1
- package/dist/template-resolver/web/index.d.ts +7 -7
- package/dist/template-resolver/web/placeholder-line-editor-lazy.d.ts +2 -2
- package/dist/template-resolver/web/placeholder-line-editor.d.ts +1 -1
- package/dist/template-resolver-user-data/index.d.ts +0 -4
- package/dist/template-resolver-user-data/index.js +0 -2
- package/dist/tenant/feature.d.ts +1 -1
- package/dist/tenant/index.d.ts +10 -10
- package/dist/tenant/is-tenant-serving-public-content.d.ts +1 -1
- package/dist/tenant/testing.d.ts +1 -1
- package/dist/tenant/web/index.d.ts +3 -3
- package/dist/tenant-handover/feature.d.ts +1 -1
- package/dist/tenant-handover/index.d.ts +3 -3
- package/dist/tenant-handover/signup-handover-provider.d.ts +1 -1
- package/dist/tenant-lifecycle/feature.d.ts +2 -2
- package/dist/tenant-lifecycle/index.d.ts +3 -3
- package/dist/tenant-lifecycle/run-tenant-destroy.d.ts +1 -1
- package/dist/tenant-lifecycle/stages.d.ts +1 -1
- package/dist/tenant-lifecycle/testing.d.ts +1 -1
- package/dist/tenant-settings/feature.d.ts +1 -3
- package/dist/tenant-settings/feature.js +0 -2
- package/dist/tenant-settings/index.d.ts +4 -4
- package/dist/tenant-settings/index.js +1 -1
- package/dist/tier-engine/entity.d.ts +1 -1
- package/dist/tier-engine/feature.d.ts +2 -4
- package/dist/tier-engine/feature.js +0 -2
- package/dist/tier-engine/handlers/get-tenant-tier.query.d.ts +1 -1
- package/dist/tier-engine/i18n.d.ts +0 -2
- package/dist/tier-engine/i18n.js +4 -4
- package/dist/tier-engine/index.d.ts +8 -8
- package/dist/tier-engine/index.js +1 -1
- package/dist/tier-engine/tier-option-gate.d.ts +1 -1
- package/dist/tier-engine/tier-resolver.d.ts +1 -1
- package/dist/tier-engine/web/client-plugin.js +3 -2
- package/dist/tier-engine/web/index.d.ts +1 -1
- package/dist/user/index.d.ts +8 -8
- package/dist/user/invited-global-roles.d.ts +1 -1
- package/dist/user/principal-status.d.ts +1 -1
- package/dist/user/seeding.d.ts +1 -1
- package/dist/user/testing.d.ts +1 -1
- package/dist/user-data-rights/deletion-token.d.ts +1 -1
- package/dist/user-data-rights/feature.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +3 -3
- package/dist/user-data-rights/index.d.ts +13 -13
- package/dist/user-data-rights/lib/default-mailers.d.ts +4 -4
- package/dist/user-data-rights/web/client-plugin.d.ts +1 -1
- package/dist/user-data-rights/web/index.d.ts +8 -8
- package/dist/user-data-rights-defaults/index.d.ts +11 -11
- package/dist/user-profile/index.d.ts +2 -2
- package/dist/user-profile/web/index.d.ts +2 -2
- package/dist/waitlist/constants.d.ts +9 -0
- package/dist/waitlist/constants.js +11 -0
- package/dist/waitlist/entity.d.ts +38 -6
- package/dist/waitlist/entity.js +4 -2
- package/dist/waitlist/entries-admin.d.ts +4 -0
- package/dist/waitlist/entries-admin.js +42 -0
- package/dist/waitlist/feature.d.ts +1 -1
- package/dist/waitlist/feature.js +16 -1
- package/dist/waitlist/handlers/export-purge.write.d.ts +12 -0
- package/dist/waitlist/handlers/export-purge.write.js +61 -0
- package/dist/waitlist/handlers/invite.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.d.ts +1 -1
- package/dist/waitlist/i18n.js +4 -0
- package/dist/waitlist/import.d.ts +24 -0
- package/dist/waitlist/import.js +51 -0
- package/dist/waitlist/index.d.ts +7 -5
- package/dist/waitlist/index.js +2 -0
- package/dist/waitlist/legacy-migrate.d.ts +27 -0
- package/dist/waitlist/legacy-migrate.js +173 -0
- package/dist/waitlist/lib.d.ts +2 -2
- package/dist/waitlist/link-on-signup.d.ts +3 -0
- package/dist/waitlist/link-on-signup.js +83 -0
- package/dist/waitlist/options.d.ts +11 -3
- package/dist/waitlist/payloads.d.ts +3 -0
- package/dist/waitlist/payloads.js +1 -0
- package/dist/workflow-runner/feature.d.ts +0 -4
- package/dist/workflow-runner/feature.js +0 -2
- package/dist/workflow-runner/index.d.ts +4 -4
- package/dist/workflow-runner/index.js +1 -1
- package/package.json +43 -27
- package/src/account-security/changes.json +8 -0
- package/src/auth-email-password/changes.json +6 -0
- package/src/auth-foundation/changes.json +8 -0
- package/src/auth-mfa/changes.json +6 -0
- package/src/auth-mfa-user-data/changes.json +10 -1
- package/src/billing-foundation/changes.json +8 -0
- package/src/cap-counter/changes.json +8 -0
- package/src/channel-email/changes.json +6 -0
- package/src/compliance-profiles-ops/changes.json +10 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/custom-fields/changes.json +8 -0
- package/src/delivery/changes.json +6 -0
- package/src/derivatives-sharp/changes.json +8 -0
- package/src/document-ingest-foundation/changes.json +8 -0
- package/src/file-derivatives/changes.json +8 -0
- package/src/file-foundation/changes.json +8 -0
- package/src/file-provider-inmemory/changes.json +10 -1
- package/src/file-provider-s3/changes.json +22 -0
- package/src/folders/changes.json +8 -0
- package/src/folders-user-data/changes.json +10 -1
- package/src/form-draft/changes.json +8 -0
- package/src/form-draft-user-data/changes.json +10 -1
- package/src/foundation-shared/changes.json +8 -1
- package/src/host-routing/changes.json +8 -0
- package/src/inbound-mail-foundation/changes.json +8 -0
- package/src/inbound-provider-imap/changes.json +8 -0
- package/src/inbound-provider-inmemory/changes.json +10 -1
- package/src/ledger/changes.json +8 -0
- package/src/legal-pages/changes.json +6 -0
- package/src/mail-foundation/changes.json +10 -1
- package/src/mail-transport-inmemory/changes.json +10 -1
- package/src/mail-transport-smtp/changes.json +8 -0
- package/src/notes-history/changes.json +8 -0
- package/src/notes-history-user-data/changes.json +8 -0
- package/src/presets/changes.json +6 -0
- package/src/readiness/changes.json +10 -1
- package/src/secrets/changes.json +12 -0
- package/src/subscription-stripe/changes.json +6 -0
- package/src/tags/changes.json +8 -0
- package/src/template-resolver/changes.json +6 -0
- package/src/template-resolver-user-data/changes.json +10 -0
- package/src/tenant-settings/changes.json +10 -1
- package/src/tier-engine/changes.json +8 -0
- package/src/waitlist/changes.json +7 -0
- package/src/workflow-runner/changes.json +8 -0
- package/dist/file-provider-s3-env/index.d.ts +0 -8
- package/dist/file-provider-s3-env/index.js +0 -7
- package/dist/files-provider-s3/index.d.ts +0 -5
- package/dist/files-provider-s3/index.js +0 -5
- package/src/file-provider-s3-env/changes.json +0 -1
- package/src/files-provider-s3/changes.json +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
import type { FileAttachmentRef, InlineAttachmentRef, RenderedPdfAttachmentRef } from "../renderer-foundation/index.
|
|
2
|
+
import type { FileAttachmentRef, InlineAttachmentRef, RenderedPdfAttachmentRef } from "../renderer-foundation/index.ts";
|
|
3
3
|
export type { FileAttachmentRef, InlineAttachmentRef, RenderedPdfAttachmentRef };
|
|
4
4
|
export type EmailAttachmentRef = InlineAttachmentRef | FileAttachmentRef | RenderedPdfAttachmentRef;
|
|
5
5
|
export declare const MAX_EMAIL_ATTACHMENTS = 20;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type { Registry } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import { type DeliveryLogEntry } from "./types.
|
|
3
|
+
import { type DeliveryLogEntry } from "./types.ts";
|
|
4
4
|
export declare function appendAttemptEvent(db: DbConnection, registry: Registry, attemptId: string, entry: DeliveryLogEntry): Promise<void>;
|
|
5
5
|
export declare function logAttempt(db: DbConnection, registry: Registry, entry: DeliveryLogEntry): Promise<string>;
|
|
@@ -3,8 +3,8 @@ import { type DbConnection, type TenantDb } from "@cosmicdrift/kumiko-framework/
|
|
|
3
3
|
import type { ConfigAccessor, Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import type { FileContext } from "@cosmicdrift/kumiko-framework/files";
|
|
5
5
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
6
|
-
import { type MailPayload } from "../renderer-foundation/index.
|
|
7
|
-
import type { ChannelContext, RenderedMail } from "./types.
|
|
6
|
+
import { type MailPayload } from "../renderer-foundation/index.ts";
|
|
7
|
+
import type { ChannelContext, RenderedMail } from "./types.ts";
|
|
8
8
|
export declare function createTemplateMailRenderer(db: DbConnection | TenantDb, registry: Registry, tenantId: TenantId, config: ConfigAccessor | undefined): (payload: MailPayload) => Promise<RenderedMail>;
|
|
9
9
|
export declare function createEmailAttachmentReader(db: DbConnection | TenantDb, registry: Registry, tenantId: TenantId, config: ConfigAccessor | undefined, filesForTenant: (tenantId: string) => FileContext | undefined): NonNullable<ChannelContext["readAttachment"]>;
|
|
10
10
|
export declare function buildChannelContext(db: DbConnection, registry: Registry, sseBroker: SseBroker | undefined, tenantId: TenantId, secrets?: SecretsContext, tenantConfig?: ConfigAccessor, filesForTenant?: (tenantId: string) => FileContext | undefined): ChannelContext;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ChatSendResult, type ChatWebhookRequest, type ChatWebhookTarget } from "./chat-webhook-sender.
|
|
2
|
-
import type { ChannelMessage, ChannelResult, DeliveryChannel } from "./types.
|
|
1
|
+
import { type ChatSendResult, type ChatWebhookRequest, type ChatWebhookTarget } from "./chat-webhook-sender.ts";
|
|
2
|
+
import type { ChannelMessage, ChannelResult, DeliveryChannel } from "./types.ts";
|
|
3
3
|
export type ChatWebhookChannelOptions = {
|
|
4
4
|
readonly allowedHosts?: readonly string[];
|
|
5
5
|
readonly requireHttps?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { NotifyPriority } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
export declare const DELIVERY_CHANNEL_EXTENSION: "deliveryChannel";
|
|
3
3
|
export declare const EMAIL_CHANNEL_NAME: "email";
|
|
4
|
-
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_ATTEMPT_EVENT, DELIVERY_CHANNEL_CELL_COMPONENT, DELIVERY_ERROR_CELL_COMPONENT, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_RESUBSCRIBE_PATH, DELIVERY_STATUS_CELL_COMPONENT, DELIVERY_TIME_CELL_COMPONENT, DELIVERY_TYPE_CELL_COMPONENT, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobNames, DeliveryQueries, DeliveryStatus, type DeliveryStatusValue, } from "./public-names.
|
|
4
|
+
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_ATTEMPT_EVENT, DELIVERY_CHANNEL_CELL_COMPONENT, DELIVERY_ERROR_CELL_COMPONENT, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_RESUBSCRIBE_PATH, DELIVERY_STATUS_CELL_COMPONENT, DELIVERY_TIME_CELL_COMPONENT, DELIVERY_TYPE_CELL_COMPONENT, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobNames, DeliveryQueries, DeliveryStatus, type DeliveryStatusValue, } from "./public-names.ts";
|
|
5
5
|
export declare function deliveryIdempotencyRedisKey(tenantId: string, key: string): string;
|
|
6
6
|
export declare const deliveryPriorityRank: Record<NotifyPriority, number>;
|
|
7
7
|
export declare const DeliveryJobs: {
|
|
@@ -5,8 +5,8 @@ import type { FileContext } from "@cosmicdrift/kumiko-framework/files";
|
|
|
5
5
|
import { type Logger } from "@cosmicdrift/kumiko-framework/logging";
|
|
6
6
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
7
7
|
import type { Redis } from "ioredis";
|
|
8
|
-
import { type DeliveryChannel, type DeliveryService } from "./types.
|
|
9
|
-
import { type UnsubscribeLinkConfig } from "./unsubscribe-link.
|
|
8
|
+
import { type DeliveryChannel, type DeliveryService } from "./types.ts";
|
|
9
|
+
import { type UnsubscribeLinkConfig } from "./unsubscribe-link.ts";
|
|
10
10
|
export declare function redactedMessageOf(err: unknown): string;
|
|
11
11
|
export type RateLimitConfig = {
|
|
12
12
|
readonly redis: Redis;
|
package/dist/delivery/feature.js
CHANGED
|
@@ -10,6 +10,7 @@ import { resubscribeAddressWrite } from "./handlers/resubscribe-address.write.js
|
|
|
10
10
|
import { resubscribeUserWrite } from "./handlers/resubscribe-user.write.js";
|
|
11
11
|
import { setPreferenceWrite } from "./handlers/set-preference.write.js";
|
|
12
12
|
import { unsubscribeAddressWrite } from "./handlers/unsubscribe-address.write.js";
|
|
13
|
+
import { unsubscribePageChromeQuery } from "./handlers/unsubscribe-page-chrome.query.js";
|
|
13
14
|
import { unsubscribeUserWrite } from "./handlers/unsubscribe-user.write.js";
|
|
14
15
|
import { DELIVERY_I18N } from "./i18n.js";
|
|
15
16
|
import { deliveryRenderJob, deliverySendJob } from "./jobs.js";
|
|
@@ -156,6 +157,7 @@ export function createDeliveryFeature(options) {
|
|
|
156
157
|
const queries = {
|
|
157
158
|
log: r.queryHandler({ ...logQuery, access: { roles: resolvedAccess } }),
|
|
158
159
|
preferences: r.queryHandler(preferencesQuery),
|
|
160
|
+
unsubscribePageChrome: r.queryHandler(unsubscribePageChromeQuery),
|
|
159
161
|
};
|
|
160
162
|
r.screen({
|
|
161
163
|
id: DELIVERY_LOG_SCREEN_ID,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DeliveryErrorCode, type NotifyPriority } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import type { DeliveryStatusValue } from "../constants.
|
|
3
|
+
import type { DeliveryStatusValue } from "../constants.ts";
|
|
4
4
|
export declare const logQuery: import("@cosmicdrift/kumiko-framework/engine").PagedQueryHandlerDefinition<"log", z.ZodObject<{
|
|
5
5
|
cursor: z.ZodOptional<z.ZodString>;
|
|
6
6
|
limit: z.ZodDefault<z.ZodNumber>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { type MailChrome } from "../../renderer-foundation/index.ts";
|
|
3
|
+
export declare const unsubscribePageChromeQuery: import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"unsubscribePageChrome", z.ZodObject<{
|
|
4
|
+
locale: z.ZodString;
|
|
5
|
+
}, z.core.$strip>, MailChrome | null, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
3
|
+
import * as z from "zod";
|
|
4
|
+
import { collectRendererPlugins, createRendererFoundationApi, RendererError, } from "../../renderer-foundation/index.js";
|
|
5
|
+
function mailChromePlugin(plugins, tenantId) {
|
|
6
|
+
try {
|
|
7
|
+
const plugin = createRendererFoundationApi(plugins).createRendererForTenant({
|
|
8
|
+
tenantId,
|
|
9
|
+
kind: "mail",
|
|
10
|
+
});
|
|
11
|
+
return plugin.readMailChrome === undefined ? null : plugin;
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
if (e instanceof RendererError && e.code === "no_plugin_for_kind")
|
|
15
|
+
return null;
|
|
16
|
+
throw e;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export const unsubscribePageChromeQuery = defineQueryHandler({
|
|
20
|
+
name: "unsubscribePageChrome",
|
|
21
|
+
schema: z.object({ locale: z.string().min(2).max(35) }),
|
|
22
|
+
access: { roles: access.systemAdmin },
|
|
23
|
+
// Only reachable via createUnsubscribeRoutes' dispatchSystemQuery once verify()
|
|
24
|
+
// proved the token signature.
|
|
25
|
+
agent: { expose: false },
|
|
26
|
+
description: "Returns the tenant's mail brand row and footer resolved for one locale, or null without a mail renderer; dispatched by the signed unsubscribe route to dress its pages like the mail, not meant for UI callers.",
|
|
27
|
+
handler: async (query, ctx) => {
|
|
28
|
+
const { tenantId } = query.user;
|
|
29
|
+
if (!ctx.systemDb) {
|
|
30
|
+
throw new InternalError({
|
|
31
|
+
message: "unsubscribePageChrome: ctx.systemDb missing on a system-scoped handler",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const plugin = mailChromePlugin(collectRendererPlugins(ctx.registry), tenantId);
|
|
35
|
+
if (plugin?.readMailChrome === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
return plugin.readMailChrome({ locale: query.payload.locale }, {
|
|
38
|
+
db: ctx.systemDb.assertTenantMatch(tenantId),
|
|
39
|
+
registry: ctx.registry,
|
|
40
|
+
tenantId,
|
|
41
|
+
...(ctx.config !== undefined && { config: ctx.config }),
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
});
|
package/dist/delivery/index.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export { sanitizePdfAttachmentFileName } from "../shared/index.
|
|
2
|
-
export { hashUnsubscribeAddress } from "./address-opt-out.
|
|
3
|
-
export { DELIVERY_ENVELOPE_DATA_KEYS, type EmailAttachmentRef, emailAttachmentRefSchema, type FileAttachmentRef, fileAttachmentRefSchema, type InlineAttachmentRef, inlineAttachmentRefSchema, MAX_EMAIL_ATTACHMENTS, MAX_RENDERED_PDF_VARIABLES_BYTES, type RenderedPdfAttachmentRef, renderedPdfAttachmentRefSchema, toAttachmentRef, withoutDeliveryEnvelopeKeys, } from "./attachment-ref.
|
|
4
|
-
export { type AttemptLogRetentionOptions, DEFAULT_ATTEMPT_LOG_RETENTION_DAYS, runAttemptLogRetention, } from "./attempt-log-retention.
|
|
5
|
-
export { buildChannelContext, createEmailAttachmentReader, createTemplateMailRenderer, } from "./channel-context.
|
|
6
|
-
export { type ChatWebhookChannelOptions, chatMessageText, createChatWebhookChannel, resolveChatWebhookTarget, toChannelResult, } from "./chat-webhook-channel.
|
|
7
|
-
export { type ChatSendFailureCode, type ChatSendResult, type ChatWebhookRequest, type ChatWebhookResponse, type ChatWebhookTarget, chatConnectionNameSchema, chatWebhookUrlSchema, checkChatWebhookTarget, DEFAULT_CHAT_TIMEOUT_MS, postChatWebhook, truncateChars, } from "./chat-webhook-sender.
|
|
8
|
-
export type { DeliveryStatusValue } from "./constants.
|
|
9
|
-
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_CHANNEL_EXTENSION, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobs, DeliveryQueries, DeliveryStatus, EMAIL_CHANNEL_NAME, } from "./constants.
|
|
10
|
-
export { collectChannels, createDeliveryService, type DeliveryServiceOptions, type KillSwitchResolver, type RateLimitConfig, } from "./delivery-service.
|
|
11
|
-
export { createDeliveryFeature, type DeliveryFeatureOptions } from "./feature.
|
|
12
|
-
export { type UnsubscribeAddressPayload, unsubscribeAddressPayloadSchema, } from "./handlers/unsubscribe-address.write.
|
|
13
|
-
export { currentNotificationType } from "./notification-type-aliases.
|
|
14
|
-
export { createDeliveryNotifyFactory } from "./notify-factory.
|
|
15
|
-
export { deliveryAttemptsTable, notificationAddressOptOutEntity, notificationAddressOptOutsTable, notificationPreferenceEntity, notificationPreferencesTable, } from "./tables.
|
|
16
|
-
export { type CreateDeliveryTestContextOptions, createDeliveryTestContext } from "./testing.
|
|
17
|
-
export { type AttachmentOrigin, type ChannelContext, type ChannelMessage, type ChannelResult, type DeliveryChannel, type DeliveryChannelMode, type DeliveryChannelPlugin, type DeliveryLogEntry, type DeliveryService, isDeliveryChannelPlugin, type RenderedMessage, } from "./types.
|
|
18
|
-
export { type AddressUnsubscribeTokenPayload, createUnsubscribeRoutes, DELIVERY_UNSUBSCRIBE_ONE_CLICK_HEADER_VALUE, renderUnsubscribeResultPage, signAddressUnsubscribeToken, signUnsubscribeToken, type UnsubscribeResultPage, type UnsubscribeRouteOptions, type UnsubscribeTokenPayload, } from "./unsubscribe.
|
|
19
|
-
export type { UnsubscribeLinkConfig } from "./unsubscribe-link.
|
|
20
|
-
export { UNSUBSCRIBE_PAGE_EN } from "./unsubscribe-page-strings.
|
|
1
|
+
export { sanitizePdfAttachmentFileName } from "../shared/index.ts";
|
|
2
|
+
export { hashUnsubscribeAddress } from "./address-opt-out.ts";
|
|
3
|
+
export { DELIVERY_ENVELOPE_DATA_KEYS, type EmailAttachmentRef, emailAttachmentRefSchema, type FileAttachmentRef, fileAttachmentRefSchema, type InlineAttachmentRef, inlineAttachmentRefSchema, MAX_EMAIL_ATTACHMENTS, MAX_RENDERED_PDF_VARIABLES_BYTES, type RenderedPdfAttachmentRef, renderedPdfAttachmentRefSchema, toAttachmentRef, withoutDeliveryEnvelopeKeys, } from "./attachment-ref.ts";
|
|
4
|
+
export { type AttemptLogRetentionOptions, DEFAULT_ATTEMPT_LOG_RETENTION_DAYS, runAttemptLogRetention, } from "./attempt-log-retention.ts";
|
|
5
|
+
export { buildChannelContext, createEmailAttachmentReader, createTemplateMailRenderer, } from "./channel-context.ts";
|
|
6
|
+
export { type ChatWebhookChannelOptions, chatMessageText, createChatWebhookChannel, resolveChatWebhookTarget, toChannelResult, } from "./chat-webhook-channel.ts";
|
|
7
|
+
export { type ChatSendFailureCode, type ChatSendResult, type ChatWebhookRequest, type ChatWebhookResponse, type ChatWebhookTarget, chatConnectionNameSchema, chatWebhookUrlSchema, checkChatWebhookTarget, DEFAULT_CHAT_TIMEOUT_MS, postChatWebhook, truncateChars, } from "./chat-webhook-sender.ts";
|
|
8
|
+
export type { DeliveryStatusValue } from "./constants.ts";
|
|
9
|
+
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_CHANNEL_EXTENSION, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobs, DeliveryQueries, DeliveryStatus, EMAIL_CHANNEL_NAME, } from "./constants.ts";
|
|
10
|
+
export { collectChannels, createDeliveryService, type DeliveryServiceOptions, type KillSwitchResolver, type RateLimitConfig, } from "./delivery-service.ts";
|
|
11
|
+
export { createDeliveryFeature, type DeliveryFeatureOptions } from "./feature.ts";
|
|
12
|
+
export { type UnsubscribeAddressPayload, unsubscribeAddressPayloadSchema, } from "./handlers/unsubscribe-address.write.ts";
|
|
13
|
+
export { currentNotificationType } from "./notification-type-aliases.ts";
|
|
14
|
+
export { createDeliveryNotifyFactory } from "./notify-factory.ts";
|
|
15
|
+
export { deliveryAttemptsTable, notificationAddressOptOutEntity, notificationAddressOptOutsTable, notificationPreferenceEntity, notificationPreferencesTable, } from "./tables.ts";
|
|
16
|
+
export { type CreateDeliveryTestContextOptions, createDeliveryTestContext } from "./testing.ts";
|
|
17
|
+
export { type AttachmentOrigin, type ChannelContext, type ChannelMessage, type ChannelResult, type DeliveryChannel, type DeliveryChannelMode, type DeliveryChannelPlugin, type DeliveryLogEntry, type DeliveryService, isDeliveryChannelPlugin, type RenderedMessage, } from "./types.ts";
|
|
18
|
+
export { type AddressUnsubscribeTokenPayload, createUnsubscribeRoutes, DELIVERY_UNSUBSCRIBE_ONE_CLICK_HEADER_VALUE, renderUnsubscribeResultPage, signAddressUnsubscribeToken, signUnsubscribeToken, type UnsubscribeResultPage, type UnsubscribeRouteOptions, type UnsubscribeTokenPayload, } from "./unsubscribe.ts";
|
|
19
|
+
export type { UnsubscribeLinkConfig } from "./unsubscribe-link.ts";
|
|
20
|
+
export { UNSUBSCRIBE_PAGE_EN } from "./unsubscribe-page-strings.ts";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NotifyFactory } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import type { DeliveryService } from "./types.
|
|
2
|
+
import type { DeliveryService } from "./types.ts";
|
|
3
3
|
export declare function createDeliveryNotifyFactory(deliveryService: Pick<DeliveryService, "notify">, options?: {
|
|
4
4
|
readonly deliverQueuedInline?: boolean;
|
|
5
5
|
}): NotifyFactory;
|
|
@@ -11,6 +11,7 @@ export declare const DELIVERY_RESUBSCRIBE_PATH: "/api/delivery/resubscribe";
|
|
|
11
11
|
export declare const DeliveryQueries: {
|
|
12
12
|
readonly log: "delivery:query:log";
|
|
13
13
|
readonly preferences: "delivery:query:preferences";
|
|
14
|
+
readonly unsubscribePageChrome: "delivery:query:unsubscribe-page-chrome";
|
|
14
15
|
};
|
|
15
16
|
export declare const DELIVERY_LOG_SCREEN_ID: "delivery-log";
|
|
16
17
|
export declare const DELIVERY_STATUS_CELL_COMPONENT: "DeliveryStatusCell";
|
|
@@ -20,6 +20,7 @@ export const DELIVERY_RESUBSCRIBE_PATH = "/api/delivery/resubscribe";
|
|
|
20
20
|
export const DeliveryQueries = {
|
|
21
21
|
log: "delivery:query:log",
|
|
22
22
|
preferences: "delivery:query:preferences",
|
|
23
|
+
unsubscribePageChrome: "delivery:query:unsubscribe-page-chrome",
|
|
23
24
|
};
|
|
24
25
|
export const DELIVERY_LOG_SCREEN_ID = "delivery-log";
|
|
25
26
|
// Client column-renderer registered for the delivery-log screen's status
|
|
@@ -6,9 +6,9 @@ import type { JobRunner } from "@cosmicdrift/kumiko-framework/jobs";
|
|
|
6
6
|
import type { Logger } from "@cosmicdrift/kumiko-framework/logging";
|
|
7
7
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
8
8
|
import type { Redis } from "ioredis";
|
|
9
|
-
import type { KillSwitchResolver, RateLimitConfig } from "./delivery-service.
|
|
10
|
-
import type { DeliveryService } from "./types.
|
|
11
|
-
import type { UnsubscribeLinkConfig } from "./unsubscribe-link.
|
|
9
|
+
import type { KillSwitchResolver, RateLimitConfig } from "./delivery-service.ts";
|
|
10
|
+
import type { DeliveryService } from "./types.ts";
|
|
11
|
+
import type { UnsubscribeLinkConfig } from "./unsubscribe-link.ts";
|
|
12
12
|
export type CreateDeliveryTestContextOptions = {
|
|
13
13
|
readonly tenantUserIdsQuery?: string;
|
|
14
14
|
readonly rateLimit?: RateLimitConfig;
|
package/dist/delivery/types.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ import type { DbConnection, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
|
3
3
|
import type { ConfigAccessor, DeliveryErrorCode, NotifyDeliveryStatus, NotifyDispatched, NotifyJobDispatcher, NotifyOptions, NotifyPriority, Registry, SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import type { FileProviderResolver } from "@cosmicdrift/kumiko-framework/files";
|
|
5
5
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
6
|
-
import type { MailPayload, RenderedTemplateRef } from "../renderer-foundation/index.
|
|
7
|
-
import type { EmailAttachmentRef } from "./attachment-ref.
|
|
8
|
-
import { DELIVERY_CHANNEL_EXTENSION } from "./constants.
|
|
6
|
+
import type { MailPayload, RenderedTemplateRef } from "../renderer-foundation/index.ts";
|
|
7
|
+
import type { EmailAttachmentRef } from "./attachment-ref.ts";
|
|
8
|
+
import { DELIVERY_CHANNEL_EXTENSION } from "./constants.ts";
|
|
9
9
|
export type RenderedMail = {
|
|
10
10
|
readonly subject: string;
|
|
11
11
|
readonly html: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import type { ChannelContext } from "./types.
|
|
2
|
+
import type { ChannelContext } from "./types.ts";
|
|
3
3
|
/** Secret shared with `createUnsubscribeRoutes` plus the public origin the links point at. */
|
|
4
4
|
export type UnsubscribeLinkConfig = {
|
|
5
5
|
readonly secret: string;
|
|
@@ -5,7 +5,11 @@ export declare const UNSUBSCRIBE_PAGE_EN: {
|
|
|
5
5
|
readonly "mail.unsubscribe.doneTitle": "Unsubscribed";
|
|
6
6
|
readonly "mail.unsubscribe.doneMessage": "You have been unsubscribed.";
|
|
7
7
|
readonly "mail.unsubscribe.undoButton": "Undo";
|
|
8
|
+
readonly "mail.unsubscribe.undoHint": "Unsubscribed by mistake? You can undo it within the next hour.";
|
|
8
9
|
readonly "mail.unsubscribe.resubscribedTitle": "Subscribed again";
|
|
9
10
|
readonly "mail.unsubscribe.resubscribedMessage": "You have been subscribed again.";
|
|
10
11
|
readonly "mail.unsubscribe.failed": "That did not work. Please try again later.";
|
|
12
|
+
readonly "mail.unsubscribe.failedTitle": "Something went wrong";
|
|
13
|
+
readonly "mail.unsubscribe.invalidTitle": "Link no longer valid";
|
|
14
|
+
readonly "mail.unsubscribe.invalidMessage": "This link is invalid or has expired. Please use the unsubscribe link in a more recent email.";
|
|
11
15
|
};
|
|
@@ -8,8 +8,12 @@ export const UNSUBSCRIBE_PAGE_EN = {
|
|
|
8
8
|
"mail.unsubscribe.doneTitle": "Unsubscribed",
|
|
9
9
|
"mail.unsubscribe.doneMessage": "You have been unsubscribed.",
|
|
10
10
|
"mail.unsubscribe.undoButton": "Undo",
|
|
11
|
+
"mail.unsubscribe.undoHint": "Unsubscribed by mistake? You can undo it within the next hour.",
|
|
11
12
|
"mail.unsubscribe.resubscribedTitle": "Subscribed again",
|
|
12
13
|
"mail.unsubscribe.resubscribedMessage": "You have been subscribed again.",
|
|
13
14
|
"mail.unsubscribe.failed": "That did not work. Please try again later.",
|
|
15
|
+
"mail.unsubscribe.failedTitle": "Something went wrong",
|
|
16
|
+
"mail.unsubscribe.invalidTitle": "Link no longer valid",
|
|
17
|
+
"mail.unsubscribe.invalidMessage": "This link is invalid or has expired. Please use the unsubscribe link in a more recent email.",
|
|
14
18
|
};
|
|
15
19
|
registerMailTranslations("en", UNSUBSCRIBE_PAGE_EN);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MailChrome } from "../renderer-foundation/index.ts";
|
|
2
|
+
import "./unsubscribe-page-strings.ts";
|
|
3
|
+
export type UnsubscribePageState = {
|
|
4
|
+
readonly kind: "confirm";
|
|
5
|
+
readonly token: string;
|
|
6
|
+
} | {
|
|
7
|
+
readonly kind: "unsubscribed";
|
|
8
|
+
readonly resubscribeToken?: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "resubscribed";
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: "failed";
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: "invalid";
|
|
15
|
+
};
|
|
16
|
+
export type UnsubscribePageInput = {
|
|
17
|
+
readonly state: UnsubscribePageState;
|
|
18
|
+
/** A locale with registered mail translations (see resolveMailLocale). */
|
|
19
|
+
readonly locale: string;
|
|
20
|
+
/** The tenant's mail look; without it the page shows the plain card. */
|
|
21
|
+
readonly chrome?: MailChrome | null | undefined;
|
|
22
|
+
};
|
|
23
|
+
export type RenderedUnsubscribePage = {
|
|
24
|
+
readonly html: string;
|
|
25
|
+
readonly contentSecurityPolicy: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function renderUnsubscribePage(input: UnsubscribePageInput): RenderedUnsubscribePage;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mailT } from "@cosmicdrift/kumiko-framework/i18n";
|
|
3
|
+
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
4
|
+
import { DELIVERY_RESUBSCRIBE_PATH, DELIVERY_UNSUBSCRIBE_PATH } from "./public-names.js";
|
|
5
|
+
import "./unsubscribe-page-strings.js";
|
|
6
|
+
// Same values as the in-code mail layout of renderer-mail-html, so the page reads as the mail's sequel.
|
|
7
|
+
const DEFAULT_ACCENT_COLOR = "#1f5468";
|
|
8
|
+
const HEX_COLOR = /^#[0-9a-fA-F]{6}$/;
|
|
9
|
+
const FONT_URL_PREFIX = "/assets/kumiko/fonts/ibm-plex-sans-latin-";
|
|
10
|
+
function accentOf(chrome) {
|
|
11
|
+
const accent = chrome?.accentColor;
|
|
12
|
+
return accent !== undefined && HEX_COLOR.test(accent) ? accent : DEFAULT_ACCENT_COLOR;
|
|
13
|
+
}
|
|
14
|
+
function httpsOrigin(url) {
|
|
15
|
+
if (url === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
try {
|
|
18
|
+
const parsed = new URL(url);
|
|
19
|
+
return parsed.protocol === "https:" ? parsed.origin : undefined;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function webHost(url) {
|
|
26
|
+
try {
|
|
27
|
+
const parsed = new URL(url);
|
|
28
|
+
return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.host : undefined;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const SAFE_LINK_URL = /^(https?:|mailto:)/i;
|
|
35
|
+
function linkHtml(link) {
|
|
36
|
+
const url = link.url.trim();
|
|
37
|
+
if (!SAFE_LINK_URL.test(url) || link.label.trim() === "")
|
|
38
|
+
return "";
|
|
39
|
+
return `<a href="${escapeHtmlAttr(url)}">${escapeHtml(link.label)}</a>`;
|
|
40
|
+
}
|
|
41
|
+
// The style block is static apart from the validated hex accent and the markup carries
|
|
42
|
+
// no style attributes, so the CSP admits exactly this block by its hash.
|
|
43
|
+
function pageStyle(accent) {
|
|
44
|
+
return `@font-face{font-family:"IBM Plex Sans";font-style:normal;font-weight:400;font-display:swap;src:url("${FONT_URL_PREFIX}400.woff2") format("woff2")}
|
|
45
|
+
@font-face{font-family:"IBM Plex Sans";font-style:normal;font-weight:600;font-display:swap;src:url("${FONT_URL_PREFIX}600.woff2") format("woff2")}
|
|
46
|
+
:root{--accent:${accent}}
|
|
47
|
+
*{box-sizing:border-box}
|
|
48
|
+
html,body{margin:0;padding:0}
|
|
49
|
+
body{background:#ecedea;color:#2a2f3a;font-family:"IBM Plex Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.65;-webkit-font-smoothing:antialiased}
|
|
50
|
+
.page{max-width:560px;margin:0 auto;padding:48px 16px}
|
|
51
|
+
.card{background:#fff;border:1px solid #dcdfda;border-radius:14px;overflow:hidden}
|
|
52
|
+
.accent{height:4px;background:var(--accent)}
|
|
53
|
+
.brand{display:flex;align-items:center;gap:10px;padding:32px 40px 0}
|
|
54
|
+
.brand img{height:28px;width:auto;max-width:140px;display:block}
|
|
55
|
+
.tile{width:28px;height:28px;line-height:28px;border-radius:8px;background:var(--accent);color:#fff;font-weight:600;font-size:14px;text-align:center;flex:none}
|
|
56
|
+
.name{font-size:15px;font-weight:600;color:#0b0d12}
|
|
57
|
+
.suffix{font-size:13px;color:#5a6170}
|
|
58
|
+
.content{padding:28px 40px 36px}
|
|
59
|
+
h1{margin:0 0 8px;font-size:22px;line-height:1.3;font-weight:600;color:#0b0d12}
|
|
60
|
+
p{margin:0}
|
|
61
|
+
form{margin:24px 0 0}
|
|
62
|
+
.button{display:inline-block;font:inherit;font-weight:600;font-size:15px;line-height:1.4;padding:10px 20px;border-radius:6px;border:1px solid var(--accent);background:var(--accent);color:#fff;cursor:pointer}
|
|
63
|
+
.button.secondary{background:#fff;color:var(--accent)}
|
|
64
|
+
.button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
65
|
+
.hint{margin-top:24px;font-size:14px;color:#5a6170}
|
|
66
|
+
.hint+form{margin-top:12px}
|
|
67
|
+
.band{background:#fbfbfa;border-top:1px solid #ecedea;padding:16px 40px;font-size:13px;color:#5a6170}
|
|
68
|
+
.band a{color:#4a515e}
|
|
69
|
+
.footer{padding:20px 24px 0;text-align:center;font-size:12px;color:#5a6170}
|
|
70
|
+
.footer a{color:#5a6170}
|
|
71
|
+
@media (max-width:480px){.page{padding:24px 12px}.brand{padding:24px 20px 0}.content{padding:20px 20px 28px}.band{padding:14px 20px}h1{font-size:20px}.button{width:100%}}`;
|
|
72
|
+
}
|
|
73
|
+
function brandRowHtml(chrome) {
|
|
74
|
+
const name = chrome.tenantName.trim();
|
|
75
|
+
const initial = Array.from(name)[0]?.toLocaleUpperCase() ?? "";
|
|
76
|
+
const mark = httpsOrigin(chrome.logoUrl) !== undefined && chrome.logoUrl !== undefined
|
|
77
|
+
? `<img src="${escapeHtmlAttr(chrome.logoUrl)}" alt="">`
|
|
78
|
+
: initial === ""
|
|
79
|
+
? ""
|
|
80
|
+
: `<span class="tile" aria-hidden="true">${escapeHtml(initial)}</span>`;
|
|
81
|
+
const suffix = chrome.brandSuffix.trim();
|
|
82
|
+
if (mark === "" && name === "")
|
|
83
|
+
return "";
|
|
84
|
+
return `<div class="brand">${mark}${name === "" ? "" : `<span class="name">${escapeHtml(name)}</span>`}${suffix === "" ? "" : `<span class="suffix">${escapeHtml(suffix)}</span>`}</div>`;
|
|
85
|
+
}
|
|
86
|
+
function bandHtml(chrome) {
|
|
87
|
+
const host = chrome.siteUrl === undefined ? undefined : webHost(chrome.siteUrl);
|
|
88
|
+
if (host === undefined || chrome.siteUrl === undefined)
|
|
89
|
+
return "";
|
|
90
|
+
return `<div class="band"><a href="${escapeHtmlAttr(chrome.siteUrl)}">${escapeHtml(host)}</a></div>`;
|
|
91
|
+
}
|
|
92
|
+
function footerHtml(chrome) {
|
|
93
|
+
const text = chrome.footerText?.trim() ?? "";
|
|
94
|
+
const links = [chrome.imprint, chrome.privacy]
|
|
95
|
+
.map((link) => (link === undefined ? "" : linkHtml(link)))
|
|
96
|
+
.filter((html) => html !== "");
|
|
97
|
+
const lineHtmls = [
|
|
98
|
+
...(text === "" ? [] : [escapeHtml(text)]),
|
|
99
|
+
...(links.length === 0 ? [] : [links.join(" · ")]),
|
|
100
|
+
];
|
|
101
|
+
const linesHtml = lineHtmls.join("<br>");
|
|
102
|
+
return linesHtml === "" ? "" : `<footer class="footer">${linesHtml}</footer>`;
|
|
103
|
+
}
|
|
104
|
+
function tokenForm(action, token, label, variant) {
|
|
105
|
+
return `<form method="post" action="${escapeHtmlAttr(action)}">
|
|
106
|
+
<input type="hidden" name="token" value="${escapeHtmlAttr(token)}">
|
|
107
|
+
<button type="submit" class="${escapeHtmlAttr(variant)}">${escapeHtml(label)}</button>
|
|
108
|
+
</form>`;
|
|
109
|
+
}
|
|
110
|
+
function pageText(state, lang) {
|
|
111
|
+
const paragraph = (key) => `<p>${escapeHtml(mailT(lang, key))}</p>`;
|
|
112
|
+
switch (state.kind) {
|
|
113
|
+
case "confirm":
|
|
114
|
+
return {
|
|
115
|
+
title: mailT(lang, "mail.unsubscribe.confirmTitle"),
|
|
116
|
+
bodyHtml: `${paragraph("mail.unsubscribe.confirmQuestion")}
|
|
117
|
+
${tokenForm(DELIVERY_UNSUBSCRIBE_PATH, state.token, mailT(lang, "mail.unsubscribe.confirmButton"), "button")}`,
|
|
118
|
+
};
|
|
119
|
+
case "unsubscribed":
|
|
120
|
+
return {
|
|
121
|
+
title: mailT(lang, "mail.unsubscribe.doneTitle"),
|
|
122
|
+
bodyHtml: state.resubscribeToken === undefined
|
|
123
|
+
? paragraph("mail.unsubscribe.doneMessage")
|
|
124
|
+
: `${paragraph("mail.unsubscribe.doneMessage")}
|
|
125
|
+
<p class="hint">${escapeHtml(mailT(lang, "mail.unsubscribe.undoHint"))}</p>
|
|
126
|
+
${tokenForm(DELIVERY_RESUBSCRIBE_PATH, state.resubscribeToken, mailT(lang, "mail.unsubscribe.undoButton"), "button secondary")}`,
|
|
127
|
+
};
|
|
128
|
+
case "resubscribed":
|
|
129
|
+
return {
|
|
130
|
+
title: mailT(lang, "mail.unsubscribe.resubscribedTitle"),
|
|
131
|
+
bodyHtml: paragraph("mail.unsubscribe.resubscribedMessage"),
|
|
132
|
+
};
|
|
133
|
+
case "failed":
|
|
134
|
+
return {
|
|
135
|
+
title: mailT(lang, "mail.unsubscribe.failedTitle"),
|
|
136
|
+
bodyHtml: paragraph("mail.unsubscribe.failed"),
|
|
137
|
+
};
|
|
138
|
+
case "invalid":
|
|
139
|
+
return {
|
|
140
|
+
title: mailT(lang, "mail.unsubscribe.invalidTitle"),
|
|
141
|
+
bodyHtml: paragraph("mail.unsubscribe.invalidMessage"),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// The page loads nothing but its own style block, the same-origin font and, with
|
|
146
|
+
// branding, the tenant's https logo. Forms only post back to the same origin.
|
|
147
|
+
function contentSecurityPolicy(style, chrome) {
|
|
148
|
+
const styleHash = createHash("sha256").update(style).digest("base64");
|
|
149
|
+
const logoOrigin = httpsOrigin(chrome?.logoUrl);
|
|
150
|
+
return [
|
|
151
|
+
"default-src 'none'",
|
|
152
|
+
`style-src 'sha256-${styleHash}'`,
|
|
153
|
+
"font-src 'self'",
|
|
154
|
+
`img-src 'self' data:${logoOrigin === undefined ? "" : ` ${logoOrigin}`}`,
|
|
155
|
+
"form-action 'self'",
|
|
156
|
+
"base-uri 'none'",
|
|
157
|
+
"frame-ancestors 'none'",
|
|
158
|
+
].join("; ");
|
|
159
|
+
}
|
|
160
|
+
export function renderUnsubscribePage(input) {
|
|
161
|
+
const { state, locale, chrome } = input;
|
|
162
|
+
const { title, bodyHtml } = pageText(state, locale);
|
|
163
|
+
const style = pageStyle(accentOf(chrome));
|
|
164
|
+
const branded = chrome !== null && chrome !== undefined;
|
|
165
|
+
// html-ok: static CSS whose only variable is the hex-validated accent; escaping would break its quotes and the CSP hash.
|
|
166
|
+
const styleBlockHtml = `<style>${style}</style>`;
|
|
167
|
+
const html = `<!doctype html>
|
|
168
|
+
<html lang="${escapeHtmlAttr(locale)}">
|
|
169
|
+
<head>
|
|
170
|
+
<meta charset="utf-8">
|
|
171
|
+
<meta name="robots" content="noindex">
|
|
172
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
173
|
+
<title>${escapeHtml(title)}</title>
|
|
174
|
+
${styleBlockHtml}
|
|
175
|
+
</head>
|
|
176
|
+
<body>
|
|
177
|
+
<main class="page">
|
|
178
|
+
<div class="card">
|
|
179
|
+
<div class="accent"></div>
|
|
180
|
+
${branded ? brandRowHtml(chrome) : ""}
|
|
181
|
+
<div class="content">
|
|
182
|
+
<h1>${escapeHtml(title)}</h1>
|
|
183
|
+
${bodyHtml}
|
|
184
|
+
</div>
|
|
185
|
+
${branded ? bandHtml(chrome) : ""}
|
|
186
|
+
</div>
|
|
187
|
+
${branded ? footerHtml(chrome) : ""}
|
|
188
|
+
</main>
|
|
189
|
+
</body>
|
|
190
|
+
</html>`;
|
|
191
|
+
return { html, contentSecurityPolicy: contentSecurityPolicy(style, chrome) };
|
|
192
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ExtraRouteDefinition } from "@cosmicdrift/kumiko-framework/api";
|
|
2
2
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import "
|
|
3
|
+
import type { MailChrome } from "../renderer-foundation/index.ts";
|
|
4
4
|
export type UnsubscribeTokenPayload = {
|
|
5
5
|
readonly userId: string;
|
|
6
6
|
readonly tenantId: TenantId;
|
|
@@ -41,10 +41,18 @@ export type UnsubscribeResultPage = {
|
|
|
41
41
|
readonly kind: "resubscribed";
|
|
42
42
|
} | {
|
|
43
43
|
readonly kind: "failed";
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: "invalid";
|
|
44
46
|
};
|
|
45
|
-
/** The
|
|
46
|
-
* (e.g. legacy) unsubscribe links. Texts come from the mail translations of `locale
|
|
47
|
+
/** The result page the unsubscribe routes answer with, for apps serving their own
|
|
48
|
+
* (e.g. legacy) unsubscribe links. Texts come from the mail translations of `locale`;
|
|
49
|
+
* `chrome` (the mail renderer's readMailChrome) adds the tenant's brand row and footer.
|
|
50
|
+
* Served under runProdApp's default CSP the style block and the same-origin font pass;
|
|
51
|
+
* an https logo additionally needs its origin, e.g.
|
|
52
|
+
* `securityHeaders: { csp: { extend: { "img-src": [logoOrigin] } } }`. A hand-written CSP
|
|
53
|
+
* needs `style-src 'unsafe-inline'` as well. */
|
|
47
54
|
export declare function renderUnsubscribeResultPage(page: UnsubscribeResultPage & {
|
|
48
55
|
readonly locale?: string | undefined;
|
|
56
|
+
readonly chrome?: MailChrome | null | undefined;
|
|
49
57
|
}): string;
|
|
50
58
|
export declare function createUnsubscribeRoutes(options: UnsubscribeRouteOptions): readonly ExtraRouteDefinition[];
|