@cosmicdrift/kumiko-bundled-features 0.362.0 → 0.364.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/admin-shell/feature.d.ts +3 -0
- package/dist/admin-shell/feature.js +6 -1
- package/dist/agent-tools/agent-manifest.js +2 -1
- package/dist/agent-tools/filter-ops.d.ts +1 -1
- package/dist/agent-tools/filter-ops.js +1 -3
- package/dist/agent-tools/tool-dispatch.js +2 -1
- package/dist/audit/handlers/list.query.js +9 -5
- package/dist/auth-email-password/bootstrap.d.ts +8 -5
- package/dist/auth-email-password/bootstrap.js +12 -4
- package/dist/auth-email-password/email-rate-limits.d.ts +4 -0
- package/dist/auth-email-password/email-rate-limits.js +13 -0
- package/dist/auth-email-password/email-templates.d.ts +4 -26
- package/dist/auth-email-password/email-templates.js +9 -101
- package/dist/auth-email-password/feature.js +24 -6
- package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +6 -2
- package/dist/auth-email-password/handlers/confirm-account-unlock.write.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-accept.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-create.write.js +4 -4
- 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/logout.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/logout.write.js +6 -2
- package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.js +2 -4
- package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.js +2 -4
- package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.js +2 -4
- package/dist/auth-email-password/handlers/reset-password.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-confirm.write.js +3 -4
- package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.js +2 -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 -3
- package/dist/auth-email-password/handlers/token-request-handler.js +2 -2
- package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
- package/dist/auth-email-password/index.d.ts +2 -2
- package/dist/auth-email-password/index.js +1 -1
- package/dist/auth-email-password/magic-link-mail.d.ts +3 -2
- package/dist/auth-email-password/magic-link-mail.js +19 -14
- package/dist/auth-email-password/mail-notifications.d.ts +32 -0
- package/dist/auth-email-password/mail-notifications.js +116 -0
- package/dist/auth-email-password/signup-activation.d.ts +1 -1
- package/dist/auth-email-password/signup-activation.js +2 -3
- package/dist/auth-email-password/web/auth-gate.js +16 -4
- package/dist/auth-foundation/types.js +2 -8
- package/dist/auth-mfa/feature.js +4 -4
- package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
- package/dist/auth-mfa/hmac-token-codec.js +4 -4
- package/dist/auth-mfa/mfa-challenge-token.js +3 -3
- package/dist/auth-mfa/mfa-preauth-setup-token.js +3 -3
- package/dist/auth-mfa/mfa-setup-token.js +8 -8
- package/dist/billing-foundation/constants.d.ts +3 -3
- package/dist/billing-foundation/constants.js +5 -4
- package/dist/billing-foundation/consumer-protection/confirmation-mail.d.ts +32 -14
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +74 -32
- package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +3 -0
- package/dist/billing-foundation/consumer-protection/consent-gate.js +21 -2
- package/dist/billing-foundation/consumer-protection/issue-confirmation.js +3 -3
- package/dist/billing-foundation/consumer-protection/mail-notifications.d.ts +8 -0
- package/dist/billing-foundation/consumer-protection/mail-notifications.js +95 -0
- package/dist/billing-foundation/consumer-protection/register-consent.js +2 -0
- package/dist/billing-foundation/consumer-protection/register-termination.js +11 -1
- package/dist/billing-foundation/consumer-protection/termination-mail.d.ts +25 -13
- package/dist/billing-foundation/consumer-protection/termination-mail.js +11 -23
- package/dist/billing-foundation/consumer-protection/termination-notify.js +2 -2
- package/dist/billing-foundation/consumer-protection/termination-pages.js +1 -3
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +6 -0
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +34 -0
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +2 -0
- package/dist/billing-foundation/consumer-protection/termination-record.js +7 -1
- package/dist/billing-foundation/consumer-protection/termination-request.js +31 -21
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/termination-texts.js +6 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +10 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.js +26 -0
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +11 -5
- package/dist/billing-foundation/handlers/process-event.write.js +12 -8
- package/dist/billing-foundation/handlers/process-payment-event.write.js +1 -1
- package/dist/billing-foundation/i18n.js +3 -0
- package/dist/billing-foundation/subscription-tier-sync.d.ts +7 -1
- package/dist/billing-foundation/subscription-tier-sync.js +16 -9
- package/dist/billing-foundation/types.d.ts +7 -2
- package/dist/cap-counter/calendar-cap-usage-reservation.js +2 -0
- package/dist/cap-counter/enforce-cap.d.ts +18 -1
- package/dist/cap-counter/enforce-cap.js +49 -6
- package/dist/cap-counter/index.d.ts +1 -1
- package/dist/cap-counter/index.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +2 -0
- package/dist/cap-overview/handlers/tenant-caps-list.query.js +2 -1
- package/dist/cap-overview/web/cap-usage-cell.js +5 -4
- package/dist/channel-email/email-channel.d.ts +2 -2
- package/dist/channel-email/email-channel.js +101 -26
- package/dist/channel-email/feature.js +3 -3
- package/dist/channel-email/index.d.ts +1 -1
- package/dist/channel-email/index.js +1 -1
- package/dist/channel-email/pii-guard.js +10 -0
- package/dist/channel-email/smtp-transport.js +13 -0
- package/dist/channel-email/types.d.ts +8 -0
- package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
- package/dist/config/handlers/reset.write.d.ts +1 -1
- package/dist/config/handlers/set.write.d.ts +1 -1
- package/dist/config/handlers/set.write.js +3 -4
- package/dist/config/resolver.d.ts +1 -0
- package/dist/config/resolver.js +11 -14
- package/dist/config/write-helpers.d.ts +2 -0
- package/dist/config/write-helpers.js +19 -0
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.js +29 -19
- package/dist/custom-fields/handlers/update-tenant-field.write.js +0 -1
- package/dist/custom-fields/lib/value-schema.js +10 -11
- package/dist/custom-fields/wire-user-data-rights.js +7 -6
- package/dist/data-retention/index.d.ts +1 -0
- package/dist/data-retention/index.js +1 -0
- package/dist/data-retention/run-retention-cleanup.js +6 -6
- package/dist/delivery/attachment-ref.d.ts +41 -0
- package/dist/delivery/attachment-ref.js +78 -0
- package/dist/delivery/channel-context.d.ts +8 -4
- package/dist/delivery/channel-context.js +94 -2
- package/dist/delivery/constants.d.ts +1 -0
- package/dist/delivery/constants.js +1 -0
- package/dist/delivery/delivery-service.d.ts +4 -1
- package/dist/delivery/delivery-service.js +38 -32
- package/dist/delivery/feature.js +1 -1
- package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
- package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
- package/dist/delivery/index.d.ts +5 -2
- package/dist/delivery/index.js +4 -1
- package/dist/delivery/jobs.js +66 -14
- package/dist/delivery/notify-factory.js +4 -1
- package/dist/delivery/testing.d.ts +4 -1
- package/dist/delivery/types.d.ts +26 -14
- package/dist/delivery/unsubscribe.js +4 -1
- package/dist/derivatives-sharp/render.js +1 -18
- package/dist/document-ingest-foundation/pages.js +4 -4
- package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
- package/dist/feature-toggles/toggle-sync-signal.js +4 -4
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-foundation/index.d.ts +1 -0
- package/dist/file-foundation/index.js +1 -0
- package/dist/file-foundation/read-file-ref-content.d.ts +27 -0
- package/dist/file-foundation/read-file-ref-content.js +51 -0
- package/dist/files-tenant-data/hooks.js +4 -0
- package/dist/folders/web/folder-manager.js +3 -2
- package/dist/form-draft/db/queries/cleanup.js +4 -4
- package/dist/form-draft/db/queries/draft-count.js +2 -2
- package/dist/form-draft/db/queries/owned-file-refs.js +2 -2
- package/dist/form-draft/handlers/discard.write.d.ts +1 -1
- package/dist/form-draft/handlers/save.write.d.ts +1 -1
- package/dist/form-draft/release-file-refs.js +3 -2
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +1 -1
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +6 -6
- package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +1 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +8 -3
- package/dist/inbound-mail-foundation/oauth-state.js +7 -7
- package/dist/inbound-mail-foundation/types.js +4 -4
- package/dist/inbound-mail-foundation/watch-supervisor.js +24 -13
- package/dist/inbound-provider-imap/imap-client.js +4 -3
- package/dist/jobs/db/queries/stale-run-sweep.d.ts +1 -1
- package/dist/jobs/db/queries/stale-run-sweep.js +12 -5
- package/dist/jobs/feature.js +5 -3
- package/dist/jobs/handlers/list.query.js +3 -1
- package/dist/jobs/handlers/retry.write.d.ts +1 -1
- package/dist/jobs/handlers/stale-run-sweep.job.d.ts +1 -1
- package/dist/jobs/handlers/stale-run-sweep.job.js +2 -2
- package/dist/jobs/handlers/trigger.write.d.ts +1 -1
- package/dist/jobs/job-run-logger.js +32 -10
- package/dist/jobs/tenant-job-run-table.js +3 -2
- package/dist/ledger/entity.js +3 -1
- package/dist/ledger/recurring.js +1 -3
- package/dist/managed-pages/branding.d.ts +2 -0
- package/dist/managed-pages/branding.js +24 -2
- package/dist/managed-pages/feature.js +1 -0
- package/dist/managed-pages/handlers/set.write.d.ts +1 -1
- package/dist/managed-pages/i18n.js +1 -0
- package/dist/managed-pages/screens/branding-screen.js +8 -1
- package/dist/page-render/branding.d.ts +1 -0
- package/dist/page-render/branding.js +1 -0
- package/dist/page-render/markdown.js +1 -1
- package/dist/personal-access-tokens/feature.js +1 -1
- package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
- package/dist/personal-access-tokens/handlers/list.query.js +2 -1
- package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
- package/dist/personal-access-tokens/revoke-for-user.js +2 -1
- package/dist/renderer-foundation/api.d.ts +13 -13
- package/dist/renderer-foundation/api.js +1 -1
- package/dist/renderer-foundation/constants.js +2 -4
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/renderer-foundation/index.d.ts +2 -1
- package/dist/renderer-foundation/index.js +1 -0
- package/dist/renderer-foundation/types.d.ts +94 -32
- package/dist/renderer-pdf/feature.js +7 -1
- package/dist/renderer-pdf/render-table-pdf.d.ts +27 -33
- package/dist/renderer-pdf/render-table-pdf.js +95 -34
- package/dist/secrets/feature.js +4 -3
- package/dist/secrets/handlers/delete.write.d.ts +1 -1
- package/dist/secrets/handlers/set.write.d.ts +1 -1
- package/dist/secrets/secrets-context.js +15 -3
- package/dist/sessions/db/queries/cleanup.js +2 -2
- package/dist/sessions/feature.js +1 -1
- package/dist/sessions/handlers/list.query.js +2 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke.write.d.ts +1 -1
- package/dist/shared/attachment-file-name.d.ts +3 -0
- package/dist/shared/attachment-file-name.js +35 -0
- package/dist/shared/chunked-entity-migration.d.ts +1 -0
- package/dist/shared/chunked-entity-migration.js +1 -1
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/is-tenant-db.js +1 -1
- package/dist/shared/mail-template-body.d.ts +7 -0
- package/dist/shared/mail-template-body.js +27 -0
- package/dist/shared/sharp-input-limits.d.ts +6 -0
- package/dist/shared/sharp-input-limits.js +22 -0
- package/dist/shared/signup-handover.js +2 -2
- package/dist/subscription-stripe/plugin-methods.js +18 -8
- package/dist/subscription-stripe/verify-webhook.d.ts +1 -1
- package/dist/tags/handlers/assign-tag.write.js +3 -1
- package/dist/tags/web/tag-chip.js +2 -0
- package/dist/template-resolver/api.d.ts +30 -2
- package/dist/template-resolver/api.js +42 -6
- package/dist/template-resolver/compile-document-body.d.ts +12 -0
- package/dist/template-resolver/compile-document-body.js +205 -0
- package/dist/template-resolver/constants.d.ts +13 -4
- package/dist/template-resolver/constants.js +32 -10
- package/dist/template-resolver/document-sanitizer.d.ts +32 -0
- package/dist/template-resolver/document-sanitizer.js +201 -0
- package/dist/template-resolver/document-schema.d.ts +21 -0
- package/dist/template-resolver/document-schema.js +316 -0
- package/dist/template-resolver/feature.d.ts +20 -0
- package/dist/template-resolver/feature.js +53 -6
- package/dist/template-resolver/handlers/bundle-import.d.ts +20 -0
- package/dist/template-resolver/handlers/bundle-import.js +147 -0
- package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-set.write.js +25 -2
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +19 -0
- package/dist/template-resolver/handlers/copy-locale.write.js +134 -0
- package/dist/template-resolver/handlers/diff-to-system.query.d.ts +22 -0
- package/dist/template-resolver/handlers/diff-to-system.query.js +30 -0
- package/dist/template-resolver/handlers/discard-draft.write.d.ts +13 -0
- package/dist/template-resolver/handlers/discard-draft.write.js +37 -0
- package/dist/template-resolver/handlers/export-bundle.query.d.ts +35 -0
- package/dist/template-resolver/handlers/export-bundle.query.js +118 -0
- package/dist/template-resolver/handlers/find-by-id.query.d.ts +2 -0
- package/dist/template-resolver/handlers/find-by-id.query.js +9 -6
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +39 -0
- package/dist/template-resolver/handlers/import-bundle-system.write.js +36 -0
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +40 -0
- package/dist/template-resolver/handlers/import-bundle.write.js +19 -0
- package/dist/template-resolver/handlers/layout-source.query.d.ts +31 -0
- package/dist/template-resolver/handlers/layout-source.query.js +87 -0
- package/dist/template-resolver/handlers/list.query.d.ts +4 -1
- package/dist/template-resolver/handlers/list.query.js +9 -8
- package/dist/template-resolver/handlers/override-diff.d.ts +20 -0
- package/dist/template-resolver/handlers/override-diff.js +41 -0
- package/dist/template-resolver/handlers/overview.query.d.ts +65 -0
- package/dist/template-resolver/handlers/overview.query.js +205 -0
- package/dist/template-resolver/handlers/preview.query.d.ts +12 -0
- package/dist/template-resolver/handlers/preview.query.js +24 -0
- package/dist/template-resolver/handlers/reset-to-system.write.d.ts +8 -0
- package/dist/template-resolver/handlers/reset-to-system.write.js +50 -0
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +8 -0
- package/dist/template-resolver/handlers/resource-link-pdf.write.js +32 -0
- package/dist/template-resolver/handlers/resource-remove.write.d.ts +9 -0
- package/dist/template-resolver/handlers/resource-remove.write.js +44 -0
- package/dist/template-resolver/handlers/resource-shared.d.ts +9 -0
- package/dist/template-resolver/handlers/resource-shared.js +14 -0
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +13 -0
- package/dist/template-resolver/handlers/resource-upload.write.js +98 -0
- package/dist/template-resolver/handlers/send-test.write.d.ts +13 -0
- package/dist/template-resolver/handlers/send-test.write.js +108 -0
- package/dist/template-resolver/handlers/set.write.d.ts +5 -2
- package/dist/template-resolver/handlers/set.write.js +25 -3
- package/dist/template-resolver/handlers/shared.d.ts +9 -5
- package/dist/template-resolver/handlers/shared.js +6 -2
- package/dist/template-resolver/handlers/template-gates.d.ts +36 -0
- package/dist/template-resolver/handlers/template-gates.js +142 -0
- package/dist/template-resolver/handlers/template-write.d.ts +45 -0
- package/dist/template-resolver/handlers/template-write.js +141 -0
- package/dist/template-resolver/handlers/tenant-overrides.query.d.ts +49 -0
- package/dist/template-resolver/handlers/tenant-overrides.query.js +112 -0
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +27 -2
- package/dist/template-resolver/handlers/toggle-status.write.js +47 -15
- package/dist/template-resolver/handlers/upsert-system.write.d.ts +5 -8
- package/dist/template-resolver/handlers/upsert-system.write.js +14 -59
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +5 -8
- package/dist/template-resolver/handlers/upsert-tenant.write.js +11 -62
- package/dist/template-resolver/handlers/usage.query.d.ts +17 -0
- package/dist/template-resolver/handlers/usage.query.js +24 -0
- package/dist/template-resolver/handlers/validate.query.d.ts +74 -0
- package/dist/template-resolver/handlers/validate.query.js +80 -0
- package/dist/template-resolver/index.d.ts +19 -1
- package/dist/template-resolver/index.js +17 -1
- package/dist/template-resolver/layout-appearance.d.ts +10 -0
- package/dist/template-resolver/layout-appearance.js +26 -0
- package/dist/template-resolver/layout-regions.d.ts +23 -0
- package/dist/template-resolver/layout-regions.js +125 -0
- package/dist/template-resolver/linked-resources.d.ts +17 -0
- package/dist/template-resolver/linked-resources.js +75 -0
- package/dist/template-resolver/pdf-constants.d.ts +7 -0
- package/dist/template-resolver/pdf-constants.js +8 -0
- package/dist/template-resolver/preview-display-html.d.ts +7 -0
- package/dist/template-resolver/preview-display-html.js +27 -0
- package/dist/template-resolver/print-document.d.ts +1 -0
- package/dist/template-resolver/print-document.js +55 -0
- package/dist/template-resolver/qualified-names.d.ts +34 -0
- package/dist/template-resolver/qualified-names.js +34 -0
- package/dist/template-resolver/record-mapping.d.ts +2 -0
- package/dist/template-resolver/record-mapping.js +21 -0
- package/dist/template-resolver/resource-image.d.ts +15 -0
- package/dist/template-resolver/resource-image.js +34 -0
- package/dist/template-resolver/seeding.d.ts +14 -1
- package/dist/template-resolver/seeding.js +125 -18
- package/dist/template-resolver/store-template-resource.d.ts +64 -0
- package/dist/template-resolver/store-template-resource.js +264 -0
- package/dist/template-resolver/table.d.ts +150 -8
- package/dist/template-resolver/table.js +20 -2
- package/dist/template-resolver/template-bundle.d.ts +36 -0
- package/dist/template-resolver/template-bundle.js +60 -0
- package/dist/template-resolver/template-diff.d.ts +7 -0
- package/dist/template-resolver/template-diff.js +68 -0
- package/dist/template-resolver/template-draft.d.ts +51 -0
- package/dist/template-resolver/template-draft.js +72 -0
- package/dist/template-resolver/template-meta.d.ts +85 -0
- package/dist/template-resolver/template-meta.js +145 -0
- package/dist/template-resolver/template-preview.d.ts +103 -0
- package/dist/template-resolver/template-preview.js +418 -0
- package/dist/template-resolver/template-resources.d.ts +19 -0
- package/dist/template-resolver/template-resources.js +73 -0
- package/dist/template-resolver/template-usage.d.ts +16 -0
- package/dist/template-resolver/template-usage.js +35 -0
- package/dist/template-resolver/template-validation.d.ts +22 -0
- package/dist/template-resolver/template-validation.js +173 -0
- package/dist/template-resolver/testing.js +5 -5
- package/dist/template-resolver/user-content-table.d.ts +14 -8
- package/dist/template-resolver/web/client-plugin.d.ts +1 -0
- package/dist/template-resolver/web/client-plugin.js +12 -7
- package/dist/template-resolver/web/document-editor-extensions.d.ts +18 -0
- package/dist/template-resolver/web/document-editor-extensions.js +145 -0
- package/dist/template-resolver/web/document-editor.d.ts +4 -0
- package/dist/template-resolver/web/document-editor.js +17 -0
- package/dist/template-resolver/web/document-tiptap-editor.d.ts +3 -0
- package/dist/template-resolver/web/document-tiptap-editor.js +492 -0
- package/dist/template-resolver/web/document-toolbar-blocks.d.ts +41 -0
- package/dist/template-resolver/web/document-toolbar-blocks.js +19 -0
- package/dist/template-resolver/web/editor-handle.d.ts +3 -0
- package/dist/template-resolver/web/editor-handle.js +24 -0
- package/dist/template-resolver/web/i18n.js +91 -0
- package/dist/template-resolver/web/index.d.ts +5 -0
- package/dist/template-resolver/web/index.js +5 -0
- package/dist/template-resolver/web/placeholder-line-editor-lazy.d.ts +4 -0
- package/dist/template-resolver/web/placeholder-line-editor-lazy.js +16 -0
- package/dist/template-resolver/web/placeholder-line-editor.d.ts +17 -0
- package/dist/template-resolver/web/placeholder-line-editor.js +94 -0
- package/dist/template-resolver/web/placeholder-text.d.ts +4 -0
- package/dist/template-resolver/web/placeholder-text.js +34 -0
- package/dist/template-resolver/web/use-stable-by-key.d.ts +1 -0
- package/dist/template-resolver/web/use-stable-by-key.js +13 -0
- package/dist/tenant/handlers/add-member.write.d.ts +1 -1
- package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
- package/dist/tenant/handlers/create.write.d.ts +1 -1
- package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
- package/dist/tenant/handlers/team-list.query.js +3 -2
- package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
- package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
- package/dist/tenant/handlers/update.write.d.ts +1 -1
- package/dist/tenant/seeding.js +31 -6
- package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +2 -2
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +2 -1
- package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
- package/dist/tier-engine/feature.js +9 -3
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
- package/dist/user/db/queries/stream-tenant-backfill.js +4 -4
- package/dist/user/handlers/create.write.d.ts +1 -1
- package/dist/user/handlers/detail.query.js +2 -1
- package/dist/user/handlers/update.write.d.ts +1 -1
- package/dist/user/resolve-display-names.js +5 -9
- package/dist/user/seeding.js +20 -1
- package/dist/user-data-rights/db/queries/forget-cleanup.d.ts +2 -2
- package/dist/user-data-rights/email-templates.d.ts +1 -29
- package/dist/user-data-rights/email-templates.js +5 -106
- package/dist/user-data-rights/feature.js +53 -35
- package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +2 -1
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.js +5 -7
- package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
- package/dist/user-data-rights/lib/default-mailers.d.ts +15 -7
- package/dist/user-data-rights/lib/default-mailers.js +100 -48
- package/dist/user-data-rights/lib/update-user-lifecycle.js +1 -1
- package/dist/user-data-rights/mail-notifications.d.ts +13 -0
- package/dist/user-data-rights/mail-notifications.js +118 -0
- package/dist/user-data-rights/web/privacy-center-screen.js +2 -1
- package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
- package/dist/user-profile/web/profile-screen.js +2 -1
- package/dist/waitlist/feature.js +10 -0
- package/dist/waitlist/handlers/invite.write.d.ts +1 -1
- package/dist/waitlist/handlers/reject.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.js +3 -4
- package/dist/waitlist/mail.d.ts +19 -6
- package/dist/waitlist/mail.js +50 -14
- package/dist/waitlist/options.js +1 -1
- package/dist/workflow-runner/event-trigger.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +7 -2
- package/package.json +37 -17
- package/src/admin-shell/changes.json +6 -0
- package/src/audit/changes.json +6 -0
- package/src/auth-email-password/changes.json +51 -0
- package/src/billing-foundation/changes.json +43 -0
- package/src/cap-counter/changes.json +6 -0
- package/src/channel-email/changes.json +19 -0
- package/src/config/changes.json +6 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/custom-fields/changes.json +6 -0
- package/src/data-retention/changes.json +6 -0
- package/src/delivery/changes.json +66 -0
- package/src/file-foundation/changes.json +6 -0
- package/src/files-tenant-data/changes.json +6 -0
- package/src/inbound-mail-foundation/changes.json +6 -0
- package/src/jobs/changes.json +19 -0
- package/src/ledger/changes.json +7 -0
- package/src/managed-pages/changes.json +6 -0
- package/src/renderer-foundation/changes.json +39 -0
- package/src/renderer-pdf/changes.json +12 -0
- package/src/secrets/changes.json +6 -0
- package/src/shared/changes.json +6 -0
- package/src/subscription-stripe/changes.json +6 -0
- package/src/template-resolver/changes.json +186 -0
- package/src/tier-engine/changes.json +6 -0
- package/src/user/changes.json +6 -0
- package/src/user-data-rights/changes.json +13 -0
- package/src/user-profile/changes.json +1 -1
- package/src/waitlist/changes.json +7 -0
- package/src/workflow-runner/changes.json +6 -0
- package/dist/renderer-simple/feature.d.ts +0 -10
- package/dist/renderer-simple/feature.js +0 -42
- package/dist/renderer-simple/index.d.ts +0 -3
- package/dist/renderer-simple/index.js +0 -2
- package/dist/renderer-simple/mail-blocks.d.ts +0 -21
- package/dist/renderer-simple/mail-blocks.js +0 -107
- package/dist/renderer-simple/resolve-variables.d.ts +0 -7
- package/dist/renderer-simple/resolve-variables.js +0 -47
- package/dist/renderer-simple/simple-renderer.d.ts +0 -24
- package/dist/renderer-simple/simple-renderer.js +0 -200
- package/src/renderer-simple/changes.json +0 -27
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
3
4
|
function hmacSign(input, secret) {
|
|
4
5
|
return createHmac("sha256", secret).update(input).digest("base64url");
|
|
5
6
|
}
|
|
@@ -8,13 +9,12 @@ function hmacSign(input, secret) {
|
|
|
8
9
|
// replayed as a challenge token), since both share the same secret and payload shape.
|
|
9
10
|
export function createHmacTokenCodec(domain, isPayload) {
|
|
10
11
|
function splitEncodedBody(value) {
|
|
11
|
-
if (
|
|
12
|
+
if (!isPlainObject(value))
|
|
12
13
|
return null;
|
|
13
|
-
const
|
|
14
|
-
const expiresAtMs = v["expiresAtMs"];
|
|
14
|
+
const expiresAtMs = value["expiresAtMs"];
|
|
15
15
|
if (typeof expiresAtMs !== "number")
|
|
16
16
|
return null;
|
|
17
|
-
const { expiresAtMs: _drop, ...rest } =
|
|
17
|
+
const { expiresAtMs: _drop, ...rest } = value;
|
|
18
18
|
return isPayload(rest) ? { payload: rest, expiresAtMs } : null;
|
|
19
19
|
}
|
|
20
20
|
return {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
3
|
import { createHmacTokenCodec } from "./hmac-token-codec.js";
|
|
3
4
|
function isPayload(value) {
|
|
4
|
-
if (
|
|
5
|
+
if (!isPlainObject(value))
|
|
5
6
|
return false;
|
|
6
|
-
|
|
7
|
-
return typeof v["userId"] === "string" && typeof v["tenantId"] === "string";
|
|
7
|
+
return typeof value["userId"] === "string" && typeof value["tenantId"] === "string";
|
|
8
8
|
}
|
|
9
9
|
// Domain-separated from mfa-preauth-setup (see hmac-token-codec). Single-use is
|
|
10
10
|
// enforced by the consumer via burnToken (purpose "mfa-challenge"); this codec
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
3
|
import { createHmacTokenCodec } from "./hmac-token-codec.js";
|
|
3
4
|
function isPayload(value) {
|
|
4
|
-
if (
|
|
5
|
+
if (!isPlainObject(value))
|
|
5
6
|
return false;
|
|
6
|
-
|
|
7
|
-
return typeof v["userId"] === "string" && typeof v["tenantId"] === "string";
|
|
7
|
+
return typeof value["userId"] === "string" && typeof value["tenantId"] === "string";
|
|
8
8
|
}
|
|
9
9
|
// Domain "mfa-preauth-setup" must never equal the challenge domain: a setup
|
|
10
10
|
// token has to fail verification as a challenge token and vice versa. The
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// generated secret material, not just re-derive it from a lookup.
|
|
12
12
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
13
13
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
14
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
14
15
|
function sign(input, secret) {
|
|
15
16
|
return createHmac("sha256", secret).update(input).digest("base64url");
|
|
16
17
|
}
|
|
@@ -22,15 +23,14 @@ export function signMfaSetupToken(payload, ttlMinutes, secret, now = Temporal.No
|
|
|
22
23
|
return { token: `${bodyB64}.${signature}`, expiresAt };
|
|
23
24
|
}
|
|
24
25
|
function isEncodedBody(value) {
|
|
25
|
-
if (
|
|
26
|
+
if (!isPlainObject(value))
|
|
26
27
|
return false;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
typeof
|
|
33
|
-
(v["tenantId"] === undefined || typeof v["tenantId"] === "string"));
|
|
28
|
+
return (typeof value["userId"] === "string" &&
|
|
29
|
+
typeof value["totpSecretBase32"] === "string" &&
|
|
30
|
+
Array.isArray(value["recoveryCodeHashes"]) &&
|
|
31
|
+
value["recoveryCodeHashes"].every((h) => typeof h === "string") &&
|
|
32
|
+
typeof value["expiresAtMs"] === "number" &&
|
|
33
|
+
(value["tenantId"] === undefined || typeof value["tenantId"] === "string"));
|
|
34
34
|
}
|
|
35
35
|
export function verifyMfaSetupToken(token, secret, now = Temporal.Now.instant()) {
|
|
36
36
|
const parts = token.split(".");
|
|
@@ -3,11 +3,11 @@ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
|
3
3
|
export declare const BILLING_FOUNDATION_FEATURE: "billing-foundation";
|
|
4
4
|
export declare const SUBSCRIPTION_PROVIDER_EXTENSION: "subscriptionProvider";
|
|
5
5
|
/** delivery notification type of the § 312f contract confirmation mail. */
|
|
6
|
-
export declare const CONTRACT_CONFIRMATION_NOTIFICATION_TYPE: "billing-foundation:contract-confirmation";
|
|
6
|
+
export declare const CONTRACT_CONFIRMATION_NOTIFICATION_TYPE: "billing-foundation:notify:contract-confirmation";
|
|
7
7
|
/** delivery notification types of the § 312k termination receipt and the
|
|
8
8
|
* operator notice. */
|
|
9
|
-
export declare const CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE: "billing-foundation:contract-termination-receipt";
|
|
10
|
-
export declare const CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE: "billing-foundation:contract-termination-operator-notice";
|
|
9
|
+
export declare const CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE: "billing-foundation:notify:contract-termination-receipt";
|
|
10
|
+
export declare const CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE: "billing-foundation:notify:contract-termination-operator-notice";
|
|
11
11
|
export declare const SubscriptionFoundationHandlers: {
|
|
12
12
|
/** Programmatic entry-point für den webhook-handler. Receives the
|
|
13
13
|
* parsed SubscriptionEvent (vom Plugin schon verifiziert) + macht
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
2
|
// @runtime client
|
|
3
3
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
|
+
import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
4
5
|
// Feature name
|
|
5
6
|
export const BILLING_FOUNDATION_FEATURE = "billing-foundation";
|
|
6
7
|
// Extension-point name fuer Provider-Plugins (subscription-stripe,
|
|
7
8
|
// subscription-mollie, ...).
|
|
8
9
|
export const SUBSCRIPTION_PROVIDER_EXTENSION = "subscriptionProvider";
|
|
9
10
|
/** delivery notification type of the § 312f contract confirmation mail. */
|
|
10
|
-
export const CONTRACT_CONFIRMATION_NOTIFICATION_TYPE = "billing-foundation:contract-confirmation";
|
|
11
|
+
export const CONTRACT_CONFIRMATION_NOTIFICATION_TYPE = "billing-foundation:notify:contract-confirmation";
|
|
11
12
|
/** delivery notification types of the § 312k termination receipt and the
|
|
12
13
|
* operator notice. */
|
|
13
|
-
export const CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE = "billing-foundation:contract-termination-receipt";
|
|
14
|
-
export const CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE = "billing-foundation:contract-termination-operator-notice";
|
|
14
|
+
export const CONTRACT_TERMINATION_RECEIPT_NOTIFICATION_TYPE = "billing-foundation:notify:contract-termination-receipt";
|
|
15
|
+
export const CONTRACT_TERMINATION_OPERATOR_NOTIFICATION_TYPE = "billing-foundation:notify:contract-termination-operator-notice";
|
|
15
16
|
// Qualified write handler names (QN format: scope:type:name).
|
|
16
17
|
export const SubscriptionFoundationHandlers = {
|
|
17
18
|
/** Programmatic entry-point für den webhook-handler. Receives the
|
|
@@ -195,5 +196,5 @@ export const DEFAULT_PURCHASE_ROLES = ["TenantAdmin", "SystemAdmin"];
|
|
|
195
196
|
// `<plugin-name>:config:price-to-tier`-Key.
|
|
196
197
|
export const TERMINATION_SCOPES = ["tenant-host", "platform"];
|
|
197
198
|
export function isTerminationScope(value) {
|
|
198
|
-
return TERMINATION_SCOPES
|
|
199
|
+
return isOneOf(TERMINATION_SCOPES, value);
|
|
199
200
|
}
|
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
import type { CheckoutConsentRecordedPayload } from "../events.js";
|
|
2
|
-
|
|
2
|
+
import { type ConsentLocale } from "./consent-text.js";
|
|
3
|
+
type ConfirmationLabels = {
|
|
4
|
+
readonly subject: string;
|
|
5
|
+
readonly intro: string;
|
|
6
|
+
readonly plan: string;
|
|
7
|
+
readonly item: string;
|
|
8
|
+
readonly oneOffPayment: string;
|
|
9
|
+
readonly price: string;
|
|
10
|
+
readonly oneOff: string;
|
|
11
|
+
readonly contractStart: string;
|
|
12
|
+
readonly currentPeriodEnd: string;
|
|
13
|
+
readonly consentHeading: string;
|
|
14
|
+
readonly consentGivenAt: string;
|
|
15
|
+
readonly termsHeading: string;
|
|
16
|
+
readonly contact: string;
|
|
17
|
+
readonly intervals: Readonly<Record<string, {
|
|
18
|
+
one: string;
|
|
19
|
+
many: string;
|
|
20
|
+
}>>;
|
|
21
|
+
readonly every: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const CONFIRMATION_LABELS: Readonly<Record<ConsentLocale, ConfirmationLabels>>;
|
|
24
|
+
type TextRow = {
|
|
3
25
|
readonly text: string;
|
|
4
|
-
} | {
|
|
5
|
-
readonly heading: string;
|
|
6
|
-
} | {
|
|
7
|
-
readonly markdown: string;
|
|
8
26
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
readonly
|
|
27
|
+
/** Variables of the contract confirmation template. */
|
|
28
|
+
export type ContractConfirmationVariables = {
|
|
29
|
+
readonly contractLines: readonly TextRow[];
|
|
30
|
+
readonly consentGivenAt: string;
|
|
31
|
+
readonly termsParagraphs: readonly TextRow[];
|
|
32
|
+
readonly operatorEmail: string;
|
|
14
33
|
};
|
|
15
|
-
export type
|
|
34
|
+
export type ContractConfirmationArgs = {
|
|
16
35
|
readonly consent: CheckoutConsentRecordedPayload;
|
|
17
36
|
readonly timeZone: string;
|
|
18
37
|
/** Translated plan name; falls back to the raw tier. */
|
|
@@ -26,6 +45,5 @@ export type RenderContractConfirmationArgs = {
|
|
|
26
45
|
readonly operatorEmail: string;
|
|
27
46
|
readonly termsContent: string;
|
|
28
47
|
};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export declare function renderContractConfirmation(args: RenderContractConfirmationArgs): ContractConfirmationContent;
|
|
48
|
+
export declare function contractConfirmationVariables(args: ContractConfirmationArgs): ContractConfirmationVariables;
|
|
49
|
+
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { escapeHtml, escapeHtmlAttr } from "@cosmicdrift/kumiko-headless";
|
|
1
2
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
|
-
import {
|
|
3
|
-
|
|
3
|
+
import { Marked } from "marked";
|
|
4
|
+
import { isAllowedDocumentLinkHref, isDocumentPlaceholderHref, } from "../../template-resolver/index.js";
|
|
5
|
+
import { resolveConsentLocale } from "./consent-text.js";
|
|
6
|
+
export const CONFIRMATION_LABELS = {
|
|
4
7
|
de: {
|
|
5
8
|
subject: "Vertragsbestätigung",
|
|
6
9
|
intro: "Vielen Dank für deine Bestellung. Hiermit bestätigen wir den Vertragsschluss mit folgendem Inhalt.",
|
|
@@ -47,7 +50,7 @@ const LABELS = {
|
|
|
47
50
|
},
|
|
48
51
|
};
|
|
49
52
|
function formatPrice(consent, locale) {
|
|
50
|
-
const labels =
|
|
53
|
+
const labels = CONFIRMATION_LABELS[locale];
|
|
51
54
|
if (consent.unitAmount === null || consent.currency === null)
|
|
52
55
|
return "-";
|
|
53
56
|
let amount;
|
|
@@ -89,40 +92,79 @@ function formatDate(iso, locale, timeZone) {
|
|
|
89
92
|
timeZoneName: "short",
|
|
90
93
|
}).format(epochMilliseconds);
|
|
91
94
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
// One richText row of inline HTML per Markdown block. The sanitizer shows a rejected
|
|
96
|
+
// row as escaped text, so author HTML, images and refused links stay plain text.
|
|
97
|
+
const ROW_END = "\n\n";
|
|
98
|
+
function isMailLinkHref(href) {
|
|
99
|
+
return isAllowedDocumentLinkHref(href) && !isDocumentPlaceholderHref(href);
|
|
100
|
+
}
|
|
101
|
+
const inlineHtmlMarkdown = new Marked({ gfm: false, breaks: false });
|
|
102
|
+
inlineHtmlMarkdown.use({
|
|
103
|
+
renderer: {
|
|
104
|
+
heading({ tokens }) {
|
|
105
|
+
const headingHtml = this.parser.parseInline(tokens);
|
|
106
|
+
return `<strong>${headingHtml}</strong>${ROW_END}`;
|
|
107
|
+
},
|
|
108
|
+
paragraph({ tokens }) {
|
|
109
|
+
return `${this.parser.parseInline(tokens)}${ROW_END}`;
|
|
110
|
+
},
|
|
111
|
+
code: ({ text }) => `${escapeHtml(text)}${ROW_END}`,
|
|
112
|
+
blockquote({ tokens }) {
|
|
113
|
+
return this.parser.parse(tokens);
|
|
114
|
+
},
|
|
115
|
+
list({ items }) {
|
|
116
|
+
return items.map((item) => this.parser.parse(item.tokens)).join("");
|
|
117
|
+
},
|
|
118
|
+
hr: () => "",
|
|
119
|
+
space: () => "",
|
|
120
|
+
del({ tokens }) {
|
|
121
|
+
return this.parser.parseInline(tokens);
|
|
122
|
+
},
|
|
123
|
+
br: () => " ",
|
|
124
|
+
html: ({ text }) => escapeHtml(text),
|
|
125
|
+
image: ({ text }) => escapeHtml(text),
|
|
126
|
+
text(token) {
|
|
127
|
+
// Only block-level text (a list item's own text) carries inline child tokens.
|
|
128
|
+
return "tokens" in token && token.tokens
|
|
129
|
+
? `${this.parser.parseInline(token.tokens)}${ROW_END}`
|
|
130
|
+
: escapeHtml(token.text);
|
|
131
|
+
},
|
|
132
|
+
link({ href, tokens }) {
|
|
133
|
+
const labelHtml = this.parser.parseInline(tokens);
|
|
134
|
+
if (isMailLinkHref(href))
|
|
135
|
+
return `<a href="${escapeHtmlAttr(href)}">${labelHtml}</a>`;
|
|
136
|
+
return labelHtml === escapeHtml(href) ? labelHtml : `${labelHtml} (${escapeHtml(href)})`;
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
function termsParagraphsOf(markdown) {
|
|
141
|
+
return inlineHtmlMarkdown
|
|
142
|
+
.parse(markdown, { async: false })
|
|
143
|
+
.split(/\n\s*\n/)
|
|
144
|
+
.map((row) => row.replace(/\s+/g, " ").trim())
|
|
145
|
+
.filter((row) => row.length > 0)
|
|
146
|
+
.map((text) => ({ text }));
|
|
147
|
+
}
|
|
148
|
+
export function contractConfirmationVariables(args) {
|
|
95
149
|
const locale = resolveConsentLocale(args.consent.locale);
|
|
96
|
-
const labels =
|
|
97
|
-
const
|
|
98
|
-
const { consent } = args;
|
|
99
|
-
const { timeZone } = args;
|
|
150
|
+
const labels = CONFIRMATION_LABELS[locale];
|
|
151
|
+
const { consent, timeZone } = args;
|
|
100
152
|
const subjectLine = consent.mode === "payment"
|
|
101
153
|
? `${labels.item}: ${args.itemLabel ?? labels.oneOffPayment}`
|
|
102
154
|
: `${labels.plan}: ${args.tierLabel ?? consent.tier ?? labels.oneOffPayment}`;
|
|
103
|
-
const contractLines = [
|
|
104
|
-
subjectLine,
|
|
105
|
-
`${labels.price}: ${formatPrice(consent, locale)}`,
|
|
106
|
-
`${labels.contractStart}: ${formatDate(args.contractStartIso, locale, timeZone)}`,
|
|
107
|
-
...(args.currentPeriodEndIso !== undefined
|
|
108
|
-
? [`${labels.currentPeriodEnd}: ${formatDate(args.currentPeriodEndIso, locale, timeZone)}`]
|
|
109
|
-
: []),
|
|
110
|
-
];
|
|
111
155
|
const vatNote = args.vatNote[locale] ?? args.vatNote[resolveConsentLocale()];
|
|
112
156
|
return {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
{
|
|
117
|
-
...
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
],
|
|
126
|
-
footer: `${labels.contact} ${args.operatorEmail}`,
|
|
157
|
+
contractLines: [
|
|
158
|
+
subjectLine,
|
|
159
|
+
`${labels.price}: ${formatPrice(consent, locale)}`,
|
|
160
|
+
`${labels.contractStart}: ${formatDate(args.contractStartIso, locale, timeZone)}`,
|
|
161
|
+
...(args.currentPeriodEndIso !== undefined
|
|
162
|
+
? [`${labels.currentPeriodEnd}: ${formatDate(args.currentPeriodEndIso, locale, timeZone)}`]
|
|
163
|
+
: []),
|
|
164
|
+
...(vatNote !== undefined ? [vatNote] : []),
|
|
165
|
+
].map((text) => ({ text })),
|
|
166
|
+
consentGivenAt: formatDate(args.consentGivenAtIso, locale, timeZone),
|
|
167
|
+
termsParagraphs: termsParagraphsOf(args.termsContent),
|
|
168
|
+
operatorEmail: args.operatorEmail,
|
|
127
169
|
};
|
|
128
170
|
}
|
|
@@ -22,6 +22,9 @@ export type OrderItem = {
|
|
|
22
22
|
readonly labelKey: string;
|
|
23
23
|
readonly params?: Readonly<Record<string, string | number>>;
|
|
24
24
|
};
|
|
25
|
+
/** Throws an InternalError (an app configuration fault, not a buyer error) for a
|
|
26
|
+
* label the consent event could not store. */
|
|
27
|
+
export declare function assertValidOrderItem(item: OrderItem | undefined, priceId: string): void;
|
|
25
28
|
export type ConsentPriceDetails = {
|
|
26
29
|
readonly tier: string | null;
|
|
27
30
|
readonly priceId: string;
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// validate + prepare before the provider call, record only after it succeeded.
|
|
3
3
|
import { createHash } from "node:crypto";
|
|
4
4
|
import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
5
|
-
import { UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
|
+
import { InternalError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
|
|
6
6
|
import { generateId } from "@cosmicdrift/kumiko-framework/utils";
|
|
7
7
|
import * as z from "zod";
|
|
8
8
|
import { requireTemplateResolver, TEXT_BLOCK_KIND, TemplateNotFoundError, } from "../../template-resolver/index.js";
|
|
9
9
|
import { paymentAggregateId, subscriptionAggregateId } from "../aggregate-id.js";
|
|
10
|
-
import { CHECKOUT_CONSENT_RECORDED_EVENT_QN, PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
10
|
+
import { CHECKOUT_CONSENT_RECORDED_EVENT_QN, checkoutConsentRecordedPayloadSchema, PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
11
11
|
import { consentTextVersion, resolveConsentLocale, submitMessageFor } from "./consent-text.js";
|
|
12
12
|
// Optional at the schema level so a missing/unchecked consent reaches
|
|
13
13
|
// prepareConsent and fails as 422 consent_required, not as a zod 400.
|
|
@@ -19,6 +19,25 @@ export const consentPayloadSchema = z
|
|
|
19
19
|
locale: z.string().min(2).max(35),
|
|
20
20
|
})
|
|
21
21
|
.strict();
|
|
22
|
+
// Bounds come from the event schema the label ends up in, so an app label that
|
|
23
|
+
// passes here cannot fail the append after the provider session exists.
|
|
24
|
+
const orderItemSchema = z.object({
|
|
25
|
+
labelKey: checkoutConsentRecordedPayloadSchema.shape.itemLabelKey.unwrap(),
|
|
26
|
+
params: checkoutConsentRecordedPayloadSchema.shape.itemLabelParams,
|
|
27
|
+
});
|
|
28
|
+
/** Throws an InternalError (an app configuration fault, not a buyer error) for a
|
|
29
|
+
* label the consent event could not store. */
|
|
30
|
+
export function assertValidOrderItem(item, priceId) {
|
|
31
|
+
// skip: subscription checkouts have no one-off order item
|
|
32
|
+
if (item === undefined)
|
|
33
|
+
return;
|
|
34
|
+
const parsed = orderItemSchema.safeParse(item);
|
|
35
|
+
if (!parsed.success) {
|
|
36
|
+
throw new InternalError({
|
|
37
|
+
message: `billing-foundation: consumerProtection.oneOffItemLabel returned an invalid label for priceId "${priceId}": ${parsed.error.message}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
22
41
|
export async function prepareConsent(ctx, options, consent, mode) {
|
|
23
42
|
if (!consent?.earlyPerformanceRequested || !consent.withdrawalLossAcknowledged) {
|
|
24
43
|
throw new UnprocessableError("consent_required", {
|
|
@@ -11,7 +11,7 @@ import { UserQueries } from "../../user/index.js";
|
|
|
11
11
|
import { paymentAggregateId, subscriptionAggregateId } from "../aggregate-id.js";
|
|
12
12
|
import { CONTRACT_CONFIRMATION_NOTIFICATION_TYPE } from "../constants.js";
|
|
13
13
|
import { CHECKOUT_CONSENT_RECORDED_EVENT_QN, CONTRACT_CONFIRMATION_ISSUED_EVENT_QN, checkoutConsentRecordedPayloadSchema, contractConfirmationIssuedPayloadSchema, PAYMENT_AGGREGATE_TYPE, SUBSCRIPTION_AGGREGATE_TYPE, } from "../events.js";
|
|
14
|
-
import {
|
|
14
|
+
import { contractConfirmationVariables } from "./confirmation-mail.js";
|
|
15
15
|
import { resolveConsentLocale } from "./consent-text.js";
|
|
16
16
|
export const issueContractConfirmationSchema = z
|
|
17
17
|
.object({
|
|
@@ -128,7 +128,7 @@ export function createIssueContractConfirmationHandler(options, consumerProtecti
|
|
|
128
128
|
? translatedOrUndefined(i18n.t(consent.itemLabelKey, locale, consent.itemLabelParams), consent.itemLabelKey)
|
|
129
129
|
: undefined;
|
|
130
130
|
const issuedAtIso = options.now().toString();
|
|
131
|
-
const
|
|
131
|
+
const variables = contractConfirmationVariables({
|
|
132
132
|
consent,
|
|
133
133
|
timeZone: pickTimeZone(recipient.data.timezone, ctx.tz.tenant),
|
|
134
134
|
...(tierLabel !== undefined && { tierLabel }),
|
|
@@ -159,7 +159,7 @@ export function createIssueContractConfirmationHandler(options, consumerProtecti
|
|
|
159
159
|
await stream.appendOne({ type: CONTRACT_CONFIRMATION_ISSUED_EVENT_QN, payload: issued });
|
|
160
160
|
await ctx.notify(CONTRACT_CONFIRMATION_NOTIFICATION_TYPE, {
|
|
161
161
|
route: { email: recipient.data.email },
|
|
162
|
-
data:
|
|
162
|
+
data: variables,
|
|
163
163
|
locale,
|
|
164
164
|
priority: "critical",
|
|
165
165
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type FeatureRegistrar, type NotificationLocalizedTemplate, type TemplateVariables } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
export declare const TERMINATION_RECEIPT_VARIABLES: TemplateVariables;
|
|
3
|
+
export declare const OPERATOR_NOTICE_VARIABLES: TemplateVariables;
|
|
4
|
+
export declare const CONTRACT_CONFIRMATION_VARIABLES: TemplateVariables;
|
|
5
|
+
export declare function terminationReceiptTemplate(): NotificationLocalizedTemplate;
|
|
6
|
+
export declare function operatorNoticeTemplate(): NotificationLocalizedTemplate;
|
|
7
|
+
export declare function contractConfirmationTemplate(): NotificationLocalizedTemplate;
|
|
8
|
+
export declare function registerConsumerProtectionMails(r: FeatureRegistrar): void;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { templateVariable, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { mailHeading, mailParagraph, mailRepeatedRows } from "../../shared/index.js";
|
|
3
|
+
import { CONFIRMATION_LABELS } from "./confirmation-mail.js";
|
|
4
|
+
import { CONSENT_LOCALES, CONSENT_TEXTS } from "./consent-text.js";
|
|
5
|
+
import { TERMINATION_TEXTS } from "./termination-texts.js";
|
|
6
|
+
// Slot syntax for the translated texts: `{name}` becomes a template variable.
|
|
7
|
+
const OPERATOR_EMAIL_SLOT = "{operatorEmail}";
|
|
8
|
+
const textRows = () => templateVariable.list({ text: templateVariable.text({ required: true }) }, { required: true });
|
|
9
|
+
export const TERMINATION_RECEIPT_VARIABLES = {
|
|
10
|
+
subject: templateVariable.text({ required: true }),
|
|
11
|
+
receivedAt: templateVariable.text({ required: true }),
|
|
12
|
+
requestId: templateVariable.text({ required: true }),
|
|
13
|
+
details: textRows(),
|
|
14
|
+
operatorEmail: templateVariable.text({ required: true }),
|
|
15
|
+
};
|
|
16
|
+
export const OPERATOR_NOTICE_VARIABLES = {
|
|
17
|
+
subject: templateVariable.text({ required: true }),
|
|
18
|
+
lines: textRows(),
|
|
19
|
+
operatorEmail: templateVariable.text({ required: true }),
|
|
20
|
+
};
|
|
21
|
+
export const CONTRACT_CONFIRMATION_VARIABLES = {
|
|
22
|
+
contractLines: textRows(),
|
|
23
|
+
consentGivenAt: templateVariable.text({ required: true }),
|
|
24
|
+
termsParagraphs: templateVariable.list({ text: templateVariable.richText({ required: true }) }, { required: true }),
|
|
25
|
+
operatorEmail: templateVariable.text({ required: true }),
|
|
26
|
+
};
|
|
27
|
+
function perLocale(build) {
|
|
28
|
+
return Object.fromEntries(CONSENT_LOCALES.map((locale) => {
|
|
29
|
+
const { body, subject } = build(locale);
|
|
30
|
+
return [locale, { body, meta: { subject, category: "transactional" } }];
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
export function terminationReceiptTemplate() {
|
|
34
|
+
return perLocale((locale) => {
|
|
35
|
+
const texts = TERMINATION_TEXTS[locale];
|
|
36
|
+
return {
|
|
37
|
+
subject: "{{subject}}",
|
|
38
|
+
body: [
|
|
39
|
+
mailParagraph(texts.receiptGreeting),
|
|
40
|
+
mailParagraph(texts.receiptIntro),
|
|
41
|
+
mailParagraph(`${texts.receivedAt}: {receivedAt}`),
|
|
42
|
+
mailParagraph(`${texts.requestId}: {requestId}`),
|
|
43
|
+
mailRepeatedRows("details", "text"),
|
|
44
|
+
mailParagraph(texts.receiptNextSteps),
|
|
45
|
+
mailParagraph(texts.receiptRevoke(OPERATOR_EMAIL_SLOT)),
|
|
46
|
+
mailParagraph(`${texts.contact} {operatorEmail}`),
|
|
47
|
+
].join(""),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export function operatorNoticeTemplate() {
|
|
52
|
+
return perLocale((locale) => ({
|
|
53
|
+
subject: "{{subject}}",
|
|
54
|
+
body: [
|
|
55
|
+
mailParagraph(TERMINATION_TEXTS[locale].operatorIntro),
|
|
56
|
+
mailRepeatedRows("lines", "text"),
|
|
57
|
+
mailParagraph("{operatorEmail}"),
|
|
58
|
+
].join(""),
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
export function contractConfirmationTemplate() {
|
|
62
|
+
return perLocale((locale) => {
|
|
63
|
+
const labels = CONFIRMATION_LABELS[locale];
|
|
64
|
+
const consent = CONSENT_TEXTS[locale];
|
|
65
|
+
return {
|
|
66
|
+
subject: labels.subject,
|
|
67
|
+
body: [
|
|
68
|
+
mailParagraph(labels.intro),
|
|
69
|
+
mailRepeatedRows("contractLines", "text"),
|
|
70
|
+
mailHeading(labels.consentHeading),
|
|
71
|
+
mailParagraph(consent.earlyPerformance),
|
|
72
|
+
mailParagraph(consent.withdrawalLoss),
|
|
73
|
+
mailParagraph(`${labels.consentGivenAt}: {consentGivenAt}`),
|
|
74
|
+
mailHeading(labels.termsHeading),
|
|
75
|
+
mailRepeatedRows("termsParagraphs", "text"),
|
|
76
|
+
mailParagraph(`${labels.contact} {operatorEmail}`),
|
|
77
|
+
].join(""),
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// The registered notification names are the tail of the QN types in constants.ts.
|
|
82
|
+
export function registerConsumerProtectionMails(r) {
|
|
83
|
+
r.notification("contract-confirmation", {
|
|
84
|
+
variables: CONTRACT_CONFIRMATION_VARIABLES,
|
|
85
|
+
localizedTemplate: contractConfirmationTemplate,
|
|
86
|
+
});
|
|
87
|
+
r.notification("contract-termination-receipt", {
|
|
88
|
+
variables: TERMINATION_RECEIPT_VARIABLES,
|
|
89
|
+
localizedTemplate: terminationReceiptTemplate,
|
|
90
|
+
});
|
|
91
|
+
r.notification("contract-termination-operator-notice", {
|
|
92
|
+
variables: OPERATOR_NOTICE_VARIABLES,
|
|
93
|
+
localizedTemplate: operatorNoticeTemplate,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -2,6 +2,7 @@ import { paymentAggregateId, subscriptionAggregateId } from "../aggregate-id.js"
|
|
|
2
2
|
import { SubscriptionFoundationHandlers, SubscriptionStatuses } from "../constants.js";
|
|
3
3
|
import { CHECKOUT_CONSENT_RECORDED_EVENT_SHORT, CONTRACT_CONFIRMATION_ISSUED_EVENT_SHORT, checkoutConsentRecordedPayloadSchema, contractConfirmationIssuedPayloadSchema, INVOICE_PAID_EVENT_QN, PAYMENT_RECEIVED_EVENT_QN, SUBSCRIPTION_CREATED_EVENT_QN, SUBSCRIPTION_UPDATED_EVENT_QN, } from "../events.js";
|
|
4
4
|
import { createIssueContractConfirmationHandler } from "./issue-confirmation.js";
|
|
5
|
+
import { registerConsumerProtectionMails } from "./mail-notifications.js";
|
|
5
6
|
import { registerContractTermination } from "./register-termination.js";
|
|
6
7
|
const CONFIRMATION_TRIGGERS = [
|
|
7
8
|
{
|
|
@@ -22,6 +23,7 @@ function isConfirmableSubscriptionStatus(status) {
|
|
|
22
23
|
}
|
|
23
24
|
export function registerConsumerProtection(r, options, consumerProtection) {
|
|
24
25
|
r.requires("template-resolver", "delivery", "user", "tenant");
|
|
26
|
+
registerConsumerProtectionMails(r);
|
|
25
27
|
registerContractTermination(r, options, consumerProtection);
|
|
26
28
|
r.defineEvent(CHECKOUT_CONSENT_RECORDED_EVENT_SHORT, checkoutConsentRecordedPayloadSchema, {
|
|
27
29
|
piiFields: "none",
|
|
@@ -16,7 +16,17 @@ export function registerContractTermination(r, options, consumerProtection) {
|
|
|
16
16
|
// request: matched and unmatched requests then do the same work and the
|
|
17
17
|
// response time does not tell whether the email belongs to a customer.
|
|
18
18
|
// The tenant comes from the stored trigger event (the job's system user).
|
|
19
|
-
|
|
19
|
+
// Every declaration appends to the same subscription stream, so parallel runs
|
|
20
|
+
// and a declaration arriving mid-run hit version conflicts. Sequential runs
|
|
21
|
+
// rule out the first; a retry re-reads the stream and the requestId check in
|
|
22
|
+
// record-contract-termination keeps it from recording twice.
|
|
23
|
+
r.job("cancel-on-public-termination-declared", {
|
|
24
|
+
trigger: { on: CONTRACT_TERMINATION_DECLARED_EVENT_QN },
|
|
25
|
+
runIn: "worker",
|
|
26
|
+
concurrency: "sequential",
|
|
27
|
+
retries: 3,
|
|
28
|
+
backoff: "exponential",
|
|
29
|
+
}, async (payload, ctx) => {
|
|
20
30
|
const declared = contractTerminationDeclaredPayloadSchema.safeParse(payload);
|
|
21
31
|
// skip: trigger event carries no usable declaration
|
|
22
32
|
if (!declared.success)
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import type { ContractTerminationDeclarationType, ContractTerminationKind, ProviderCancelOutcome } from "../events.js";
|
|
2
2
|
import type { ConsentLocale } from "./consent-text.js";
|
|
3
3
|
import { type OperatorNoticeReason } from "./termination-texts.js";
|
|
4
|
-
|
|
4
|
+
type TextRow = {
|
|
5
|
+
readonly text: string;
|
|
6
|
+
};
|
|
7
|
+
/** Variables of the termination receipt template. */
|
|
8
|
+
export type TerminationReceiptVariables = {
|
|
9
|
+
readonly subject: string;
|
|
10
|
+
readonly receivedAt: string;
|
|
11
|
+
readonly requestId: string;
|
|
12
|
+
readonly details: readonly TextRow[];
|
|
13
|
+
readonly operatorEmail: string;
|
|
14
|
+
};
|
|
15
|
+
/** Variables of the operator notice template. */
|
|
16
|
+
export type OperatorNoticeVariables = {
|
|
5
17
|
readonly subject: string;
|
|
6
|
-
readonly
|
|
7
|
-
readonly
|
|
8
|
-
readonly text: string;
|
|
9
|
-
}[];
|
|
10
|
-
readonly footer: string;
|
|
18
|
+
readonly lines: readonly TextRow[];
|
|
19
|
+
readonly operatorEmail: string;
|
|
11
20
|
};
|
|
12
21
|
/** What the declarant entered; the only input of the receipt. */
|
|
13
22
|
export type TerminationDeclaration = {
|
|
@@ -21,17 +30,19 @@ export type TerminationDeclaration = {
|
|
|
21
30
|
/** The operator notice for a provider problem has no declarant data at all. */
|
|
22
31
|
export type OperatorNoticeDeclaration = Pick<TerminationDeclaration, "declarationType" | "terminationKind"> & Partial<Omit<TerminationDeclaration, "declarationType" | "terminationKind">>;
|
|
23
32
|
export declare function formatReceivedAt(iso: string, locale: ConsentLocale): string;
|
|
24
|
-
|
|
33
|
+
/** The receipt carries enum fields only: free text from an anonymous caller
|
|
34
|
+
* must not be echoed to an arbitrary address. */
|
|
35
|
+
export type ReceiptDeclaration = Pick<TerminationDeclaration, "declarationType" | "terminationKind">;
|
|
36
|
+
export type TerminationReceiptArgs = {
|
|
25
37
|
readonly locale: ConsentLocale;
|
|
26
38
|
readonly requestId: string;
|
|
27
39
|
readonly receivedAtIso: string;
|
|
28
|
-
readonly declaration:
|
|
40
|
+
readonly declaration: ReceiptDeclaration;
|
|
29
41
|
readonly operatorEmail: string;
|
|
30
42
|
};
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
export
|
|
34
|
-
export type RenderOperatorNoticeArgs = {
|
|
43
|
+
/** The content must not depend on whether (or how) the declaration matched a contract. */
|
|
44
|
+
export declare function terminationReceiptVariables(args: TerminationReceiptArgs): TerminationReceiptVariables;
|
|
45
|
+
export type OperatorNoticeArgs = {
|
|
35
46
|
readonly locale: ConsentLocale;
|
|
36
47
|
readonly requestId: string;
|
|
37
48
|
readonly receivedAtIso: string;
|
|
@@ -42,4 +53,5 @@ export type RenderOperatorNoticeArgs = {
|
|
|
42
53
|
readonly providerCancel?: ProviderCancelOutcome;
|
|
43
54
|
readonly operatorEmail: string;
|
|
44
55
|
};
|
|
45
|
-
export declare function
|
|
56
|
+
export declare function operatorNoticeVariables(args: OperatorNoticeArgs): OperatorNoticeVariables;
|
|
57
|
+
export {};
|