@cosmicdrift/kumiko-bundled-features 0.377.0 → 0.379.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/feature.js +2 -2
- package/dist/account-security/index.d.ts +2 -2
- package/dist/account-security/index.js +2 -2
- package/dist/account-security/{constants.js → web/constants.js} +0 -1
- package/dist/account-security/{i18n.js → web/i18n.js} +0 -1
- package/dist/admin-shell/feature.js +4 -3
- package/dist/admin-shell/index.d.ts +2 -2
- package/dist/admin-shell/index.js +2 -2
- package/dist/admin-shell/web/client-plugin.js +2 -3
- package/dist/admin-shell/{constants.js → web/constants.js} +0 -1
- package/dist/admin-shell/web/default-translations.d.ts +2 -0
- package/dist/admin-shell/web/default-translations.js +4 -0
- package/dist/admin-shell/web/i18n.d.ts +5 -2
- package/dist/admin-shell/web/i18n.js +50 -5
- package/dist/admin-shell/web/index.js +0 -1
- package/dist/audit/feature.js +58 -59
- package/dist/audit/handlers/audit-events.d.ts +102 -0
- package/dist/audit/handlers/audit-events.js +112 -0
- package/dist/audit/handlers/audit-system-db.d.ts +1 -0
- package/dist/audit/handlers/audit-system-db.js +9 -0
- package/dist/audit/handlers/details-all-tenants.query.d.ts +15 -0
- package/dist/audit/handlers/details-all-tenants.query.js +20 -0
- package/dist/audit/handlers/details.query.d.ts +2 -1
- package/dist/audit/handlers/details.query.js +8 -24
- package/dist/audit/handlers/list-all-tenants.query.d.ts +41 -0
- package/dist/audit/handlers/list-all-tenants.query.js +32 -0
- package/dist/audit/handlers/list.query.d.ts +2 -1
- package/dist/audit/handlers/list.query.js +9 -99
- package/dist/audit/handlers/resolve-audit-tenant.d.ts +3 -1
- package/dist/audit/handlers/resolve-audit-tenant.js +21 -7
- package/dist/audit/index.d.ts +1 -1
- package/dist/audit/index.js +1 -1
- package/dist/audit/run-escape-hatch-retention.js +1 -1
- package/dist/audit/screens.d.ts +65 -0
- package/dist/audit/screens.js +73 -0
- package/dist/audit/web/client-plugin.js +2 -3
- package/dist/audit/{constants.d.ts → web/constants.d.ts} +8 -0
- package/dist/audit/{constants.js → web/constants.js} +8 -1
- package/dist/audit/web/default-translations.d.ts +2 -0
- package/dist/audit/web/default-translations.js +3 -0
- package/dist/audit/web/i18n.d.ts +5 -2
- package/dist/audit/web/i18n.js +31 -4
- package/dist/audit/web/index.js +0 -1
- package/dist/auth-email-password/bootstrap.d.ts +1 -1
- package/dist/auth-email-password/bootstrap.js +4 -4
- package/dist/auth-email-password/errors.js +1 -1
- package/dist/auth-email-password/feature.js +2 -2
- package/dist/auth-email-password/handlers/confirm-account-unlock.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.js +3 -3
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -0
- package/dist/auth-email-password/handlers/login.write.js +26 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.js +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.js +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.js +1 -1
- package/dist/auth-email-password/handlers/reset-password.write.js +1 -1
- package/dist/auth-email-password/handlers/verify-email.write.js +1 -1
- package/dist/auth-email-password/index.d.ts +1 -1
- package/dist/auth-email-password/index.js +1 -1
- package/dist/auth-email-password/mail-notifications.js +1 -1
- package/dist/auth-email-password/signup-activation.js +1 -1
- package/dist/auth-email-password/web/auth-client.js +0 -1
- package/dist/auth-email-password/web/auth-form-logic.js +0 -1
- package/dist/auth-email-password/web/auth-form-primitives.js +0 -1
- package/dist/auth-email-password/web/auth-gate.js +0 -1
- package/dist/auth-email-password/web/auth-redirect.js +0 -1
- package/dist/auth-email-password/web/client-actions.js +0 -1
- package/dist/auth-email-password/web/client-plugin.js +1 -2
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +0 -1
- package/dist/auth-email-password/{constants.js → web/constants.js} +3 -6
- package/dist/auth-email-password/web/default-topbar-actions.js +0 -1
- package/dist/auth-email-password/web/forgot-password-screen.js +0 -1
- package/dist/auth-email-password/{i18n.js → web/i18n.js} +3 -4
- package/dist/auth-email-password/web/index.d.ts +1 -1
- package/dist/auth-email-password/web/index.js +1 -2
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +2 -2
- package/dist/auth-email-password/web/invite-accept-screen.js +0 -1
- package/dist/auth-email-password/web/login-screen.js +0 -1
- package/dist/auth-email-password/{mail-i18n.js → web/mail-i18n.js} +0 -1
- package/dist/auth-email-password/web/request-account-unlock-screen.js +0 -1
- package/dist/auth-email-password/web/reset-password-screen.js +0 -1
- package/dist/auth-email-password/web/session-bootstrap-error.js +0 -1
- package/dist/auth-email-password/web/session.js +0 -1
- package/dist/auth-email-password/web/signup-complete-screen.d.ts +2 -2
- package/dist/auth-email-password/web/signup-complete-screen.js +0 -1
- package/dist/auth-email-password/web/signup-screen.js +0 -1
- package/dist/auth-email-password/web/tenant-menu-items.js +0 -1
- package/dist/auth-email-password/web/tenant-switcher.js +0 -1
- package/dist/auth-email-password/web/use-shell-user.js +0 -1
- package/dist/auth-email-password/web/user-menu.js +0 -1
- package/dist/auth-email-password/web/verify-email-screen.js +0 -1
- package/dist/auth-mfa/errors.d.ts +1 -1
- package/dist/auth-mfa/errors.js +2 -2
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/enable-start.write.js +1 -1
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/index.d.ts +1 -1
- package/dist/auth-mfa/index.js +1 -1
- package/dist/auth-mfa/mfa-status-checker.js +1 -1
- package/dist/auth-mfa/screens.js +1 -1
- package/dist/auth-mfa/web/client-plugin.js +0 -1
- package/dist/auth-mfa/{constants.js → web/constants.js} +0 -1
- package/dist/auth-mfa/web/i18n.js +0 -1
- package/dist/auth-mfa/web/index.js +0 -1
- package/dist/auth-mfa/web/mfa-client.js +0 -1
- package/dist/auth-mfa/web/mfa-disable-dialog.js +1 -2
- package/dist/auth-mfa/web/mfa-recovery-codes-reveal.js +0 -1
- package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +1 -2
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +11 -18
- package/dist/auth-mfa/web/mfa-verify-screen.js +0 -1
- package/dist/billing-foundation/checkout-core.js +1 -1
- package/dist/billing-foundation/consumer-protection/consent-text.d.ts +2 -2
- package/dist/billing-foundation/consumer-protection/consent-text.js +1 -1
- package/dist/billing-foundation/consumer-protection/issue-confirmation.js +7 -3
- package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
- package/dist/billing-foundation/consumer-protection/register-consent.js +1 -1
- package/dist/billing-foundation/consumer-protection/register-termination.js +8 -2
- package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +1 -0
- package/dist/billing-foundation/consumer-protection/stored-user-email.js +8 -0
- package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +5 -1
- package/dist/billing-foundation/consumer-protection/termination-mail.js +3 -1
- package/dist/billing-foundation/consumer-protection/termination-notify.js +1 -1
- package/dist/billing-foundation/consumer-protection/termination-pages.js +109 -15
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +8 -1
- package/dist/billing-foundation/consumer-protection/termination-record.js +76 -3
- package/dist/billing-foundation/consumer-protection/termination-request.js +33 -6
- package/dist/billing-foundation/consumer-protection/termination-revoke.d.ts +28 -0
- package/dist/billing-foundation/consumer-protection/termination-revoke.js +149 -0
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +17 -1
- package/dist/billing-foundation/consumer-protection/termination-texts.js +39 -0
- package/dist/billing-foundation/events.d.ts +9 -0
- package/dist/billing-foundation/events.js +14 -2
- package/dist/billing-foundation/feature.js +1 -1
- package/dist/billing-foundation/handlers/process-event.write.d.ts +5 -1
- package/dist/billing-foundation/handlers/process-event.write.js +57 -3
- package/dist/billing-foundation/handlers/switch-plan.write.js +1 -1
- package/dist/billing-foundation/handlers/sync-subscription.write.js +1 -1
- package/dist/billing-foundation/index.d.ts +2 -2
- package/dist/billing-foundation/index.js +2 -2
- package/dist/billing-foundation/plan-catalog.js +1 -1
- package/dist/billing-foundation/screens.js +1 -1
- package/dist/billing-foundation/subscription-tier-sync.js +1 -1
- package/dist/billing-foundation/types.d.ts +14 -2
- package/dist/billing-foundation/types.js +1 -1
- package/dist/billing-foundation/validate-options.js +3 -3
- package/dist/billing-foundation/web/billing-contact-plan.js +1 -2
- package/dist/billing-foundation/web/billing-plans-panel.js +1 -2
- package/dist/billing-foundation/web/cancel-contract-dialog.js +1 -2
- package/dist/billing-foundation/web/checkout-consent-dialog.js +1 -2
- package/dist/billing-foundation/web/client-plugin.js +1 -1
- package/dist/billing-foundation/{constants.d.ts → web/constants.d.ts} +21 -14
- package/dist/billing-foundation/{constants.js → web/constants.js} +35 -31
- package/dist/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.js +0 -1
- package/dist/billing-foundation/{contact-card.js → web/contact-card.js} +0 -1
- package/dist/billing-foundation/web/index.d.ts +2 -2
- package/dist/billing-foundation/web/index.js +2 -3
- package/dist/billing-foundation/web/localized-params.js +0 -1
- package/dist/billing-foundation/webhook-handler.js +4 -1
- package/dist/cap-counter/stock-cap-guard.js +8 -0
- package/dist/cap-overview/feature.js +1 -1
- package/dist/cap-overview/handlers/caps-usage.query.js +1 -1
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -2
- package/dist/cap-overview/index.d.ts +2 -2
- package/dist/cap-overview/index.js +2 -2
- package/dist/cap-overview/screens.js +1 -1
- package/dist/cap-overview/web/cap-cards-panel.js +1 -1
- package/dist/cap-overview/web/cap-usage-bar.js +1 -2
- package/dist/cap-overview/web/client-plugin.js +1 -1
- package/dist/cap-overview/{constants.js → web/constants.js} +0 -1
- package/dist/cap-overview/web/index.js +0 -1
- package/dist/cap-overview/{usage-math.d.ts → web/usage-math.d.ts} +1 -1
- package/dist/compliance-profiles/feature.js +1 -1
- package/dist/compliance-profiles/index.d.ts +1 -1
- package/dist/compliance-profiles/index.js +1 -1
- package/dist/compliance-profiles/web/client-plugin.js +1 -2
- package/dist/compliance-profiles/web/compliance-profile-catalog.js +1 -2
- package/dist/compliance-profiles/{constants.js → web/constants.js} +0 -1
- package/dist/compliance-profiles/web/index.js +0 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/web/client-plugin.d.ts +1 -1
- package/dist/config/web/client-plugin.js +1 -2
- package/dist/config/{constants.js → web/constants.js} +0 -1
- package/dist/config/web/i18n.js +1 -1
- package/dist/config/web/index.d.ts +1 -1
- package/dist/config/web/index.js +1 -2
- package/dist/config/write-helpers.js +1 -1
- package/dist/custom-fields/feature.js +1 -1
- package/dist/custom-fields/handlers/clear-custom-field.write.js +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +1 -1
- package/dist/custom-fields/handlers/delete-system-field.write.js +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +1 -1
- package/dist/custom-fields/handlers/set-custom-field.write.js +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/index.d.ts +1 -1
- package/dist/custom-fields/index.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +1 -1
- package/dist/custom-fields/schemas.js +1 -1
- package/dist/custom-fields/web/client-plugin.js +1 -2
- package/dist/custom-fields/{constants.js → web/constants.js} +18 -19
- package/dist/custom-fields/web/custom-fields-form-section.js +1 -2
- package/dist/custom-fields/web/i18n.js +0 -1
- package/dist/custom-fields/web/index.d.ts +1 -1
- package/dist/custom-fields/web/index.js +1 -2
- package/dist/custom-fields/wire-for-entity.js +1 -1
- package/dist/delivery/address-opt-out.js +1 -1
- package/dist/delivery/attempt-log-retention.js +21 -3
- package/dist/delivery/constants.d.ts +1 -1
- package/dist/delivery/constants.js +2 -2
- package/dist/delivery/i18n.js +1 -1
- package/dist/delivery/unsubscribe-page.js +1 -1
- package/dist/delivery/web/client-plugin.js +1 -1
- package/dist/delivery/web/delivery-channel-cell.js +0 -1
- package/dist/delivery/web/delivery-error-cell.js +0 -1
- package/dist/delivery/web/delivery-status-cell.js +1 -2
- package/dist/delivery/web/delivery-time-cell.js +0 -1
- package/dist/delivery/web/delivery-type-cell.js +0 -1
- package/dist/delivery/web/index.js +0 -1
- package/dist/delivery/{public-names.js → web/public-names.js} +0 -1
- package/dist/document-ingest-foundation/events.d.ts +1 -0
- package/dist/document-ingest-foundation/events.js +3 -0
- package/dist/document-ingest-foundation/executor.js +2 -1
- package/dist/document-ingest-foundation/feature.js +16 -5
- package/dist/document-ingest-foundation/index.d.ts +1 -1
- package/dist/document-ingest-foundation/index.js +1 -1
- package/dist/feature-toggles/feature.d.ts +1 -1
- package/dist/feature-toggles/feature.js +2 -2
- package/dist/feature-toggles/handlers/list.query.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +1 -1
- package/dist/feature-toggles/handlers/set.write.js +1 -1
- package/dist/feature-toggles/index.d.ts +1 -1
- package/dist/feature-toggles/index.js +1 -1
- package/dist/feature-toggles/web/client-plugin.js +1 -2
- package/dist/feature-toggles/{constants.js → web/constants.js} +0 -1
- package/dist/feature-toggles/web/index.js +0 -1
- package/dist/folders/feature.js +1 -1
- package/dist/folders/handlers/clear-folder.write.js +1 -1
- package/dist/folders/handlers/delete-folder.write.js +1 -1
- package/dist/folders/handlers/set-folder.write.js +1 -1
- package/dist/folders/index.d.ts +1 -1
- package/dist/folders/index.js +1 -1
- package/dist/folders/web/client-plugin.js +1 -2
- package/dist/folders/{constants.js → web/constants.js} +0 -1
- package/dist/folders/web/folder-manager.js +1 -2
- package/dist/folders/web/folder-section.js +1 -2
- package/dist/folders/web/i18n.js +0 -1
- package/dist/folders/web/index.d.ts +1 -1
- package/dist/folders/web/index.js +1 -2
- package/dist/folders/web/tree.js +0 -1
- package/dist/form-draft/db/queries/cleanup.d.ts +3 -2
- package/dist/form-draft/db/queries/cleanup.js +18 -9
- package/dist/form-draft/decrypt-draft.d.ts +2 -0
- package/dist/form-draft/decrypt-draft.js +19 -0
- package/dist/form-draft/entity.js +6 -9
- package/dist/form-draft/feature.js +1 -1
- package/dist/form-draft/handlers/cleanup.job.d.ts +1 -0
- package/dist/form-draft/handlers/cleanup.job.js +17 -4
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/handlers/get.query.js +6 -7
- package/dist/form-draft/handlers/list.query.js +11 -7
- package/dist/form-draft/handlers/save.write.js +1 -1
- package/dist/form-draft/index.d.ts +1 -1
- package/dist/form-draft/index.js +1 -1
- package/dist/form-draft/lookup.d.ts +2 -2
- package/dist/form-draft/lookup.js +7 -2
- package/dist/form-draft/schemas.js +1 -1
- package/dist/form-draft/{constants.js → web/constants.js} +0 -1
- package/dist/form-draft-user-data/hooks.js +2 -2
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.d.ts +1 -1
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +11 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +7 -5
- package/dist/jobs/feature.js +2 -2
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/handlers/trigger.write.js +1 -1
- package/dist/jobs/index.d.ts +1 -1
- package/dist/jobs/index.js +1 -1
- package/dist/jobs/web/client-plugin.js +2 -3
- package/dist/jobs/{constants.js → web/constants.js} +0 -1
- package/dist/jobs/web/default-translations.d.ts +2 -0
- package/dist/jobs/web/default-translations.js +3 -0
- package/dist/jobs/web/i18n.d.ts +5 -2
- package/dist/jobs/web/i18n.js +51 -4
- package/dist/jobs/web/index.js +0 -1
- package/dist/ledger/entity.d.ts +1 -1
- package/dist/ledger/entity.js +1 -1
- package/dist/ledger/feature.js +1 -1
- package/dist/ledger/handlers/confirm-schedule-period.write.js +2 -5
- package/dist/ledger/handlers/create-transaction.write.js +1 -1
- package/dist/ledger/handlers/reports.query.js +1 -1
- package/dist/ledger/handlers/reverse-transaction.write.js +1 -1
- package/dist/ledger/index.d.ts +1 -1
- package/dist/ledger/index.js +1 -1
- package/dist/ledger/recurring.d.ts +1 -1
- package/dist/ledger/reports.d.ts +1 -1
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/{constants.js → web/constants.js} +0 -1
- package/dist/ledger/web/index.d.ts +1 -1
- package/dist/ledger/web/index.js +1 -2
- package/dist/legal-pages/feature.d.ts +1 -1
- package/dist/legal-pages/feature.js +1 -1
- package/dist/legal-pages/index.d.ts +1 -1
- package/dist/legal-pages/index.js +1 -1
- package/dist/legal-pages/lib/boot-check.d.ts +1 -1
- package/dist/legal-pages/lib/boot-check.js +1 -1
- package/dist/legal-pages/lib/validate-routes.d.ts +1 -1
- package/dist/legal-pages/web/client-plugin.js +1 -2
- package/dist/legal-pages/{constants.js → web/constants.js} +6 -8
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/i18n.d.ts +5 -2
- package/dist/mail-foundation/i18n.js +3 -2
- package/dist/mail-transport-smtp/i18n.d.ts +1 -1
- package/dist/mail-transport-smtp/i18n.js +1 -1
- package/dist/managed-pages/feature.js +1 -1
- package/dist/managed-pages/web/client-plugin.js +1 -2
- package/dist/managed-pages/web/default-translations.d.ts +2 -0
- package/dist/managed-pages/web/default-translations.js +11 -0
- package/dist/managed-pages/web/i18n.d.ts +5 -2
- package/dist/managed-pages/web/i18n.js +53 -12
- package/dist/managed-pages/web/index.d.ts +1 -1
- package/dist/managed-pages/web/index.js +1 -2
- package/dist/metrics/compute.d.ts +1 -1
- package/dist/metrics/compute.js +1 -1
- package/dist/metrics/feature.js +1 -1
- package/dist/metrics/index.d.ts +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/types.d.ts +1 -1
- package/dist/metrics/validate.js +1 -1
- package/dist/metrics/{constants.js → web/constants.js} +0 -1
- package/dist/metrics/window.d.ts +1 -1
- package/dist/notes-history/feature.js +1 -1
- package/dist/notes-history/handlers/add-note.write.js +1 -1
- package/dist/notes-history/index.d.ts +1 -1
- package/dist/notes-history/index.js +1 -1
- package/dist/notes-history/web/client-plugin.js +1 -2
- package/dist/notes-history/{constants.js → web/constants.js} +0 -1
- package/dist/notes-history/web/i18n.js +0 -1
- package/dist/notes-history/web/index.d.ts +1 -1
- package/dist/notes-history/web/index.js +1 -2
- package/dist/notes-history/web/notes-section.js +2 -3
- package/dist/personal-access-tokens/feature.d.ts +2 -2
- package/dist/personal-access-tokens/feature.js +6 -4
- package/dist/personal-access-tokens/handlers/available-scopes.query.d.ts +1 -1
- package/dist/personal-access-tokens/handlers/create.write.js +1 -1
- package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
- package/dist/personal-access-tokens/hash.js +1 -1
- package/dist/personal-access-tokens/i18n.d.ts +1 -1
- package/dist/personal-access-tokens/i18n.js +1 -1
- package/dist/personal-access-tokens/index.d.ts +5 -5
- package/dist/personal-access-tokens/index.js +3 -3
- package/dist/personal-access-tokens/resolver.d.ts +1 -1
- package/dist/personal-access-tokens/resolver.js +1 -1
- package/dist/personal-access-tokens/schema/api-token.js +1 -1
- package/dist/personal-access-tokens/screens.d.ts +1 -1
- package/dist/personal-access-tokens/screens.js +1 -1
- package/dist/personal-access-tokens/{constants.js → web/constants.js} +0 -1
- package/dist/presets/index.d.ts +0 -1
- package/dist/presets/index.js +0 -1
- package/dist/presets/security-baseline.d.ts +1 -1
- package/dist/presets/security-baseline.js +1 -1
- package/dist/secrets/feature.js +1 -1
- package/dist/secrets/handlers/delete.write.js +1 -1
- package/dist/secrets/handlers/list.query.js +1 -1
- package/dist/secrets/handlers/set.write.js +1 -1
- package/dist/secrets/i18n.js +1 -1
- package/dist/secrets/index.d.ts +1 -1
- package/dist/secrets/index.js +1 -1
- package/dist/secrets/{constants.js → web/constants.js} +0 -1
- package/dist/secrets/write-gate.js +1 -1
- package/dist/sessions/feature.js +7 -4
- package/dist/sessions/{i18n.js → web/i18n.js} +0 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/purge-files-reaching-subject.js +7 -3
- package/dist/subscription-stripe/feature.js +2 -1
- package/dist/subscription-stripe/plugin-methods.d.ts +3 -0
- package/dist/subscription-stripe/plugin-methods.js +14 -0
- package/dist/subscription-stripe/verify-webhook.js +1 -0
- package/dist/tags/feature.js +1 -1
- package/dist/tags/handlers/assign-tag.write.js +11 -7
- package/dist/tags/handlers/create-tag.write.js +1 -1
- package/dist/tags/handlers/delete-tag.write.js +4 -1
- package/dist/tags/handlers/remove-tag.write.js +1 -1
- package/dist/tags/handlers/update-tag.write.js +1 -1
- package/dist/tags/index.d.ts +1 -1
- package/dist/tags/index.js +1 -1
- package/dist/tags/screens.js +1 -1
- package/dist/tags/web/client-plugin.js +1 -2
- package/dist/tags/{constants.d.ts → web/constants.d.ts} +1 -0
- package/dist/tags/{constants.js → web/constants.js} +3 -1
- package/dist/tags/web/entity-tags.js +1 -2
- package/dist/tags/web/i18n.js +2 -2
- package/dist/tags/web/index.d.ts +1 -1
- package/dist/tags/web/index.js +1 -2
- package/dist/tags/web/tag-filter.js +1 -2
- package/dist/tags/web/tag-manager.js +5 -4
- package/dist/tags/web/tag-picker.js +0 -1
- package/dist/tags/web/tag-section.js +1 -2
- package/dist/tags/web/tags-cell.js +1 -2
- package/dist/template-resolver/api.d.ts +21 -23
- package/dist/template-resolver/api.js +34 -6
- package/dist/template-resolver/compile-document-body.d.ts +3 -0
- package/dist/template-resolver/compile-document-body.js +51 -4
- package/dist/template-resolver/compile-steps-block.js +2 -2
- package/dist/template-resolver/document-ops.d.ts +1 -1
- package/dist/template-resolver/document-ops.js +3 -3
- package/dist/template-resolver/document-sanitizer.d.ts +2 -2
- package/dist/template-resolver/document-sanitizer.js +23 -3
- package/dist/template-resolver/feature.d.ts +11 -0
- package/dist/template-resolver/feature.js +68 -35
- package/dist/template-resolver/handlers/by-slug.query.js +6 -1
- package/dist/template-resolver/handlers/by-tenant.query.js +6 -2
- package/dist/template-resolver/handlers/collection-item.query.js +2 -1
- package/dist/template-resolver/handlers/collection-list.query.js +2 -1
- package/dist/template-resolver/handlers/collection-set.write.d.ts +2 -1
- package/dist/template-resolver/handlers/collection-set.write.js +15 -3
- package/dist/template-resolver/handlers/collection-shared.d.ts +1 -2
- package/dist/template-resolver/handlers/collection-shared.js +0 -4
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +2 -1
- package/dist/template-resolver/handlers/copy-locale.write.js +69 -65
- package/dist/template-resolver/handlers/diff-to-system.query.js +5 -1
- package/dist/template-resolver/handlers/discard-draft.write.d.ts +3 -2
- package/dist/template-resolver/handlers/discard-draft.write.js +19 -7
- package/dist/template-resolver/handlers/document-base.d.ts +1 -1
- package/dist/template-resolver/handlers/document-base.js +6 -1
- package/dist/template-resolver/handlers/document-blocks.query.d.ts +1 -1
- package/dist/template-resolver/handlers/document-blocks.query.js +2 -2
- package/dist/template-resolver/handlers/export-bundle.query.js +5 -2
- package/dist/template-resolver/handlers/find-by-id.query.js +4 -2
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +2 -1
- package/dist/template-resolver/handlers/import-bundle.write.js +30 -25
- package/dist/template-resolver/handlers/layout-source.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +5 -2
- package/dist/template-resolver/handlers/overview.query.d.ts +12 -3
- package/dist/template-resolver/handlers/overview.query.js +87 -51
- package/dist/template-resolver/handlers/patch-draft.write.d.ts +2 -1
- package/dist/template-resolver/handlers/patch-draft.write.js +93 -87
- package/dist/template-resolver/handlers/reset-to-system.write.d.ts +2 -1
- package/dist/template-resolver/handlers/reset-to-system.write.js +51 -44
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +2 -1
- package/dist/template-resolver/handlers/resource-link-pdf.write.js +34 -28
- package/dist/template-resolver/handlers/resource-remove.write.d.ts +2 -1
- package/dist/template-resolver/handlers/resource-remove.write.js +39 -33
- package/dist/template-resolver/handlers/resource-shared.js +1 -1
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +2 -1
- package/dist/template-resolver/handlers/resource-upload.write.js +105 -97
- package/dist/template-resolver/handlers/send-test-shared.d.ts +5 -0
- package/dist/template-resolver/handlers/send-test-shared.js +19 -0
- package/dist/template-resolver/handlers/send-test-status.query.d.ts +9 -0
- package/dist/template-resolver/handlers/send-test-status.query.js +18 -0
- package/dist/template-resolver/handlers/send-test.write.d.ts +2 -1
- package/dist/template-resolver/handlers/send-test.write.js +89 -91
- package/dist/template-resolver/handlers/set.write.d.ts +2 -1
- package/dist/template-resolver/handlers/set.write.js +95 -91
- package/dist/template-resolver/handlers/shared.js +1 -1
- package/dist/template-resolver/handlers/template-gates.d.ts +1 -1
- package/dist/template-resolver/handlers/template-gates.js +1 -1
- package/dist/template-resolver/handlers/template-write.d.ts +1 -1
- package/dist/template-resolver/handlers/template-write.js +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +6 -7
- package/dist/template-resolver/handlers/toggle-status.write.js +28 -10
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +2 -1
- package/dist/template-resolver/handlers/upsert-tenant.write.js +30 -24
- package/dist/template-resolver/handlers/usage.query.js +3 -2
- package/dist/template-resolver/handlers/validate.query.d.ts +1 -1
- package/dist/template-resolver/handlers/validate.query.js +3 -1
- package/dist/template-resolver/i18n.d.ts +3 -0
- package/dist/template-resolver/i18n.js +24 -0
- package/dist/template-resolver/index.d.ts +8 -5
- package/dist/template-resolver/index.js +6 -4
- package/dist/template-resolver/layout-appearance.js +1 -1
- package/dist/template-resolver/layout-regions.d.ts +1 -1
- package/dist/template-resolver/seeding.d.ts +4 -1
- package/dist/template-resolver/seeding.js +13 -7
- package/dist/template-resolver/store-template-resource.js +2 -2
- package/dist/template-resolver/table.js +1 -1
- package/dist/template-resolver/template-bundle.js +2 -2
- package/dist/template-resolver/template-delivery-policy.d.ts +22 -0
- package/dist/template-resolver/template-delivery-policy.js +40 -0
- package/dist/template-resolver/template-draft.d.ts +1 -1
- package/dist/template-resolver/template-draft.js +1 -1
- package/dist/template-resolver/template-edit-policy.d.ts +22 -0
- package/dist/template-resolver/template-edit-policy.js +45 -0
- package/dist/template-resolver/template-meta.d.ts +2 -2
- package/dist/template-resolver/template-meta.js +2 -2
- package/dist/template-resolver/template-preview.d.ts +1 -1
- package/dist/template-resolver/template-preview.js +15 -6
- package/dist/template-resolver/template-usage.d.ts +1 -1
- package/dist/template-resolver/template-usage.js +1 -1
- package/dist/template-resolver/template-validation.js +34 -14
- package/dist/template-resolver/testing.js +1 -1
- package/dist/template-resolver/user-content-table.js +1 -1
- package/dist/template-resolver/web/client-plugin.js +1 -2
- package/dist/template-resolver/{constants.d.ts → web/constants.d.ts} +4 -1
- package/dist/template-resolver/{constants.js → web/constants.js} +9 -10
- package/dist/template-resolver/{document-blocks.d.ts → web/document-blocks.d.ts} +2 -2
- package/dist/template-resolver/{document-blocks.js → web/document-blocks.js} +1 -0
- package/dist/template-resolver/web/document-editor-extensions.d.ts +1 -0
- package/dist/template-resolver/web/document-editor-extensions.js +22 -2
- package/dist/template-resolver/web/document-editor.js +0 -1
- package/dist/template-resolver/web/document-images.d.ts +2 -0
- package/dist/template-resolver/web/document-images.js +27 -0
- package/dist/template-resolver/{document-schema.d.ts → web/document-schema.d.ts} +2 -1
- package/dist/template-resolver/{document-schema.js → web/document-schema.js} +4 -1
- package/dist/template-resolver/{document-steps.js → web/document-steps.js} +0 -1
- package/dist/template-resolver/web/document-tiptap-editor.d.ts +1 -1
- package/dist/template-resolver/web/document-tiptap-editor.js +24 -9
- package/dist/template-resolver/web/document-toolbar-blocks.d.ts +4 -2
- package/dist/template-resolver/web/document-toolbar-blocks.js +1 -1
- package/dist/template-resolver/web/editor-handle.js +1 -1
- package/dist/template-resolver/web/i18n.js +5 -1
- package/dist/template-resolver/web/index.d.ts +3 -3
- package/dist/template-resolver/web/index.js +3 -4
- package/dist/template-resolver/{mail-constants.js → web/mail-constants.js} +0 -1
- package/dist/template-resolver/{pdf-constants.js → web/pdf-constants.js} +0 -1
- package/dist/template-resolver/web/placeholder-line-editor-lazy.js +0 -1
- package/dist/template-resolver/web/placeholder-line-editor.js +6 -4
- package/dist/template-resolver/{qualified-names.d.ts → web/qualified-names.d.ts} +2 -0
- package/dist/template-resolver/{qualified-names.js → web/qualified-names.js} +2 -1
- package/dist/template-resolver/web/use-stable-by-key.js +0 -1
- package/dist/tenant/handlers/add-member.write.js +1 -1
- package/dist/tenant/index.d.ts +1 -1
- package/dist/tenant/index.js +1 -1
- package/dist/tenant/invitation-table.js +1 -1
- package/dist/tenant/invited-membership.js +1 -1
- package/dist/tenant/last-tenant-admin.js +1 -1
- package/dist/tenant/member-role-options.js +1 -1
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/web/client-plugin.js +1 -2
- package/dist/tenant/{constants.js → web/constants.js} +3 -6
- package/dist/tenant/web/index.js +0 -1
- package/dist/tenant/web/member-roles-cell.js +0 -1
- package/dist/tenant/web/member-status-cell.js +0 -1
- package/dist/tenant-lifecycle/stages.js +2 -3
- package/dist/tier-engine/entity.d.ts +1 -1
- package/dist/tier-engine/entity.js +1 -1
- package/dist/tier-engine/feature.js +2 -2
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -1
- package/dist/tier-engine/index.d.ts +1 -1
- package/dist/tier-engine/index.js +1 -1
- package/dist/tier-engine/web/client-plugin.js +2 -3
- package/dist/tier-engine/{constants.js → web/constants.js} +2 -3
- package/dist/tier-engine/{i18n.js → web/i18n.js} +0 -1
- package/dist/tier-engine/web/index.js +0 -1
- package/dist/user/handlers/create.write.js +1 -1
- package/dist/user/handlers/update-roles.js +1 -1
- package/dist/user/handlers/update.write.js +1 -1
- package/dist/user/index.d.ts +1 -1
- package/dist/user/index.js +1 -1
- package/dist/user/invited-global-roles.d.ts +1 -1
- package/dist/user/invited-global-roles.js +1 -1
- package/dist/user/schema/user.js +1 -1
- package/dist/user/{constants.js → web/constants.js} +0 -1
- package/dist/user-data-rights/env.js +1 -1
- package/dist/user-data-rights/feature.js +3 -3
- package/dist/user-data-rights/index.d.ts +1 -1
- package/dist/user-data-rights/index.js +1 -1
- package/dist/user-data-rights/lib/resolve-tenant-model.js +1 -1
- package/dist/user-data-rights/mail-notifications.js +1 -1
- package/dist/user-data-rights/web/client-plugin.js +2 -3
- package/dist/user-data-rights/web/confirm-deletion-screen.js +0 -1
- package/dist/user-data-rights/{constants.js → web/constants.js} +11 -12
- package/dist/user-data-rights/web/default-translations.d.ts +2 -0
- package/dist/user-data-rights/web/default-translations.js +59 -0
- package/dist/user-data-rights/web/i18n.d.ts +5 -2
- package/dist/user-data-rights/web/i18n.js +37 -59
- package/dist/user-data-rights/web/index.d.ts +1 -1
- package/dist/user-data-rights/web/index.js +1 -2
- package/dist/user-data-rights/web/privacy-center-screen.js +1 -2
- package/dist/user-data-rights/web/request-deletion-screen.js +0 -1
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +6 -1
- package/dist/user-profile/feature.js +1 -1
- package/dist/user-profile/handlers/change-email.write.js +1 -1
- package/dist/user-profile/index.d.ts +1 -1
- package/dist/user-profile/index.js +1 -1
- package/dist/user-profile/web/client-plugin.js +2 -3
- package/dist/user-profile/{constants.js → web/constants.js} +0 -1
- package/dist/user-profile/{i18n.js → web/i18n.js} +0 -1
- package/dist/user-profile/web/profile-screen.js +2 -3
- package/dist/waitlist/entity.js +1 -1
- package/dist/waitlist/feature.js +1 -1
- package/dist/waitlist/handlers/export-purge.write.js +1 -1
- package/dist/waitlist/handlers/invite.write.js +1 -1
- package/dist/waitlist/handlers/reject.write.js +1 -1
- package/dist/waitlist/handlers/submit.write.js +4 -3
- package/dist/waitlist/import.d.ts +1 -1
- package/dist/waitlist/index.d.ts +1 -1
- package/dist/waitlist/index.js +1 -1
- package/dist/waitlist/legacy-migrate.js +1 -1
- package/dist/waitlist/link-on-signup.js +1 -1
- package/dist/waitlist/mail.d.ts +0 -1
- package/dist/waitlist/mail.js +6 -4
- package/dist/waitlist/payloads.js +1 -1
- package/dist/waitlist/screens.js +1 -1
- package/dist/waitlist/{constants.js → web/constants.js} +0 -1
- package/kumiko-es-tables.json +102 -0
- package/package.json +30 -29
- package/src/audit/changes.json +7 -0
- package/src/auth-email-password/changes.json +6 -0
- package/src/auth-mfa/changes.json +6 -0
- package/src/billing-foundation/changes.json +18 -0
- package/src/cap-counter/changes.json +12 -0
- package/src/delivery/changes.json +6 -0
- package/src/document-ingest-foundation/changes.json +6 -0
- package/src/files/changes.json +7 -0
- package/src/form-draft/changes.json +7 -0
- package/src/inbound-mail-foundation/changes.json +6 -0
- package/src/ledger/changes.json +7 -0
- package/src/mail-foundation/changes.json +6 -0
- package/src/presets/changes.json +7 -0
- package/src/tags/changes.json +6 -0
- package/src/template-resolver/changes.json +63 -0
- package/src/user-data-rights/changes.json +14 -0
- package/src/waitlist/changes.json +6 -0
- package/dist/admin-shell/i18n.d.ts +0 -5
- package/dist/admin-shell/i18n.js +0 -51
- package/dist/audit/i18n.d.ts +0 -5
- package/dist/audit/i18n.js +0 -22
- package/dist/jobs/i18n.d.ts +0 -5
- package/dist/jobs/i18n.js +0 -52
- package/dist/managed-pages/i18n.d.ts +0 -5
- package/dist/managed-pages/i18n.js +0 -55
- package/dist/presets/dsgvo-self-service.d.ts +0 -10
- package/dist/presets/dsgvo-self-service.js +0 -24
- package/dist/user-data-rights/i18n.d.ts +0 -5
- package/dist/user-data-rights/i18n.js +0 -39
- /package/dist/account-security/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/account-security/{i18n.d.ts → web/i18n.d.ts} +0 -0
- /package/dist/admin-shell/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/auth-email-password/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/auth-email-password/{i18n.d.ts → web/i18n.d.ts} +0 -0
- /package/dist/auth-email-password/{mail-i18n.d.ts → web/mail-i18n.d.ts} +0 -0
- /package/dist/auth-mfa/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.d.ts +0 -0
- /package/dist/billing-foundation/{contact-card.d.ts → web/contact-card.d.ts} +0 -0
- /package/dist/cap-overview/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/cap-overview/{usage-math.js → web/usage-math.js} +0 -0
- /package/dist/compliance-profiles/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/config/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/custom-fields/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/delivery/{public-names.d.ts → web/public-names.d.ts} +0 -0
- /package/dist/feature-toggles/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/folders/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/form-draft/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/jobs/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/ledger/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/legal-pages/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/metrics/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/notes-history/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/personal-access-tokens/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/personal-access-tokens/{scopes.d.ts → web/scopes.d.ts} +0 -0
- /package/dist/personal-access-tokens/{scopes.js → web/scopes.js} +0 -0
- /package/dist/secrets/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/sessions/{i18n.d.ts → web/i18n.d.ts} +0 -0
- /package/dist/template-resolver/{document-steps.d.ts → web/document-steps.d.ts} +0 -0
- /package/dist/template-resolver/{mail-constants.d.ts → web/mail-constants.d.ts} +0 -0
- /package/dist/template-resolver/{pdf-constants.d.ts → web/pdf-constants.d.ts} +0 -0
- /package/dist/template-resolver/{placeholder-text.d.ts → web/placeholder-text.d.ts} +0 -0
- /package/dist/template-resolver/{placeholder-text.js → web/placeholder-text.js} +0 -0
- /package/dist/tenant/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/tier-engine/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/tier-engine/{i18n.d.ts → web/i18n.d.ts} +0 -0
- /package/dist/user/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/user-data-rights/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/user-profile/{constants.d.ts → web/constants.d.ts} +0 -0
- /package/dist/user-profile/{i18n.d.ts → web/i18n.d.ts} +0 -0
- /package/dist/waitlist/{constants.d.ts → web/constants.d.ts} +0 -0
|
@@ -7,10 +7,10 @@ import { UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
|
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { subscriptionAggregateId, terminationUnmatchedAggregateId } from "../aggregate-id.js";
|
|
9
9
|
import { resolveProviderPlugin } from "../checkout-core.js";
|
|
10
|
-
import {
|
|
11
|
-
import { CONTRACT_TERMINATION_CHANNELS, CONTRACT_TERMINATION_DECLARATION_TYPES, CONTRACT_TERMINATION_DECLARED_EVENT_QN, CONTRACT_TERMINATION_KINDS, CONTRACT_TERMINATION_REQUESTED_EVENT_QN, CONTRACT_TERMINATION_UNMATCHED_AGGREGATE_TYPE, CONTRACT_TERMINATION_UNMATCHED_EVENT_QN, contractTerminationRequestedPayloadSchema, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
10
|
+
import { CONTRACT_TERMINATION_CHANNELS, CONTRACT_TERMINATION_DECLARATION_TYPES, CONTRACT_TERMINATION_DECLARED_EVENT_QN, CONTRACT_TERMINATION_KINDS, CONTRACT_TERMINATION_REQUESTED_EVENT_QN, CONTRACT_TERMINATION_REVOKED_EVENT_QN, CONTRACT_TERMINATION_UNMATCHED_AGGREGATE_TYPE, CONTRACT_TERMINATION_UNMATCHED_EVENT_QN, contractTerminationRequestedPayloadSchema, contractTerminationRevokedPayloadSchema, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
12
11
|
import { getSubscriptionForTenant } from "../get-subscription-for-tenant.js";
|
|
13
|
-
import {
|
|
12
|
+
import { isTerminalSubscriptionStatus, SubscriptionCancelTimings } from "../web/constants.js";
|
|
13
|
+
import { CONSENT_LOCALES, FALLBACK_CONSENT_LOCALE, } from "../web/consumer-protection/consent-locale.js";
|
|
14
14
|
import { notifyOperator } from "./termination-notify.js";
|
|
15
15
|
import { isWithinWithdrawalPeriod } from "./withdrawal-period.js";
|
|
16
16
|
const REQUESTED_CANCEL_TIMINGS = [
|
|
@@ -38,6 +38,7 @@ export const declareContractTerminationSchema = z
|
|
|
38
38
|
terminationKind: z.enum(CONTRACT_TERMINATION_KINDS),
|
|
39
39
|
receivedAtIso: z.string().min(1),
|
|
40
40
|
locale: z.enum(CONSENT_LOCALES),
|
|
41
|
+
revocationTokenHash: z.string().length(64).optional(),
|
|
41
42
|
})
|
|
42
43
|
.strict();
|
|
43
44
|
export const recordUnmatchedContractTerminationSchema = z
|
|
@@ -114,6 +115,42 @@ export function createDeclareContractTerminationHandler() {
|
|
|
114
115
|
},
|
|
115
116
|
};
|
|
116
117
|
}
|
|
118
|
+
function revokedRecordResult(receivedAtIso) {
|
|
119
|
+
return {
|
|
120
|
+
isSuccess: true,
|
|
121
|
+
data: {
|
|
122
|
+
receivedAtIso,
|
|
123
|
+
effectiveAtIso: null,
|
|
124
|
+
providerCancel: "none",
|
|
125
|
+
noticeReason: null,
|
|
126
|
+
withdrawalPeriodExpired: false,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// A revocation that landed during the provider cancel found nothing to take back yet.
|
|
131
|
+
async function takeBackLateRevokedCancel(ctx, consumerProtection, args) {
|
|
132
|
+
const { payload, tenantId, receivedAtIso, providerCancel } = args;
|
|
133
|
+
// skip: nothing was cancelled at the provider, nothing to resume
|
|
134
|
+
if (providerCancel !== "period-end")
|
|
135
|
+
return;
|
|
136
|
+
const reasons = await resumeAtProvider(ctx, await getSubscriptionForTenant(ctx, tenantId));
|
|
137
|
+
// skip: resumed cleanly, the revocation notice already tells the operator
|
|
138
|
+
if (reasons.length === 0)
|
|
139
|
+
return;
|
|
140
|
+
await notifyOperator(ctx, consumerProtection, {
|
|
141
|
+
locale: payload.locale ?? FALLBACK_CONSENT_LOCALE,
|
|
142
|
+
requestId: payload.requestId,
|
|
143
|
+
receivedAtIso,
|
|
144
|
+
channel: "public",
|
|
145
|
+
declaration: {
|
|
146
|
+
declarationType: payload.declarationType,
|
|
147
|
+
terminationKind: payload.terminationKind,
|
|
148
|
+
},
|
|
149
|
+
reasons,
|
|
150
|
+
tenantId,
|
|
151
|
+
providerCancel,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
117
154
|
export function createRecordContractTerminationHandler(options, consumerProtection) {
|
|
118
155
|
return {
|
|
119
156
|
name: "record-contract-termination",
|
|
@@ -153,6 +190,10 @@ export function createRecordContractTerminationHandler(options, consumerProtecti
|
|
|
153
190
|
},
|
|
154
191
|
};
|
|
155
192
|
}
|
|
193
|
+
// A revoked public declaration never reaches the provider.
|
|
194
|
+
if (hasRevocation(stream.events, payload.requestId)) {
|
|
195
|
+
return revokedRecordResult(receivedAtIso);
|
|
196
|
+
}
|
|
156
197
|
const withdrawalPeriodExpired = payload.declarationType === "withdrawal" &&
|
|
157
198
|
payload.when === SubscriptionCancelTimings.immediately &&
|
|
158
199
|
!isWithinWithdrawalPeriod(stream.events, options.now());
|
|
@@ -173,6 +214,16 @@ export function createRecordContractTerminationHandler(options, consumerProtecti
|
|
|
173
214
|
aggregateId: subscriptionAggregateId(tenantId),
|
|
174
215
|
aggregateType: SUBSCRIPTION_AGGREGATE_TYPE,
|
|
175
216
|
});
|
|
217
|
+
// A revocation that landed during the provider call found no cancel to take back.
|
|
218
|
+
if (hasRevocation(streamAfterProviderCall.events, payload.requestId)) {
|
|
219
|
+
await takeBackLateRevokedCancel(ctx, consumerProtection, {
|
|
220
|
+
payload,
|
|
221
|
+
tenantId,
|
|
222
|
+
receivedAtIso,
|
|
223
|
+
providerCancel,
|
|
224
|
+
});
|
|
225
|
+
return revokedRecordResult(receivedAtIso);
|
|
226
|
+
}
|
|
176
227
|
await streamAfterProviderCall.appendOne({
|
|
177
228
|
type: CONTRACT_TERMINATION_REQUESTED_EVENT_QN,
|
|
178
229
|
payload: recorded,
|
|
@@ -207,6 +258,28 @@ export function createRecordContractTerminationHandler(options, consumerProtecti
|
|
|
207
258
|
},
|
|
208
259
|
};
|
|
209
260
|
}
|
|
261
|
+
export function hasRevocation(events, requestId) {
|
|
262
|
+
return events.some((e) => e.type === CONTRACT_TERMINATION_REVOKED_EVENT_QN &&
|
|
263
|
+
contractTerminationRevokedPayloadSchema.safeParse(e.payload).data?.requestId === requestId);
|
|
264
|
+
}
|
|
265
|
+
export async function resumeAtProvider(ctx, subscription) {
|
|
266
|
+
if (subscription === null || isTerminalSubscriptionStatus(subscription.status)) {
|
|
267
|
+
return ["revocation_resume_manual"];
|
|
268
|
+
}
|
|
269
|
+
const plugin = findPlugin(ctx, subscription.providerName);
|
|
270
|
+
if (!plugin?.resumeSubscription)
|
|
271
|
+
return ["revocation_resume_manual"];
|
|
272
|
+
try {
|
|
273
|
+
await plugin.resumeSubscription(ctx, {
|
|
274
|
+
providerSubscriptionId: subscription.providerSubscriptionId,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
ctx.log?.warn(`[billing-foundation:revoke-contract-termination] provider resume failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
279
|
+
return ["revocation_resume_failed"];
|
|
280
|
+
}
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
210
283
|
function findPlugin(ctx, providerName) {
|
|
211
284
|
try {
|
|
212
285
|
return resolveProviderPlugin(ctx, providerName).plugin;
|
|
@@ -8,13 +8,15 @@ import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
|
8
8
|
import * as z from "zod";
|
|
9
9
|
import { TenantQueries } from "../../tenant/index.js";
|
|
10
10
|
import { UserQueries } from "../../user/index.js";
|
|
11
|
-
import { CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE, SubscriptionCancelTimings, SubscriptionFoundationHandlers, SubscriptionFoundationQueries, } from "../constants.js";
|
|
12
11
|
import { CONTRACT_TERMINATION_DECLARATION_TYPES, CONTRACT_TERMINATION_KINDS, } from "../events.js";
|
|
13
12
|
import { purchaseRolesOf } from "../plan-catalog.js";
|
|
13
|
+
import { CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE, SubscriptionCancelTimings, SubscriptionFoundationHandlers, SubscriptionFoundationQueries, } from "../web/constants.js";
|
|
14
14
|
import { resolveConsentLocale } from "./consent-text.js";
|
|
15
|
+
import { openStoredUserEmail } from "./stored-user-email.js";
|
|
15
16
|
import { terminationReceiptVariables } from "./termination-mail.js";
|
|
16
17
|
import { notifyOperator, requireNotify } from "./termination-notify.js";
|
|
17
18
|
import { mayMailReceipt } from "./termination-receipt-limit.js";
|
|
19
|
+
import { createRevocationToken, revocationUrl } from "./termination-revoke.js";
|
|
18
20
|
const EXTRAORDINARY_REASON_MESSAGE = "reason is required for an extraordinary termination";
|
|
19
21
|
const authUserRowSchema = z.object({
|
|
20
22
|
id: z.string().min(1),
|
|
@@ -66,6 +68,7 @@ async function sendTerminationMails(ctx, consumerProtection, plan) {
|
|
|
66
68
|
terminationKind: plan.declaration.terminationKind,
|
|
67
69
|
},
|
|
68
70
|
operatorEmail: consumerProtection.operatorEmail,
|
|
71
|
+
...(plan.revokeUrl !== undefined && { revokeUrl: plan.revokeUrl }),
|
|
69
72
|
}),
|
|
70
73
|
locale: plan.locale,
|
|
71
74
|
priority: "critical",
|
|
@@ -77,7 +80,8 @@ async function sendTerminationMails(ctx, consumerProtection, plan) {
|
|
|
77
80
|
// skip: no operator notice needed for this declaration
|
|
78
81
|
if (reasons.length === 0)
|
|
79
82
|
return;
|
|
80
|
-
|
|
83
|
+
const { revokeUrl: _revokeUrl, ...noticePlan } = plan;
|
|
84
|
+
await notifyOperator(ctx, consumerProtection, { ...noticePlan, reasons });
|
|
81
85
|
}
|
|
82
86
|
// Tenants the entered email can terminate a contract for: tenants where the
|
|
83
87
|
// user holds a purchase role and the subscription is not terminal. Every identity
|
|
@@ -128,13 +132,32 @@ export function createRequestContractTerminationHandler(options, consumerProtect
|
|
|
128
132
|
const reasons = [];
|
|
129
133
|
const locale = resolveConsentLocale(payload.locale);
|
|
130
134
|
let matchedTenantId;
|
|
135
|
+
let revokeUrl;
|
|
131
136
|
const candidates = await findTerminableTenantIds(ctx, options, event.user.tenantId, payload.email);
|
|
132
137
|
const [onlyCandidate] = candidates;
|
|
133
138
|
if (candidates.length === 1 && onlyCandidate !== undefined) {
|
|
134
139
|
matchedTenantId = onlyCandidate;
|
|
135
|
-
const
|
|
136
|
-
|
|
140
|
+
const revocation = createRevocationToken();
|
|
141
|
+
const declared = await ctx.writeAs(createSystemUser(onlyCandidate), SubscriptionFoundationHandlers.declareContractTermination, {
|
|
142
|
+
requestId,
|
|
143
|
+
declarationType,
|
|
144
|
+
terminationKind,
|
|
145
|
+
receivedAtIso,
|
|
146
|
+
locale,
|
|
147
|
+
revocationTokenHash: revocation.tokenHash,
|
|
148
|
+
});
|
|
149
|
+
if (!declared.isSuccess) {
|
|
137
150
|
reasons.push("recording_failed");
|
|
151
|
+
}
|
|
152
|
+
else if (options.baseUrl !== undefined) {
|
|
153
|
+
revokeUrl = revocationUrl({
|
|
154
|
+
baseUrl: options.baseUrl,
|
|
155
|
+
locale,
|
|
156
|
+
requestId,
|
|
157
|
+
token: revocation.token,
|
|
158
|
+
tenantId: onlyCandidate,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
138
161
|
}
|
|
139
162
|
else {
|
|
140
163
|
reasons.push(candidates.length === 0 ? "unmatched" : "ambiguous");
|
|
@@ -166,6 +189,7 @@ export function createRequestContractTerminationHandler(options, consumerProtect
|
|
|
166
189
|
},
|
|
167
190
|
reasons,
|
|
168
191
|
...(matchedTenantId !== undefined && { tenantId: matchedTenantId }),
|
|
192
|
+
...(revokeUrl !== undefined && { revokeUrl }),
|
|
169
193
|
});
|
|
170
194
|
return {
|
|
171
195
|
isSuccess: true,
|
|
@@ -192,7 +216,10 @@ export function createTerminateContractHandler(options, consumerProtection) {
|
|
|
192
216
|
const caller = authUserRowSchema.safeParse(await ctx.queryAs(createSystemUser(tenantId), UserQueries.findForAuth, {
|
|
193
217
|
id: event.user.id,
|
|
194
218
|
}));
|
|
195
|
-
|
|
219
|
+
const callerEmail = caller.success && caller.data.email && caller.data.isDeleted !== true
|
|
220
|
+
? await openStoredUserEmail(caller.data.email, "billing-foundation:terminate-contract")
|
|
221
|
+
: null;
|
|
222
|
+
if (callerEmail === null) {
|
|
196
223
|
throw new InternalError({
|
|
197
224
|
message: "billing-foundation:terminate-contract: calling user has no email on record",
|
|
198
225
|
});
|
|
@@ -218,7 +245,7 @@ export function createTerminateContractHandler(options, consumerProtection) {
|
|
|
218
245
|
declaration: {
|
|
219
246
|
declarationType,
|
|
220
247
|
terminationKind,
|
|
221
|
-
email:
|
|
248
|
+
email: callerEmail,
|
|
222
249
|
...(payload.reason !== undefined && { reason: payload.reason }),
|
|
223
250
|
},
|
|
224
251
|
reasons: [
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import type { ConsumerProtectionOptions, ResolvedBillingFoundationOptions } from "../types.ts";
|
|
4
|
+
import type { ConsentLocale } from "./consent-text.ts";
|
|
5
|
+
export declare const REVOCATION_PATHS: Readonly<Record<ConsentLocale, string>>;
|
|
6
|
+
export type RevocationOutcome = "revoked" | "already-revoked" | "too-late" | "invalid";
|
|
7
|
+
export declare function createRevocationToken(): {
|
|
8
|
+
readonly token: string;
|
|
9
|
+
readonly tokenHash: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function revocationUrl(args: {
|
|
12
|
+
readonly baseUrl: string;
|
|
13
|
+
readonly locale: ConsentLocale;
|
|
14
|
+
readonly requestId: string;
|
|
15
|
+
readonly token: string;
|
|
16
|
+
readonly tenantId: string;
|
|
17
|
+
}): string;
|
|
18
|
+
export declare const revokeContractTerminationSchema: z.ZodObject<{
|
|
19
|
+
requestId: z.ZodString;
|
|
20
|
+
token: z.ZodString;
|
|
21
|
+
tenantId: z.ZodUUID;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
export declare const recordContractTerminationRevocationSchema: z.ZodObject<{
|
|
24
|
+
requestId: z.ZodString;
|
|
25
|
+
token: z.ZodString;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
export declare function createRevokeContractTerminationHandler(): WriteHandlerDef;
|
|
28
|
+
export declare function createRecordContractTerminationRevocationHandler(options: ResolvedBillingFoundationOptions, consumerProtection: ConsumerProtectionOptions): WriteHandlerDef;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// "This cancellation was not me": the signed link in the receipt mail of a
|
|
2
|
+
// matched public declaration takes the cancellation back until it takes effect.
|
|
3
|
+
// The anonymous handler only routes to the declaration's tenant; the system
|
|
4
|
+
// handler checks the token and does the work.
|
|
5
|
+
import { createHash, timingSafeEqual } from "node:crypto";
|
|
6
|
+
import { access, createSystemUser, } from "@cosmicdrift/kumiko-framework/engine";
|
|
7
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
8
|
+
import * as z from "zod";
|
|
9
|
+
import { subscriptionAggregateId } from "../aggregate-id.js";
|
|
10
|
+
import { CONTRACT_TERMINATION_DECLARED_EVENT_QN, CONTRACT_TERMINATION_REQUESTED_EVENT_QN, CONTRACT_TERMINATION_REVOKED_EVENT_QN, contractTerminationDeclaredPayloadSchema, contractTerminationRequestedPayloadSchema, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
11
|
+
import { getSubscriptionForTenant } from "../get-subscription-for-tenant.js";
|
|
12
|
+
import { SubscriptionFoundationHandlers } from "../web/constants.js";
|
|
13
|
+
import { notifyOperator } from "./termination-notify.js";
|
|
14
|
+
import { hasRevocation, resumeAtProvider } from "./termination-record.js";
|
|
15
|
+
export const REVOCATION_PATHS = {
|
|
16
|
+
de: "/legal/kuendigen/zuruecknehmen",
|
|
17
|
+
en: "/legal/cancel/revoke",
|
|
18
|
+
};
|
|
19
|
+
const TOKEN_BYTES = 32;
|
|
20
|
+
export function createRevocationToken() {
|
|
21
|
+
const token = Buffer.from(crypto.getRandomValues(new Uint8Array(TOKEN_BYTES))).toString("base64url");
|
|
22
|
+
return { token, tokenHash: hashRevocationToken(token) };
|
|
23
|
+
}
|
|
24
|
+
function hashRevocationToken(token) {
|
|
25
|
+
return createHash("sha256").update(token).digest("hex");
|
|
26
|
+
}
|
|
27
|
+
function tokenMatchesHash(token, expectedHash) {
|
|
28
|
+
const actual = Buffer.from(hashRevocationToken(token));
|
|
29
|
+
const expected = Buffer.from(expectedHash);
|
|
30
|
+
return actual.length === expected.length && timingSafeEqual(actual, expected);
|
|
31
|
+
}
|
|
32
|
+
export function revocationUrl(args) {
|
|
33
|
+
// Origin only: a baseUrl path prefix would not match the routes mounted at the root.
|
|
34
|
+
const url = new URL(REVOCATION_PATHS[args.locale], new URL(args.baseUrl).origin);
|
|
35
|
+
url.searchParams.set("r", args.requestId);
|
|
36
|
+
url.searchParams.set("t", args.token);
|
|
37
|
+
url.searchParams.set("tenant", args.tenantId);
|
|
38
|
+
return url.toString();
|
|
39
|
+
}
|
|
40
|
+
const revocationFieldsSchema = {
|
|
41
|
+
requestId: z.string().min(1).max(100),
|
|
42
|
+
token: z.string().min(1).max(200),
|
|
43
|
+
};
|
|
44
|
+
export const revokeContractTerminationSchema = z
|
|
45
|
+
.object({ ...revocationFieldsSchema, tenantId: z.uuid() })
|
|
46
|
+
.strict();
|
|
47
|
+
export const recordContractTerminationRevocationSchema = z.object(revocationFieldsSchema).strict();
|
|
48
|
+
function parseOutcome(data) {
|
|
49
|
+
const parsed = z
|
|
50
|
+
.object({ outcome: z.enum(["revoked", "already-revoked", "too-late", "invalid"]) })
|
|
51
|
+
.safeParse(data);
|
|
52
|
+
return parsed.success ? parsed.data.outcome : "invalid";
|
|
53
|
+
}
|
|
54
|
+
export function createRevokeContractTerminationHandler() {
|
|
55
|
+
return {
|
|
56
|
+
name: "revoke-contract-termination",
|
|
57
|
+
description: 'Public "this was not me" link of the § 312k receipt mail: takes a public cancellation back until it takes effect; an unknown request and a wrong token answer the same.',
|
|
58
|
+
schema: revokeContractTerminationSchema,
|
|
59
|
+
access: { roles: ["anonymous"] },
|
|
60
|
+
rateLimit: { per: "ip+handler", limit: 5, windowSeconds: 600 },
|
|
61
|
+
// The link only knows baseUrl, which may be a host that resolves no tenant; the token alone authorizes.
|
|
62
|
+
tenantlessAnonymous: true,
|
|
63
|
+
escapeHatch: {
|
|
64
|
+
reason: "Anonymous revoker has no session — writes as the system user of the tenant named in the link; only a declared event in that tenant whose revocationTokenHash matches the link token lets the revocation through, every other case answers the same generic invalid.",
|
|
65
|
+
},
|
|
66
|
+
handler: async (event, ctx) => {
|
|
67
|
+
// @cast-boundary engine-payload — dispatcher-zod-validated payload
|
|
68
|
+
const payload = event.payload;
|
|
69
|
+
const result = await ctx.writeAs(createSystemUser(payload.tenantId), SubscriptionFoundationHandlers.recordContractTerminationRevocation, { requestId: payload.requestId, token: payload.token });
|
|
70
|
+
return {
|
|
71
|
+
isSuccess: true,
|
|
72
|
+
data: { outcome: result.isSuccess ? parseOutcome(result.data) : "invalid" },
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function createRecordContractTerminationRevocationHandler(options, consumerProtection) {
|
|
78
|
+
return {
|
|
79
|
+
name: "record-contract-termination-revocation",
|
|
80
|
+
agent: { expose: false },
|
|
81
|
+
schema: recordContractTerminationRevocationSchema,
|
|
82
|
+
access: { roles: access.system },
|
|
83
|
+
handler: async (event, ctx) => {
|
|
84
|
+
// @cast-boundary engine-payload — dispatcher-zod-validated payload
|
|
85
|
+
const payload = event.payload;
|
|
86
|
+
const tenantId = event.user.tenantId;
|
|
87
|
+
const outcome = (value) => ({
|
|
88
|
+
isSuccess: true,
|
|
89
|
+
data: { outcome: value },
|
|
90
|
+
});
|
|
91
|
+
const stream = await ctx.fetchForWriting({
|
|
92
|
+
aggregateId: subscriptionAggregateId(tenantId),
|
|
93
|
+
aggregateType: SUBSCRIPTION_AGGREGATE_TYPE,
|
|
94
|
+
});
|
|
95
|
+
const declared = stream.events
|
|
96
|
+
.filter((e) => e.type === CONTRACT_TERMINATION_DECLARED_EVENT_QN)
|
|
97
|
+
.map((e) => contractTerminationDeclaredPayloadSchema.safeParse(e.payload).data)
|
|
98
|
+
.find((candidate) => candidate?.requestId === payload.requestId);
|
|
99
|
+
if (declared?.revocationTokenHash === undefined ||
|
|
100
|
+
!tokenMatchesHash(payload.token, declared.revocationTokenHash)) {
|
|
101
|
+
return outcome("invalid");
|
|
102
|
+
}
|
|
103
|
+
if (hasRevocation(stream.events, payload.requestId))
|
|
104
|
+
return outcome("already-revoked");
|
|
105
|
+
const requested = stream.events
|
|
106
|
+
.filter((e) => e.type === CONTRACT_TERMINATION_REQUESTED_EVENT_QN)
|
|
107
|
+
.map((e) => contractTerminationRequestedPayloadSchema.safeParse(e.payload).data)
|
|
108
|
+
.find((candidate) => candidate?.requestId === payload.requestId);
|
|
109
|
+
const subscription = await getSubscriptionForTenant(ctx, tenantId);
|
|
110
|
+
const effectiveAtIso = requested?.effectiveAtIso ?? subscription?.currentPeriodEnd.toString();
|
|
111
|
+
const now = options.now();
|
|
112
|
+
if (effectiveAtIso !== undefined &&
|
|
113
|
+
Temporal.Instant.compare(now, Temporal.Instant.from(effectiveAtIso)) >= 0) {
|
|
114
|
+
return outcome("too-late");
|
|
115
|
+
}
|
|
116
|
+
const reasons = ["revoked"];
|
|
117
|
+
if (requested?.providerCancel === "period-end") {
|
|
118
|
+
reasons.push(...(await resumeAtProvider(ctx, subscription)));
|
|
119
|
+
}
|
|
120
|
+
// Re-fetch after the external call, like record-contract-termination.
|
|
121
|
+
const streamAfterProviderCall = await ctx.fetchForWriting({
|
|
122
|
+
aggregateId: subscriptionAggregateId(tenantId),
|
|
123
|
+
aggregateType: SUBSCRIPTION_AGGREGATE_TYPE,
|
|
124
|
+
});
|
|
125
|
+
const revoked = {
|
|
126
|
+
requestId: payload.requestId,
|
|
127
|
+
revokedAtIso: now.toString(),
|
|
128
|
+
};
|
|
129
|
+
await streamAfterProviderCall.appendOne({
|
|
130
|
+
type: CONTRACT_TERMINATION_REVOKED_EVENT_QN,
|
|
131
|
+
payload: revoked,
|
|
132
|
+
});
|
|
133
|
+
await notifyOperator(ctx, consumerProtection, {
|
|
134
|
+
locale: declared.locale,
|
|
135
|
+
requestId: declared.requestId,
|
|
136
|
+
receivedAtIso: declared.receivedAtIso,
|
|
137
|
+
channel: "public",
|
|
138
|
+
declaration: {
|
|
139
|
+
declarationType: declared.declarationType,
|
|
140
|
+
terminationKind: declared.terminationKind,
|
|
141
|
+
},
|
|
142
|
+
reasons,
|
|
143
|
+
tenantId,
|
|
144
|
+
...(requested !== undefined && { providerCancel: requested.providerCancel }),
|
|
145
|
+
});
|
|
146
|
+
return outcome("revoked");
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
@@ -16,6 +16,8 @@ export type TerminationTexts = {
|
|
|
16
16
|
readonly receiptIntro: string;
|
|
17
17
|
readonly receiptNextSteps: string;
|
|
18
18
|
readonly receiptRevoke: (operatorEmail: string) => string;
|
|
19
|
+
readonly receiptNotMe: string;
|
|
20
|
+
readonly receiptNotMeLink: string;
|
|
19
21
|
readonly contact: string;
|
|
20
22
|
readonly operatorSubject: Readonly<Record<ContractTerminationDeclarationType, string>>;
|
|
21
23
|
readonly operatorIntro: string;
|
|
@@ -57,7 +59,21 @@ export type PageTexts = {
|
|
|
57
59
|
readonly errorGeneric: string;
|
|
58
60
|
readonly rateLimitedTitle: string;
|
|
59
61
|
readonly rateLimitedBody: string;
|
|
62
|
+
readonly revoke: RevokePageTexts;
|
|
60
63
|
};
|
|
61
|
-
export
|
|
64
|
+
export type RevokePageTexts = {
|
|
65
|
+
readonly confirmTitle: string;
|
|
66
|
+
readonly confirmLead: string;
|
|
67
|
+
readonly confirmButton: string;
|
|
68
|
+
readonly revokedTitle: string;
|
|
69
|
+
readonly revokedBody: string;
|
|
70
|
+
readonly alreadyRevokedTitle: string;
|
|
71
|
+
readonly alreadyRevokedBody: string;
|
|
72
|
+
readonly tooLateTitle: string;
|
|
73
|
+
readonly tooLateBody: string;
|
|
74
|
+
readonly invalidTitle: string;
|
|
75
|
+
readonly invalidBody: string;
|
|
76
|
+
};
|
|
77
|
+
export declare const OPERATOR_NOTICE_REASONS: readonly ["unmatched", "ambiguous", "withdrawal", "extraordinary", "provider_cannot_cancel", "provider_error", "no_active_subscription", "recording_failed", "withdrawal_period_expired", "receipt_rate_limited", "revoked", "revocation_resume_manual", "revocation_resume_failed"];
|
|
62
78
|
export type OperatorNoticeReason = (typeof OPERATOR_NOTICE_REASONS)[number];
|
|
63
79
|
export declare const TERMINATION_TEXTS: Readonly<Record<ConsentLocale, TerminationTexts>>;
|
|
@@ -9,6 +9,9 @@ export const OPERATOR_NOTICE_REASONS = [
|
|
|
9
9
|
"recording_failed",
|
|
10
10
|
"withdrawal_period_expired",
|
|
11
11
|
"receipt_rate_limited",
|
|
12
|
+
"revoked",
|
|
13
|
+
"revocation_resume_manual",
|
|
14
|
+
"revocation_resume_failed",
|
|
12
15
|
];
|
|
13
16
|
export const TERMINATION_TEXTS = {
|
|
14
17
|
de: {
|
|
@@ -33,6 +36,8 @@ export const TERMINATION_TEXTS = {
|
|
|
33
36
|
receiptIntro: "wir bestätigen den Eingang deiner Erklärung mit folgendem Inhalt. Diese E-Mail ist eine Eingangsbestätigung, keine Bestätigung der Wirksamkeit.",
|
|
34
37
|
receiptNextSteps: "Wir prüfen deine Erklärung und melden uns, sobald sie bearbeitet ist oder wir Rückfragen haben.",
|
|
35
38
|
receiptRevoke: (operatorEmail) => `Hast du diese Erklärung nicht abgegeben oder möchtest du sie zurücknehmen? Schreib uns bitte umgehend an ${operatorEmail}.`,
|
|
39
|
+
receiptNotMe: "Wurde diese Erklärung nicht von dir abgegeben? Dann nimm die Kündigung bis zu ihrem Wirksamwerden hier zurück:",
|
|
40
|
+
receiptNotMeLink: "Diese Kündigung war ich nicht",
|
|
36
41
|
contact: "Fragen richtest du bitte an",
|
|
37
42
|
operatorSubject: {
|
|
38
43
|
termination: "Kündigung: Bearbeitung nötig",
|
|
@@ -50,6 +55,9 @@ export const TERMINATION_TEXTS = {
|
|
|
50
55
|
recording_failed: "Die Erklärung konnte nicht gespeichert werden",
|
|
51
56
|
withdrawal_period_expired: "Widerruf nach Ablauf der Widerrufsfrist: zum Periodenende gekündigt, Anspruch prüfen",
|
|
52
57
|
receipt_rate_limited: "Keine Eingangsbestätigung versendet: Limit pro Empfängeradresse erreicht",
|
|
58
|
+
revoked: "Die Erklärung wurde vom Postfachinhaber über „Diese Kündigung war ich nicht“ zurückgenommen",
|
|
59
|
+
revocation_resume_manual: "Die Kündigung beim Zahlungsanbieter bitte manuell zurücknehmen (keine Schnittstelle dafür)",
|
|
60
|
+
revocation_resume_failed: "Die Kündigung beim Zahlungsanbieter konnte nicht zurückgenommen werden, bitte manuell zurücknehmen",
|
|
53
61
|
},
|
|
54
62
|
noticeReasons: "Grund der Benachrichtigung",
|
|
55
63
|
channel: "Kanal",
|
|
@@ -90,6 +98,19 @@ export const TERMINATION_TEXTS = {
|
|
|
90
98
|
errorGeneric: "Deine Erklärung konnte nicht verarbeitet werden. Bitte versuch es erneut.",
|
|
91
99
|
rateLimitedTitle: "Zu viele Anfragen",
|
|
92
100
|
rateLimitedBody: "Von deiner Adresse kamen zu viele Anfragen. Bitte versuch es später erneut.",
|
|
101
|
+
revoke: {
|
|
102
|
+
confirmTitle: "Kündigung zurücknehmen?",
|
|
103
|
+
confirmLead: "Mit dem Klick auf den Button unten nimmst du die Kündigung zurück. Dein Vertrag läuft dann weiter.",
|
|
104
|
+
confirmButton: "Diese Kündigung war ich nicht",
|
|
105
|
+
revokedTitle: "Die Kündigung ist zurückgenommen",
|
|
106
|
+
revokedBody: "Dein Vertrag läuft weiter. Wir haben den Betreiber informiert.",
|
|
107
|
+
alreadyRevokedTitle: "Schon zurückgenommen",
|
|
108
|
+
alreadyRevokedBody: "Diese Kündigung wurde bereits zurückgenommen.",
|
|
109
|
+
tooLateTitle: "Zu spät für die Rücknahme",
|
|
110
|
+
tooLateBody: "Die Kündigung ist bereits wirksam geworden. Bitte schreib dem Betreiber, die Adresse steht in der Eingangsbestätigung.",
|
|
111
|
+
invalidTitle: "Link ungültig",
|
|
112
|
+
invalidBody: "Dieser Link ist ungültig oder abgelaufen. Bitte schreib dem Betreiber, die Adresse steht in der Eingangsbestätigung.",
|
|
113
|
+
},
|
|
93
114
|
},
|
|
94
115
|
},
|
|
95
116
|
en: {
|
|
@@ -114,6 +135,8 @@ export const TERMINATION_TEXTS = {
|
|
|
114
135
|
receiptIntro: "We confirm receipt of your declaration with the following content. This email is a receipt, not a confirmation that the declaration is effective.",
|
|
115
136
|
receiptNextSteps: "We will review your declaration and get back to you once it is processed or if we have questions.",
|
|
116
137
|
receiptRevoke: (operatorEmail) => `If you did not make this declaration or want to take it back, please write to ${operatorEmail} right away.`,
|
|
138
|
+
receiptNotMe: "Did you not make this declaration? Then take the termination back here until it takes effect:",
|
|
139
|
+
receiptNotMeLink: "I did not request this cancellation",
|
|
117
140
|
contact: "Questions go to",
|
|
118
141
|
operatorSubject: {
|
|
119
142
|
termination: "Termination: action needed",
|
|
@@ -131,6 +154,9 @@ export const TERMINATION_TEXTS = {
|
|
|
131
154
|
recording_failed: "The declaration could not be stored",
|
|
132
155
|
withdrawal_period_expired: "Withdrawal after the withdrawal period: cancelled at period end, review the claim",
|
|
133
156
|
receipt_rate_limited: "No receipt mail sent: the per-recipient limit was reached",
|
|
157
|
+
revoked: 'The declaration was taken back by the mailbox owner ("I did not request this cancellation")',
|
|
158
|
+
revocation_resume_manual: "Undo the cancellation at the payment provider manually (no API for it)",
|
|
159
|
+
revocation_resume_failed: "Undoing the cancellation at the payment provider failed, undo it manually",
|
|
134
160
|
},
|
|
135
161
|
noticeReasons: "Reason for this notice",
|
|
136
162
|
channel: "Channel",
|
|
@@ -171,6 +197,19 @@ export const TERMINATION_TEXTS = {
|
|
|
171
197
|
errorGeneric: "Your declaration could not be processed. Please try again.",
|
|
172
198
|
rateLimitedTitle: "Too many requests",
|
|
173
199
|
rateLimitedBody: "Too many requests came from your address. Please try again later.",
|
|
200
|
+
revoke: {
|
|
201
|
+
confirmTitle: "Take the cancellation back?",
|
|
202
|
+
confirmLead: "Click the button below to take the cancellation back. Your contract then continues.",
|
|
203
|
+
confirmButton: "I did not request this cancellation",
|
|
204
|
+
revokedTitle: "The cancellation was taken back",
|
|
205
|
+
revokedBody: "Your contract continues. We informed the operator.",
|
|
206
|
+
alreadyRevokedTitle: "Already taken back",
|
|
207
|
+
alreadyRevokedBody: "This cancellation was already taken back.",
|
|
208
|
+
tooLateTitle: "Too late to take it back",
|
|
209
|
+
tooLateBody: "The cancellation has already taken effect. Please write to the operator, the address is in the receipt.",
|
|
210
|
+
invalidTitle: "Invalid link",
|
|
211
|
+
invalidBody: "This link is invalid or has expired. Please write to the operator, the address is in the receipt.",
|
|
212
|
+
},
|
|
174
213
|
},
|
|
175
214
|
},
|
|
176
215
|
};
|
|
@@ -25,6 +25,7 @@ export declare const subscriptionEventPayloadSchema: z.ZodObject<{
|
|
|
25
25
|
currentPeriodEndIso: z.ZodString;
|
|
26
26
|
cancelAtIso: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
27
27
|
consentId: z.ZodOptional<z.ZodString>;
|
|
28
|
+
providerEventAtIso: z.ZodOptional<z.ZodISODateTime>;
|
|
28
29
|
}, z.core.$strip>;
|
|
29
30
|
export type SubscriptionEventPayload = z.infer<typeof subscriptionEventPayloadSchema>;
|
|
30
31
|
export type SubscriptionEventHeaders = {
|
|
@@ -127,8 +128,16 @@ export declare const contractTerminationDeclaredPayloadSchema: z.ZodObject<{
|
|
|
127
128
|
de: "de";
|
|
128
129
|
en: "en";
|
|
129
130
|
}>;
|
|
131
|
+
revocationTokenHash: z.ZodOptional<z.ZodString>;
|
|
130
132
|
}, z.core.$strip>;
|
|
131
133
|
export type ContractTerminationDeclaredPayload = z.infer<typeof contractTerminationDeclaredPayloadSchema>;
|
|
134
|
+
export declare const CONTRACT_TERMINATION_REVOKED_EVENT_SHORT: "contract-termination-revoked";
|
|
135
|
+
export declare const CONTRACT_TERMINATION_REVOKED_EVENT_QN: "billing-foundation:event:contract-termination-revoked";
|
|
136
|
+
export declare const contractTerminationRevokedPayloadSchema: z.ZodObject<{
|
|
137
|
+
requestId: z.ZodString;
|
|
138
|
+
revokedAtIso: z.ZodString;
|
|
139
|
+
}, z.core.$strip>;
|
|
140
|
+
export type ContractTerminationRevokedPayload = z.infer<typeof contractTerminationRevokedPayloadSchema>;
|
|
132
141
|
export declare const CONTRACT_TERMINATION_UNMATCHED_AGGREGATE_TYPE: "contract-termination-unmatched";
|
|
133
142
|
export declare const CONTRACT_TERMINATION_UNMATCHED_EVENT_SHORT: "contract-termination-unmatched";
|
|
134
143
|
export declare const CONTRACT_TERMINATION_UNMATCHED_EVENT_QN: "billing-foundation:event:contract-termination-unmatched";
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// accounting-export, churn-analytics) listenen direkt auf den event-
|
|
11
11
|
// type ohne payload-discriminator.
|
|
12
12
|
import * as z from "zod";
|
|
13
|
-
import { BILLING_FOUNDATION_FEATURE, SubscriptionStatuses } from "./constants.js";
|
|
14
|
-
import { CONSENT_LOCALES } from "./consumer-protection/consent-locale.js";
|
|
13
|
+
import { BILLING_FOUNDATION_FEATURE, SubscriptionStatuses } from "./web/constants.js";
|
|
14
|
+
import { CONSENT_LOCALES } from "./web/consumer-protection/consent-locale.js";
|
|
15
15
|
// Aggregate-type für den event-store. Eine subscription pro Tenant ist
|
|
16
16
|
// ein stream; der subscriptionAggregateId-helper liefert die stream-id.
|
|
17
17
|
export const SUBSCRIPTION_AGGREGATE_TYPE = "subscription";
|
|
@@ -56,6 +56,8 @@ export const subscriptionEventPayloadSchema = z.object({
|
|
|
56
56
|
// doesn't report cancelAt at all — projection.ts tells the two apart.
|
|
57
57
|
cancelAtIso: z.string().min(1).nullable().optional(),
|
|
58
58
|
consentId: z.string().min(1).max(100).optional(),
|
|
59
|
+
// When the provider emitted the event; lets process-event drop late deliveries.
|
|
60
|
+
providerEventAtIso: z.iso.datetime().optional(),
|
|
59
61
|
});
|
|
60
62
|
// =============================================================================
|
|
61
63
|
// payment-received — one-off-payments (checkout mode "payment")
|
|
@@ -151,6 +153,16 @@ export const contractTerminationDeclaredPayloadSchema = z.object({
|
|
|
151
153
|
terminationKind: z.enum(CONTRACT_TERMINATION_KINDS),
|
|
152
154
|
receivedAtIso: z.string().min(1),
|
|
153
155
|
locale: z.enum(CONSENT_LOCALES),
|
|
156
|
+
// sha256 hex of the "this was not me" link token; events written before the
|
|
157
|
+
// link existed carry none and cannot be revoked.
|
|
158
|
+
revocationTokenHash: z.string().length(64).optional(),
|
|
159
|
+
});
|
|
160
|
+
// The mailbox owner took a public declaration back ("this was not me").
|
|
161
|
+
export const CONTRACT_TERMINATION_REVOKED_EVENT_SHORT = "contract-termination-revoked";
|
|
162
|
+
export const CONTRACT_TERMINATION_REVOKED_EVENT_QN = `${BILLING_FOUNDATION_FEATURE}:event:${CONTRACT_TERMINATION_REVOKED_EVENT_SHORT}`;
|
|
163
|
+
export const contractTerminationRevokedPayloadSchema = z.object({
|
|
164
|
+
requestId: z.string().min(1).max(100),
|
|
165
|
+
revokedAtIso: z.string().min(1),
|
|
154
166
|
});
|
|
155
167
|
export const CONTRACT_TERMINATION_UNMATCHED_AGGREGATE_TYPE = "contract-termination-unmatched";
|
|
156
168
|
export const CONTRACT_TERMINATION_UNMATCHED_EVENT_SHORT = "contract-termination-unmatched";
|
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
// `subscription-provider-changed`-event-type später.
|
|
52
52
|
import { defineFeature, EXT_TENANT_DATA, } from "@cosmicdrift/kumiko-framework/engine";
|
|
53
53
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
54
|
-
import { BILLING_FOUNDATION_FEATURE, SUBSCRIPTION_PROVIDER_EXTENSION, SubscriptionFoundationHandlers, } from "./constants.js";
|
|
55
54
|
import { registerConsumerProtection } from "./consumer-protection/register-consent.js";
|
|
56
55
|
import { paymentEntity, subscriptionEntity } from "./entities.js";
|
|
57
56
|
import { INVOICE_PAID_EVENT_QN, INVOICE_PAID_EVENT_SHORT, INVOICE_PAYMENT_FAILED_EVENT_QN, INVOICE_PAYMENT_FAILED_EVENT_SHORT, PAYMENT_AGGREGATE_TYPE, PAYMENT_RECEIVED_EVENT_QN, PAYMENT_RECEIVED_EVENT_SHORT, paymentEventPayloadSchema, SUBSCRIPTION_AGGREGATE_TYPE, SUBSCRIPTION_CANCELED_EVENT_QN, SUBSCRIPTION_CANCELED_EVENT_SHORT, SUBSCRIPTION_CREATED_EVENT_QN, SUBSCRIPTION_CREATED_EVENT_SHORT, SUBSCRIPTION_UPDATED_EVENT_QN, SUBSCRIPTION_UPDATED_EVENT_SHORT, subscriptionEventPayloadSchema, } from "./events.js";
|
|
@@ -69,6 +68,7 @@ import { applyInvoicePaid, applyInvoicePaymentFailed, applyPaymentReceived, appl
|
|
|
69
68
|
import { createBillingPlansScreen } from "./screens.js";
|
|
70
69
|
import { PAYMENT_TENANT_DESTROY_ARCHIVE_REASON, paymentTenantDestroyHook, SUBSCRIPTION_TENANT_DESTROY_ARCHIVE_REASON, subscriptionTenantDestroyHook, } from "./tenant-destroy-hook.js";
|
|
71
70
|
import { validateOptions } from "./validate-options.js";
|
|
71
|
+
import { BILLING_FOUNDATION_FEATURE, SUBSCRIPTION_PROVIDER_EXTENSION, SubscriptionFoundationHandlers, } from "./web/constants.js";
|
|
72
72
|
export function createBillingFoundationFeature(options = {}) {
|
|
73
73
|
validateOptions(options);
|
|
74
74
|
// Handlers take the widened, string-tiered options — `TTier` only exists
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HandlerContext, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
3
|
import * as z from "zod";
|
|
3
4
|
export declare const processEventSchema: z.ZodObject<{
|
|
4
5
|
providerEventId: z.ZodString;
|
|
@@ -22,11 +23,14 @@ export declare const processEventSchema: z.ZodObject<{
|
|
|
22
23
|
tier: z.ZodString;
|
|
23
24
|
currentPeriodEndIso: z.ZodString;
|
|
24
25
|
cancelAtIso: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
26
|
+
providerEventAtIso: z.ZodOptional<z.ZodISODateTime>;
|
|
25
27
|
consentId: z.ZodOptional<z.ZodString>;
|
|
26
28
|
}, z.core.$strip>;
|
|
27
29
|
export type ProcessEventPayload = z.infer<typeof processEventSchema>;
|
|
28
|
-
export declare function
|
|
30
|
+
export declare function clampProviderEventAt(payload: ProcessEventPayload, now: Temporal.Instant): ProcessEventPayload;
|
|
31
|
+
export declare function appendSubscriptionEvent(ctx: HandlerContext, tenantId: string, rawPayload: ProcessEventPayload, now?: Temporal.Instant): Promise<{
|
|
29
32
|
readonly duplicate: boolean;
|
|
33
|
+
readonly stale?: true;
|
|
30
34
|
readonly subscriptionAggregateId: string;
|
|
31
35
|
}>;
|
|
32
36
|
export declare function createProcessEventHandler(now: () => Temporal.Instant): WriteHandlerDef;
|