@cosmicdrift/kumiko-bundled-features 0.368.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 +15 -7
- package/dist/channel-email/email-channel.js +17 -3
- 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 +6 -2
- package/dist/channel-email/index.d.ts +6 -5
- package/dist/channel-email/index.js +2 -1
- 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/i18n.js +1 -2
- 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 +3 -1
- 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 -19
- package/dist/delivery/index.js +3 -2
- 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 +22 -1
- package/dist/delivery/unsubscribe.js +152 -65
- 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 +4 -7
- package/dist/mail-foundation/feature.js +16 -14
- package/dist/mail-foundation/i18n.d.ts +14 -0
- package/dist/mail-foundation/i18n.js +8 -0
- 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 +6 -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/config-keys.d.ts +7 -0
- package/dist/mail-transport-smtp/config-keys.js +65 -0
- package/dist/mail-transport-smtp/feature.d.ts +0 -16
- package/dist/mail-transport-smtp/feature.js +5 -35
- package/dist/mail-transport-smtp/i18n.d.ts +41 -0
- package/dist/mail-transport-smtp/i18n.js +28 -0
- 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 +5 -3
- package/dist/secrets/feature.js +19 -5
- package/dist/secrets/handlers/delete.write.js +4 -3
- package/dist/secrets/handlers/rotate.job.d.ts +1 -1
- package/dist/secrets/handlers/set.write.js +4 -3
- 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 -2
- package/dist/template-resolver/constants.js +0 -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/send-test.write.js +4 -2
- 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/feature.js +7 -4
- 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 +7 -4
- package/dist/user-data-rights/lib/default-mailers.js +25 -3
- 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 +13 -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 +12 -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 +15 -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 +18 -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/user-data-rights/changes.json +6 -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
|
@@ -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;
|
|
@@ -34,4 +34,25 @@ export declare function signUnsubscribeToken(payload: UnsubscribeTokenPayload, s
|
|
|
34
34
|
*/
|
|
35
35
|
export declare function signAddressUnsubscribeToken(payload: AddressUnsubscribeTokenPayload, secret: string): Promise<string>;
|
|
36
36
|
export declare const DELIVERY_UNSUBSCRIBE_ONE_CLICK_HEADER_VALUE: "List-Unsubscribe=One-Click";
|
|
37
|
+
export type UnsubscribeResultPage = {
|
|
38
|
+
readonly kind: "unsubscribed";
|
|
39
|
+
readonly resubscribeToken?: string;
|
|
40
|
+
} | {
|
|
41
|
+
readonly kind: "resubscribed";
|
|
42
|
+
} | {
|
|
43
|
+
readonly kind: "failed";
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: "invalid";
|
|
46
|
+
};
|
|
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. */
|
|
54
|
+
export declare function renderUnsubscribeResultPage(page: UnsubscribeResultPage & {
|
|
55
|
+
readonly locale?: string | undefined;
|
|
56
|
+
readonly chrome?: MailChrome | null | undefined;
|
|
57
|
+
}): string;
|
|
37
58
|
export declare function createUnsubscribeRoutes(options: UnsubscribeRouteOptions): readonly ExtraRouteDefinition[];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ExtraRouteRejection, signatureRoute, } from "@cosmicdrift/kumiko-framework/api";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { resolveMailLocale } from "@cosmicdrift/kumiko-framework/i18n";
|
|
3
|
+
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
4
4
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
5
5
|
import * as jose from "jose";
|
|
6
6
|
import * as z from "zod";
|
|
7
7
|
import { hashUnsubscribeAddress } from "./address-opt-out.js";
|
|
8
|
-
import { DELIVERY_RESUBSCRIBE_PATH, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, } from "./constants.js";
|
|
9
|
-
import "./unsubscribe-page
|
|
8
|
+
import { DELIVERY_RESUBSCRIBE_PATH, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryQueries, } from "./constants.js";
|
|
9
|
+
import { renderUnsubscribePage } from "./unsubscribe-page.js";
|
|
10
10
|
// The mail's locale, so the pages behind the link speak the mail's language. Optional: links
|
|
11
11
|
// signed before the claim existed keep verifying and fall back to English.
|
|
12
12
|
const localeClaimSchema = z
|
|
@@ -59,6 +59,32 @@ function localeClaim(locale) {
|
|
|
59
59
|
const UNSUBSCRIBE_TOKEN_INVALID_BODY = {
|
|
60
60
|
error: { code: "unsubscribe_token_invalid", message: "Invalid or expired token" },
|
|
61
61
|
};
|
|
62
|
+
// jose checks the signature and the issuer before the expiry, so the claims of an
|
|
63
|
+
// expired token are authentic: enough to dress the "link expired" page in the
|
|
64
|
+
// tenant's look and language, never enough to write.
|
|
65
|
+
const expiredTokenScopeSchema = z.object({
|
|
66
|
+
iss: z.literal(UNSUBSCRIBE_ISSUER),
|
|
67
|
+
tenantId: z.string().min(1),
|
|
68
|
+
locale: localeClaimSchema,
|
|
69
|
+
});
|
|
70
|
+
class ExpiredUnsubscribeTokenRejection extends ExtraRouteRejection {
|
|
71
|
+
tenantId;
|
|
72
|
+
locale;
|
|
73
|
+
constructor(tenantId, locale) {
|
|
74
|
+
super(400, UNSUBSCRIBE_TOKEN_INVALID_BODY, "unsubscribe token expired");
|
|
75
|
+
this.tenantId = tenantId;
|
|
76
|
+
this.locale = locale;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function expiredTokenRejection(err) {
|
|
80
|
+
if (!(err instanceof jose.errors.JWTExpired))
|
|
81
|
+
return null;
|
|
82
|
+
const scope = expiredTokenScopeSchema.safeParse(err.payload);
|
|
83
|
+
if (!scope.success)
|
|
84
|
+
return null;
|
|
85
|
+
// @cast-boundary engine-bridge — string post-zod → branded TenantId
|
|
86
|
+
return new ExpiredUnsubscribeTokenRejection(scope.data.tenantId, scope.data.locale);
|
|
87
|
+
}
|
|
62
88
|
export async function signUnsubscribeToken(payload, secret) {
|
|
63
89
|
assertUnsubscribeSecret(secret, "signUnsubscribeToken");
|
|
64
90
|
const encodedSecret = new TextEncoder().encode(secret);
|
|
@@ -108,10 +134,6 @@ export async function signAddressUnsubscribeToken(payload, secret) {
|
|
|
108
134
|
// RFC 8058 fixed value — both the List-Unsubscribe-Post header and the body a
|
|
109
135
|
// one-click client POSTs.
|
|
110
136
|
export const DELIVERY_UNSUBSCRIBE_ONE_CLICK_HEADER_VALUE = "List-Unsubscribe=One-Click";
|
|
111
|
-
const CONFIRMATION_PAGE_HEADERS = {
|
|
112
|
-
"Cache-Control": "no-store",
|
|
113
|
-
"Referrer-Policy": "no-referrer",
|
|
114
|
-
};
|
|
115
137
|
// Undo token, handed out only in the response of a successful unsubscribe. A
|
|
116
138
|
// separate audience and a short expiry keep the long-lived mailed unsubscribe
|
|
117
139
|
// link from being able to undo an opt-out (and vice versa).
|
|
@@ -193,7 +215,8 @@ async function verifyUnsubscribeToken(token, encodedSecret, purpose) {
|
|
|
193
215
|
catch (err) {
|
|
194
216
|
if (err instanceof ExtraRouteRejection)
|
|
195
217
|
throw err;
|
|
196
|
-
throw
|
|
218
|
+
throw (expiredTokenRejection(err) ??
|
|
219
|
+
new ExtraRouteRejection(400, UNSUBSCRIBE_TOKEN_INVALID_BODY, "unsubscribe token verification failed"));
|
|
197
220
|
}
|
|
198
221
|
}
|
|
199
222
|
async function dispatchUnsubscribeWrite(verified, deps) {
|
|
@@ -250,44 +273,101 @@ async function dispatchResubscribeWrite(verified, deps) {
|
|
|
250
273
|
function pageLocale(locale) {
|
|
251
274
|
return resolveMailLocale(locale ?? "en");
|
|
252
275
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
/** The result page the unsubscribe routes answer with, for apps serving their own
|
|
277
|
+
* (e.g. legacy) unsubscribe links. Texts come from the mail translations of `locale`;
|
|
278
|
+
* `chrome` (the mail renderer's readMailChrome) adds the tenant's brand row and footer.
|
|
279
|
+
* Served under runProdApp's default CSP the style block and the same-origin font pass;
|
|
280
|
+
* an https logo additionally needs its origin, e.g.
|
|
281
|
+
* `securityHeaders: { csp: { extend: { "img-src": [logoOrigin] } } }`. A hand-written CSP
|
|
282
|
+
* needs `style-src 'unsafe-inline'` as well. */
|
|
283
|
+
export function renderUnsubscribeResultPage(page) {
|
|
284
|
+
const { locale, chrome, ...state } = page;
|
|
285
|
+
return renderUnsubscribePage({ state, locale: pageLocale(locale), chrome }).html;
|
|
286
|
+
}
|
|
287
|
+
const NO_STORE_HEADERS = { "Cache-Control": "no-store" };
|
|
288
|
+
const mailChromeLinkSchema = z.object({ label: z.string(), url: z.string() });
|
|
289
|
+
const mailChromeSchema = z
|
|
290
|
+
.object({
|
|
291
|
+
tenantName: z.string(),
|
|
292
|
+
brandSuffix: z.string(),
|
|
293
|
+
logoUrl: z.string().optional(),
|
|
294
|
+
accentColor: z.string().optional(),
|
|
295
|
+
siteUrl: z.string().optional(),
|
|
296
|
+
footerText: z.string().optional(),
|
|
297
|
+
imprint: mailChromeLinkSchema.optional(),
|
|
298
|
+
privacy: mailChromeLinkSchema.optional(),
|
|
299
|
+
})
|
|
300
|
+
.nullable();
|
|
301
|
+
// Branding is decoration: an opt-out that went through must never turn into an
|
|
302
|
+
// error page because a footer resolver or the config read failed.
|
|
303
|
+
async function readPageChrome(deps, tenantId, locale) {
|
|
304
|
+
try {
|
|
305
|
+
const result = await deps.dispatchSystemQuery({
|
|
306
|
+
handlerQn: DeliveryQueries.unsubscribePageChrome,
|
|
307
|
+
payload: { locale },
|
|
308
|
+
tenantId,
|
|
309
|
+
});
|
|
310
|
+
const parsed = mailChromeSchema.safeParse(result);
|
|
311
|
+
return parsed.success ? parsed.data : null;
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
createFallbackLogger("delivery").warn("unsubscribe page shown without tenant branding", {
|
|
315
|
+
errorName: err instanceof Error ? err.name : typeof err,
|
|
316
|
+
});
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
266
319
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
320
|
+
// no-referrer on every page: the GET page carries the token in its URL, and the
|
|
321
|
+
// tenant logo and site link would otherwise receive it in the Referer header.
|
|
322
|
+
const PAGE_HEADERS = {
|
|
323
|
+
"Cache-Control": "no-store",
|
|
324
|
+
"Referrer-Policy": "no-referrer",
|
|
325
|
+
};
|
|
326
|
+
async function pageResponse(
|
|
327
|
+
// biome-ignore lint/suspicious/noExplicitAny: Hono context generics are invisible at the framework boundary
|
|
328
|
+
c, deps, state, scope, status) {
|
|
329
|
+
const locale = pageLocale(scope.locale);
|
|
330
|
+
const chrome = scope.tenantId === undefined ? null : await readPageChrome(deps, scope.tenantId, locale);
|
|
331
|
+
const page = renderUnsubscribePage({ state, locale, chrome });
|
|
332
|
+
return c.html(page.html, status, {
|
|
333
|
+
...PAGE_HEADERS,
|
|
334
|
+
"Content-Security-Policy": page.contentSecurityPolicy,
|
|
335
|
+
});
|
|
274
336
|
}
|
|
275
|
-
function
|
|
276
|
-
const
|
|
277
|
-
return
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
<button type="submit">${escapeHtmlAttr(mailT(lang, "mail.unsubscribe.undoButton"))}</button>
|
|
281
|
-
</form>`);
|
|
337
|
+
function localeFromAcceptLanguage(header) {
|
|
338
|
+
const first = header?.split(",")[0]?.split(";")[0]?.trim();
|
|
339
|
+
return first !== undefined && first !== "" && localeClaimSchema.safeParse(first).success
|
|
340
|
+
? first
|
|
341
|
+
: undefined;
|
|
282
342
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
343
|
+
// A browser lands on a page even for a dead link; API callers keep the JSON 400 from
|
|
344
|
+
// verifyUnsubscribeToken. The rejected result never reaches a write.
|
|
345
|
+
async function verifyForPage(token, encodedSecret, purpose, headers) {
|
|
346
|
+
try {
|
|
347
|
+
return await verifyUnsubscribeToken(token, encodedSecret, purpose);
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
if (err instanceof ExpiredUnsubscribeTokenRejection) {
|
|
351
|
+
return {
|
|
352
|
+
kind: "rejected",
|
|
353
|
+
tenantId: err.tenantId,
|
|
354
|
+
locale: err.locale ?? localeFromAcceptLanguage(headers["accept-language"]),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
if (err instanceof ExtraRouteRejection) {
|
|
358
|
+
return {
|
|
359
|
+
kind: "rejected",
|
|
360
|
+
tenantId: undefined,
|
|
361
|
+
locale: localeFromAcceptLanguage(headers["accept-language"]),
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
throw err;
|
|
365
|
+
}
|
|
286
366
|
}
|
|
287
|
-
function
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
367
|
+
async function verifyPost(request, token, encodedSecret, purpose) {
|
|
368
|
+
return isFormRequest(request.headers["content-type"])
|
|
369
|
+
? verifyForPage(token, encodedSecret, purpose, request.headers)
|
|
370
|
+
: verifyUnsubscribeToken(token, encodedSecret, purpose);
|
|
291
371
|
}
|
|
292
372
|
function isFormRequest(contentType) {
|
|
293
373
|
return contentType?.includes("application/x-www-form-urlencoded") === true;
|
|
@@ -329,30 +409,40 @@ export function createUnsubscribeRoutes(options) {
|
|
|
329
409
|
method: "GET",
|
|
330
410
|
path: DELIVERY_UNSUBSCRIBE_PATH,
|
|
331
411
|
entry: "signature",
|
|
332
|
-
verify: async ({ query }) => {
|
|
412
|
+
verify: async ({ query, headers }) => {
|
|
333
413
|
const token = query["token"];
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
414
|
+
const verified = await verifyForPage(token, encodedSecret, "unsubscribe", headers);
|
|
415
|
+
if (verified.kind === "rejected")
|
|
416
|
+
return verified;
|
|
417
|
+
// verifyForPage only accepts a present token, the check is for the type.
|
|
418
|
+
if (token === undefined)
|
|
419
|
+
return { kind: "rejected", tenantId: undefined, locale: undefined };
|
|
420
|
+
return { kind: "confirm", token, tenantId: verified.tenantId, locale: verified.locale };
|
|
339
421
|
},
|
|
340
|
-
handler: async (c,
|
|
422
|
+
handler: async (c, verified, deps) => verified.kind === "rejected"
|
|
423
|
+
? pageResponse(c, deps, { kind: "invalid" }, verified, 400)
|
|
424
|
+
: pageResponse(c, deps, { kind: "confirm", token: verified.token }, verified, 200),
|
|
341
425
|
});
|
|
342
426
|
const writeRoute = signatureRoute({
|
|
343
427
|
method: "POST",
|
|
344
428
|
path: DELIVERY_UNSUBSCRIBE_PATH,
|
|
345
429
|
entry: "signature",
|
|
346
|
-
verify: async (request) =>
|
|
430
|
+
verify: async (request) => verifyPost(request, tokenFromPostRequest(request), encodedSecret, "unsubscribe"),
|
|
347
431
|
handler: async (c, verified, deps) => {
|
|
432
|
+
if (verified.kind === "rejected") {
|
|
433
|
+
return pageResponse(c, deps, { kind: "invalid" }, verified, 400);
|
|
434
|
+
}
|
|
348
435
|
// Token-verify passed — everything below is a legitimate write. Don't
|
|
349
436
|
// swallow write-errors as "invalid token", that would mask real bugs
|
|
350
437
|
// (e.g. events-table missing, DB down) behind a misleading 400.
|
|
351
438
|
const succeeded = await dispatchUnsubscribeWrite(verified, deps);
|
|
352
439
|
if (!succeeded) {
|
|
353
|
-
return c
|
|
440
|
+
return pageResponse(c, deps, { kind: "failed" }, verified, 500);
|
|
354
441
|
}
|
|
355
|
-
return c
|
|
442
|
+
return pageResponse(c, deps, {
|
|
443
|
+
kind: "unsubscribed",
|
|
444
|
+
resubscribeToken: await signResubscribeToken(verified, encodedSecret),
|
|
445
|
+
}, verified, 200);
|
|
356
446
|
},
|
|
357
447
|
});
|
|
358
448
|
// Undo direction: token only from the JSON/form body, never the query
|
|
@@ -362,28 +452,25 @@ export function createUnsubscribeRoutes(options) {
|
|
|
362
452
|
method: "POST",
|
|
363
453
|
path: DELIVERY_RESUBSCRIBE_PATH,
|
|
364
454
|
entry: "signature",
|
|
365
|
-
verify: async (request) =>
|
|
455
|
+
verify: async (request) => verifyPost(request, tokenFromRequestBody(request), encodedSecret, "resubscribe"),
|
|
366
456
|
handler: async (c, verified, deps) => {
|
|
457
|
+
if (verified.kind === "rejected") {
|
|
458
|
+
return pageResponse(c, deps, { kind: "invalid" }, verified, 400);
|
|
459
|
+
}
|
|
367
460
|
const outcome = await dispatchResubscribeWrite(verified, deps);
|
|
368
461
|
// The undo button on the unsubscribed page posts a form; a browser should land on a page.
|
|
369
462
|
if (isFormRequest(c.req.header("content-type"))) {
|
|
370
463
|
return outcome === "success"
|
|
371
|
-
? c
|
|
372
|
-
: c
|
|
373
|
-
"Cache-Control": "no-store",
|
|
374
|
-
});
|
|
464
|
+
? pageResponse(c, deps, { kind: "resubscribed" }, verified, 200)
|
|
465
|
+
: pageResponse(c, deps, { kind: "failed" }, verified, outcome === "limit_reached" ? 409 : 500);
|
|
375
466
|
}
|
|
376
467
|
if (outcome === "limit_reached") {
|
|
377
|
-
return c.json({ error: { code: DeliveryErrors.resubscribeLimitReached } }, 409,
|
|
378
|
-
"Cache-Control": "no-store",
|
|
379
|
-
});
|
|
468
|
+
return c.json({ error: { code: DeliveryErrors.resubscribeLimitReached } }, 409, NO_STORE_HEADERS);
|
|
380
469
|
}
|
|
381
470
|
if (outcome === "failed") {
|
|
382
|
-
return c.json({ error: { code: "resubscribe_failed" } }, 500,
|
|
383
|
-
"Cache-Control": "no-store",
|
|
384
|
-
});
|
|
471
|
+
return c.json({ error: { code: "resubscribe_failed" } }, 500, NO_STORE_HEADERS);
|
|
385
472
|
}
|
|
386
|
-
return c.json({ isSuccess: true }, 200,
|
|
473
|
+
return c.json({ isSuccess: true }, 200, NO_STORE_HEADERS);
|
|
387
474
|
},
|
|
388
475
|
});
|
|
389
476
|
return [confirmRoute, writeRoute, resubscribeRoute];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { type DeliveryClientOptions, deliveryClient } from "./client-plugin.
|
|
2
|
-
export { DeliveryStatusCell } from "./delivery-status-cell.
|
|
1
|
+
export { type DeliveryClientOptions, deliveryClient } from "./client-plugin.tsx";
|
|
2
|
+
export { DeliveryStatusCell } from "./delivery-status-cell.tsx";
|
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
export declare function createDerivativesSharpFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
2
2
|
readonly exports: void;
|
|
3
3
|
};
|
|
4
|
-
/** @deprecated Use createDerivativesSharpFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
5
|
-
export declare const derivativesSharpFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
6
|
-
readonly exports: void;
|
|
7
|
-
};
|
|
@@ -15,5 +15,3 @@ export function createDerivativesSharpFeature() {
|
|
|
15
15
|
r.useExtension(EXT_DERIVATIVE_RENDERER, "image/*", plugin);
|
|
16
16
|
}, { dedupeOptions: {} });
|
|
17
17
|
}
|
|
18
|
-
/** @deprecated Use createDerivativesSharpFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
19
|
-
export const derivativesSharpFeature = createDerivativesSharpFeature();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createDerivativesSharpFeature
|
|
2
|
-
export { imageMetadata } from "./render.
|
|
1
|
+
export { createDerivativesSharpFeature } from "./feature.ts";
|
|
2
|
+
export { imageMetadata } from "./render.ts";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createDerivativesSharpFeature
|
|
1
|
+
export { createDerivativesSharpFeature } from "./feature.js";
|
|
2
2
|
export { imageMetadata } from "./render.js";
|
|
@@ -4,10 +4,3 @@ export declare function createDocumentIngestFoundationFeature(): import("@cosmic
|
|
|
4
4
|
maxPagesPerFileConfigKey: import("@cosmicdrift/kumiko-types/config").ConfigKeyHandle<"number">;
|
|
5
5
|
};
|
|
6
6
|
};
|
|
7
|
-
/** @deprecated Use createDocumentIngestFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
8
|
-
export declare const documentIngestFoundationFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
9
|
-
readonly exports: {
|
|
10
|
-
ocrLanguageConfigKey: import("@cosmicdrift/kumiko-types/config").ConfigKeyHandle<"text">;
|
|
11
|
-
maxPagesPerFileConfigKey: import("@cosmicdrift/kumiko-types/config").ConfigKeyHandle<"number">;
|
|
12
|
-
};
|
|
13
|
-
};
|
|
@@ -175,5 +175,3 @@ export function createDocumentIngestFoundationFeature() {
|
|
|
175
175
|
return { ocrLanguageConfigKey, maxPagesPerFileConfigKey };
|
|
176
176
|
}, { dedupeOptions: {} });
|
|
177
177
|
}
|
|
178
|
-
/** @deprecated Use createDocumentIngestFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
|
|
179
|
-
export const documentIngestFoundationFeature = createDocumentIngestFoundationFeature();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { documentIngestAggregateId } from "./aggregate-id.
|
|
2
|
-
export { type DocumentExtractMeta, documentExtractEntity, documentExtractsTable, type IngestPage, } from "./entity.
|
|
3
|
-
export { DOCUMENT_INGEST_AGGREGATE_TYPE, DOCUMENT_INGEST_REQUESTED_EVENT_QN, DOCUMENT_INGEST_REQUESTED_EVENT_SHORT, DOCUMENT_INGEST_SKIPPED_EVENT_QN, DOCUMENT_INGEST_SKIPPED_EVENT_SHORT, type DocumentIngestRequestedPayload, type DocumentIngestSkippedPayload, documentIngestRequestedPayloadSchema, documentIngestSkippedPayloadSchema, } from "./events.
|
|
4
|
-
export { createDocumentIngestFoundationFeature
|
|
5
|
-
export { readIngestPages, writeIngestPages } from "./pages.
|
|
6
|
-
export { type DocumentIngestProviderOptions, documentIngestProviderOptionsSchema, documentIngestProviderTrigger, EXT_DOCUMENT_INGEST_PROVIDER, listIngestibleMimeTypes, type ResolvedDocumentIngestProvider, resolveDocumentIngestProviders, } from "./providers.
|
|
7
|
-
export { type DocumentExtractWriteResult, writeDocumentExtractForLiveFileRef, } from "./write-document-extract.
|
|
1
|
+
export { documentIngestAggregateId } from "./aggregate-id.ts";
|
|
2
|
+
export { type DocumentExtractMeta, documentExtractEntity, documentExtractsTable, type IngestPage, } from "./entity.ts";
|
|
3
|
+
export { DOCUMENT_INGEST_AGGREGATE_TYPE, DOCUMENT_INGEST_REQUESTED_EVENT_QN, DOCUMENT_INGEST_REQUESTED_EVENT_SHORT, DOCUMENT_INGEST_SKIPPED_EVENT_QN, DOCUMENT_INGEST_SKIPPED_EVENT_SHORT, type DocumentIngestRequestedPayload, type DocumentIngestSkippedPayload, documentIngestRequestedPayloadSchema, documentIngestSkippedPayloadSchema, } from "./events.ts";
|
|
4
|
+
export { createDocumentIngestFoundationFeature } from "./feature.ts";
|
|
5
|
+
export { readIngestPages, writeIngestPages } from "./pages.ts";
|
|
6
|
+
export { type DocumentIngestProviderOptions, documentIngestProviderOptionsSchema, documentIngestProviderTrigger, EXT_DOCUMENT_INGEST_PROVIDER, listIngestibleMimeTypes, type ResolvedDocumentIngestProvider, resolveDocumentIngestProviders, } from "./providers.ts";
|
|
7
|
+
export { type DocumentExtractWriteResult, writeDocumentExtractForLiveFileRef, } from "./write-document-extract.ts";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { documentIngestAggregateId } from "./aggregate-id.js";
|
|
3
3
|
export { documentExtractEntity, documentExtractsTable, } from "./entity.js";
|
|
4
4
|
export { DOCUMENT_INGEST_AGGREGATE_TYPE, DOCUMENT_INGEST_REQUESTED_EVENT_QN, DOCUMENT_INGEST_REQUESTED_EVENT_SHORT, DOCUMENT_INGEST_SKIPPED_EVENT_QN, DOCUMENT_INGEST_SKIPPED_EVENT_SHORT, documentIngestRequestedPayloadSchema, documentIngestSkippedPayloadSchema, } from "./events.js";
|
|
5
|
-
export { createDocumentIngestFoundationFeature
|
|
5
|
+
export { createDocumentIngestFoundationFeature } from "./feature.js";
|
|
6
6
|
export { readIngestPages, writeIngestPages } from "./pages.js";
|
|
7
7
|
export { documentIngestProviderOptionsSchema, documentIngestProviderTrigger, EXT_DOCUMENT_INGEST_PROVIDER, listIngestibleMimeTypes, resolveDocumentIngestProviders, } from "./providers.js";
|
|
8
8
|
export { writeDocumentExtractForLiveFileRef, } from "./write-document-extract.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FeatureDefinition, Registry } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
import { DOCUMENT_INGEST_REQUESTED_EVENT_QN } from "./events.
|
|
3
|
+
import { DOCUMENT_INGEST_REQUESTED_EVENT_QN } from "./events.ts";
|
|
4
4
|
export declare const EXT_DOCUMENT_INGEST_PROVIDER: "documentIngestProvider";
|
|
5
5
|
export declare const documentIngestProviderOptionsSchema: z.ZodObject<{
|
|
6
6
|
mimeTypes: z.ZodArray<z.ZodString>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import type { SessionUser } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
import { type DocumentExtractMeta, type IngestPage } from "./entity.
|
|
3
|
+
import { type DocumentExtractMeta, type IngestPage } from "./entity.ts";
|
|
4
4
|
export type DocumentExtractWriteResult = {
|
|
5
5
|
readonly kind: "written";
|
|
6
6
|
readonly documentExtractId: string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type EffectiveFeaturesResolver, type Registry } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
import type { GlobalFeatureToggleRuntime } from "./toggle-runtime.
|
|
2
|
+
import type { GlobalFeatureToggleRuntime } from "./toggle-runtime.ts";
|
|
3
3
|
export declare function composeTierResolverWithGlobalToggles(tierResolver: EffectiveFeaturesResolver, toggleRuntime: GlobalFeatureToggleRuntime, registry: Registry): EffectiveFeaturesResolver;
|