@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
|
@@ -2,12 +2,14 @@ import type { SubjectId } from "@cosmicdrift/kumiko-framework/crypto";
|
|
|
2
2
|
import type { DbConnection, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { type ConfigKeyDefinition, type ConfigScope, type Registry, type SessionUser, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
import { type KumikoError, type WriteFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
5
|
+
import type { EnvelopeCipher } from "@cosmicdrift/kumiko-framework/secrets";
|
|
5
6
|
export type ConfigRowLookup = {
|
|
6
7
|
readonly id: string;
|
|
7
8
|
readonly version: number;
|
|
8
9
|
readonly value: string | null;
|
|
9
10
|
};
|
|
10
11
|
export declare function findConfigRow(db: DbConnection | TenantDb, key: string, tenantId: TenantId, userId: string | null): Promise<ConfigRowLookup | null>;
|
|
12
|
+
export declare function configRowHoldsValue(row: ConfigRowLookup | null, keyDef: ConfigKeyDefinition | undefined, cipher: EnvelopeCipher | undefined, qualifiedKey: string, serializedValue: string): Promise<boolean>;
|
|
11
13
|
export type PrepareConfigWriteArgs = {
|
|
12
14
|
readonly registry: Registry;
|
|
13
15
|
readonly user: SessionUser;
|
|
@@ -6,6 +6,7 @@ import { ConfigScopes, extensionSelectorTargets, isEncryptedAtRest, SYSTEM_ROLE,
|
|
|
6
6
|
import { AccessDeniedError, InternalError, NotFoundError, UnprocessableError, ValidationError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
|
|
7
7
|
import { assertUnreachable } from "@cosmicdrift/kumiko-framework/utils";
|
|
8
8
|
import { ConfigErrors } from "./constants.js";
|
|
9
|
+
import { decryptStoredValue } from "./resolver.js";
|
|
9
10
|
import { configValuesTable } from "./table.js";
|
|
10
11
|
// Locate an existing config_values row by the (key, tenant, user) triple —
|
|
11
12
|
// the effective natural key. System-scope rows carry SYSTEM_TENANT_ID on
|
|
@@ -26,6 +27,24 @@ export async function findConfigRow(db, key, tenantId, userId) {
|
|
|
26
27
|
value: row.value ?? null,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
30
|
+
// Idempotency check for declarative writers: does the stored row already hold
|
|
31
|
+
// `serializedValue` (JSON of the plaintext)? Encrypted rows are decrypted
|
|
32
|
+
// first, since their ciphertext differs on every encrypt.
|
|
33
|
+
export async function configRowHoldsValue(row, keyDef, cipher, qualifiedKey, serializedValue) {
|
|
34
|
+
if (row?.value === null || row?.value === undefined)
|
|
35
|
+
return false;
|
|
36
|
+
if (!keyDef?.encrypted && !keyDef?.piiEncrypted)
|
|
37
|
+
return row.value === serializedValue;
|
|
38
|
+
if (!keyDef)
|
|
39
|
+
return false;
|
|
40
|
+
try {
|
|
41
|
+
return (await decryptStoredValue(row.value, keyDef, cipher, qualifiedKey)) === serializedValue;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Unreadable (rotated key, missing cipher/KMS): the caller rewrites the row, which is the repair.
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
29
48
|
export function prepareConfigWrite(args) {
|
|
30
49
|
const { registry, user, key, scope: requestedScope } = args;
|
|
31
50
|
const keyDef = registry.getConfigKey(key);
|
|
@@ -48,4 +48,4 @@ export declare const forgetSubjectWrite: import("@cosmicdrift/kumiko-types/defin
|
|
|
48
48
|
reason: z.ZodString;
|
|
49
49
|
}, z.core.$strip>, {
|
|
50
50
|
subjectKey: string;
|
|
51
|
-
}, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap>;
|
|
51
|
+
}, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap, undefined>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { requestContext } from "@cosmicdrift/kumiko-framework/api";
|
|
2
2
|
import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
|
|
3
|
-
import { runInSavepointIfSupported } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
3
|
+
import { fetchOne, runInSavepointIfSupported, runnerCanBeginTransaction, transaction, } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
4
4
|
import { computeBlindIndex, configuredBlindIndexKey, configuredPiiSubjectKms, subjectIdSchema, subjectIdToKey, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
5
5
|
import { nullBlindIndexesForSubject, recordEventsOwnedExclusivelyByTenant, recordRowExistsInTenant, recordRowOwningTenantId, subjectRowExistsInTenant, } from "@cosmicdrift/kumiko-framework/db";
|
|
6
6
|
import { defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -12,7 +12,7 @@ import * as z from "zod";
|
|
|
12
12
|
import { resolveRetentionPolicyForTenant } from "../../data-retention/index.js";
|
|
13
13
|
import { eraseNoteBodiesReachingSubject } from "../../notes-history-user-data/index.js";
|
|
14
14
|
import { revokeAllPatTokensForUser } from "../../personal-access-tokens/index.js";
|
|
15
|
-
import { USER_STATUS } from "../../user/index.js";
|
|
15
|
+
import { USER_STATUS, userTable } from "../../user/index.js";
|
|
16
16
|
import { denyIfTargetOutsideAdminTenant, isSystemAdminActor, updateUserLifecycle, } from "../../user-data-rights/index.js";
|
|
17
17
|
import { CRYPTO_SHREDDING_AGGREGATE_TYPE, CRYPTO_SHREDDING_FEATURE_NAME, RECORD_ENTITY_NOT_REGISTERED, SUBJECT_FORGET_DENIED_EVENT_NAME, SUBJECT_FORGOTTEN_EVENT_NAME, TARGET_RECORD_NOT_ADMIN_TENANT, TARGET_RECORD_RETENTION_BLOCK_DELETE, TARGET_TENANT_NOT_ADMIN_TENANT, } from "../constants.js";
|
|
18
18
|
export { subjectIdSchema };
|
|
@@ -241,22 +241,29 @@ async function sweepDerivedSubjectData(ctx, subject, subjectKey, crossTenantRunn
|
|
|
241
241
|
return sweepErrorLabel(err);
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
|
-
//
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
244
|
+
// Email subscribers and other non-user entities use user-style subject keys
|
|
245
|
+
// without a read_users row — the key erase is the GDPR-relevant part, so no row
|
|
246
|
+
// means nothing to close. For an existing row, failures propagate: the handler
|
|
247
|
+
// throws and the retry re-runs the (idempotent) erase plus the door close. With
|
|
248
|
+
// an outside-transaction runner that can open its own transaction, the door
|
|
249
|
+
// closes there and stays committed when the handler throws afterwards (sweep
|
|
250
|
+
// error). Otherwise a savepoint confines a failure to the handler transaction.
|
|
251
|
+
async function closeUserLoginDoor(ctx, userId, outsideRunner, handlerTxRunner) {
|
|
252
|
+
const userRow = await fetchOne(handlerTxRunner, userTable, { id: userId });
|
|
253
|
+
// skip: no user row for this subject key (e.g. email subscribers); there is no door to close.
|
|
254
|
+
if (!userRow)
|
|
255
|
+
return;
|
|
256
|
+
const closeDoor = async (runner) => {
|
|
257
|
+
await updateUserLifecycle(runner, userId, { status: USER_STATUS.Deleted });
|
|
258
|
+
if (ctx.registry.features.has("personal-access-tokens")) {
|
|
259
|
+
await revokeAllPatTokensForUser(runner, userId);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
if (outsideRunner && runnerCanBeginTransaction(outsideRunner)) {
|
|
263
|
+
await transaction(outsideRunner, closeDoor);
|
|
257
264
|
}
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
else {
|
|
266
|
+
await runInSavepointIfSupported(handlerTxRunner, closeDoor);
|
|
260
267
|
}
|
|
261
268
|
}
|
|
262
269
|
// Through the outside-transaction db when available, so the audit event commits
|
|
@@ -351,7 +358,6 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
351
358
|
userId: event.user.id,
|
|
352
359
|
eraseReason: event.payload.reason,
|
|
353
360
|
});
|
|
354
|
-
const cleanupError = await sweepDerivedSubjectData(ctx, subject, subjectKey, ctx.db.unsafeRaw(), { requestId, erasedBy: event.user.id });
|
|
355
361
|
// User subject: close the login door. DEK-erase makes the passwordHash
|
|
356
362
|
// ciphertext unreadable, but status + PATs are standalone credentials —
|
|
357
363
|
// the PAT resolver only checks revokedAt/expiresAt, NOT user.status
|
|
@@ -367,9 +373,13 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
367
373
|
// crash recovery is safe. User-feature guard: without the user feature
|
|
368
374
|
// read_users doesn't exist (crypto-only stack). Tenant subjects have no
|
|
369
375
|
// credentials.
|
|
376
|
+
// Runs before the sweep and in its own transaction: a failing sweep rolls the
|
|
377
|
+
// handler transaction back, and the handler tx holds no lock on this user's
|
|
378
|
+
// read_users row yet (only read gates ran), so there is no lock conflict.
|
|
370
379
|
if (raw.kind === "user" && ctx.registry.features.has("user")) {
|
|
371
|
-
await
|
|
380
|
+
await closeUserLoginDoor(ctx, raw.userId, ctx.dbOutsideTransaction?.unsafeRaw(), ctx.db.unsafeRaw());
|
|
372
381
|
}
|
|
382
|
+
const cleanupError = await sweepDerivedSubjectData(ctx, subject, subjectKey, ctx.db.unsafeRaw(), { requestId, erasedBy: event.user.id });
|
|
373
383
|
await appendSubjectForgotten(ctx, event, subjectAggregateId(raw), {
|
|
374
384
|
subjectKey,
|
|
375
385
|
reason: event.payload.reason,
|
|
@@ -11,7 +11,6 @@ export function createUpdateTenantFieldHandler(opts = {}) {
|
|
|
11
11
|
schema: updateFieldPayloadSchema,
|
|
12
12
|
access: { roles: opts.roles ?? DEFAULT_FIELD_DEFINITION_WRITE_ROLES },
|
|
13
13
|
description: "Replaces a tenant-owned custom-field definition with a complete new spec; serializedField.type may be omitted, in which case the stored type applies, and a different type is refused. Use it to relabel or re-constrain an existing field rather than to create or remove one.",
|
|
14
|
-
excludedFields: ["type"],
|
|
15
14
|
handler: async (event, ctx) => {
|
|
16
15
|
const payload = event.payload; // @cast-boundary engine-payload
|
|
17
16
|
const tenantId = event.user.tenantId;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_CURRENCIES, fieldToZod, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
3
|
import { SUPPORTED_FIELD_TYPES } from "../constants.js";
|
|
3
4
|
// Builds a Zod schema that validates a custom-field VALUE against its
|
|
4
5
|
// fieldDefinition. Reuses the framework's `fieldToZod` (Builder-Reuse /
|
|
@@ -29,10 +30,9 @@ const SUPPORTED_EMBEDDED_SUB_TYPES = new Set([
|
|
|
29
30
|
// resulting schema validates the type-shape only, not the constraint.
|
|
30
31
|
const CONSTRAINT_KEYS = ["required", "maxLength", "format", "default"];
|
|
31
32
|
export function buildCustomFieldValueSchema(parsedField) {
|
|
32
|
-
if (!parsedField
|
|
33
|
+
if (!isPlainObject(parsedField))
|
|
33
34
|
return null;
|
|
34
|
-
const
|
|
35
|
-
const rawType = obj["type"];
|
|
35
|
+
const rawType = parsedField["type"];
|
|
36
36
|
if (typeof rawType !== "string")
|
|
37
37
|
return null;
|
|
38
38
|
if (!SUPPORTED_TYPES_SET.has(rawType))
|
|
@@ -47,37 +47,36 @@ export function buildCustomFieldValueSchema(parsedField) {
|
|
|
47
47
|
// drops everywhere else.
|
|
48
48
|
let strippedSubSchema;
|
|
49
49
|
if (rawType === "embedded") {
|
|
50
|
-
const schema =
|
|
50
|
+
const schema = parsedField["schema"];
|
|
51
51
|
if (!schema || typeof schema !== "object")
|
|
52
52
|
return null;
|
|
53
53
|
strippedSubSchema = {};
|
|
54
54
|
for (const [subKey, sub] of Object.entries(schema)) {
|
|
55
|
-
if (!sub
|
|
55
|
+
if (!isPlainObject(sub))
|
|
56
56
|
return null;
|
|
57
|
-
const
|
|
58
|
-
const subType = subObj["type"];
|
|
57
|
+
const subType = sub["type"];
|
|
59
58
|
if (typeof subType !== "string" || !SUPPORTED_EMBEDDED_SUB_TYPES.has(subType)) {
|
|
60
59
|
return null;
|
|
61
60
|
}
|
|
62
|
-
const strippedSub = { ...
|
|
61
|
+
const strippedSub = { ...sub };
|
|
63
62
|
for (const k of CONSTRAINT_KEYS)
|
|
64
63
|
delete strippedSub[k];
|
|
65
64
|
strippedSubSchema[subKey] = strippedSub;
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
|
-
const fieldDef = { ...
|
|
67
|
+
const fieldDef = { ...parsedField };
|
|
69
68
|
for (const k of CONSTRAINT_KEYS)
|
|
70
69
|
delete fieldDef[k];
|
|
71
70
|
if (strippedSubSchema !== undefined)
|
|
72
71
|
fieldDef["schema"] = strippedSubSchema;
|
|
73
72
|
if (rawType === "enum") {
|
|
74
73
|
fieldDef["type"] = "select";
|
|
75
|
-
fieldDef["options"] =
|
|
74
|
+
fieldDef["options"] = parsedField["values"] ?? parsedField["options"] ?? [];
|
|
76
75
|
}
|
|
77
76
|
// fieldToZod's money case validates `currency` against the passed list, not
|
|
78
77
|
// a field-level key — so surface the field's own currency when it declares
|
|
79
78
|
// one, else fall back to the framework defaults.
|
|
80
|
-
const currencies = typeof
|
|
79
|
+
const currencies = typeof parsedField["currency"] === "string" ? [parsedField["currency"]] : DEFAULT_CURRENCIES;
|
|
81
80
|
// @cast-boundary serialized-field is the dehydrated r.field.X() output =
|
|
82
81
|
// a FieldDefinition; fieldToZod reads only its type-specific keys (the
|
|
83
82
|
// extra fieldAccess/retention/label keys are ignored).
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
// T1.5c — user-data-rights wiring for custom-fields.
|
|
2
2
|
import { extractTableName } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
|
+
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
4
5
|
import { selectCustomFieldsHostRows } from "./db/queries/user-data-rights.js";
|
|
5
6
|
function asCustomFieldsHostRow(value) {
|
|
6
|
-
if (!
|
|
7
|
+
if (!isPlainObject(value))
|
|
7
8
|
return null;
|
|
8
|
-
|
|
9
|
+
const id = value["id"];
|
|
10
|
+
if (typeof id !== "string")
|
|
9
11
|
return null;
|
|
10
|
-
const
|
|
11
|
-
const cf = record["custom_fields"] ?? record["customFields"];
|
|
12
|
+
const cf = value["custom_fields"] ?? value["customFields"];
|
|
12
13
|
if (cf === undefined)
|
|
13
14
|
return null;
|
|
14
15
|
if (cf === null)
|
|
15
|
-
return { id
|
|
16
|
+
return { id, customFields: null };
|
|
16
17
|
if (!cf || typeof cf !== "object" || Array.isArray(cf))
|
|
17
18
|
return null;
|
|
18
|
-
return { id
|
|
19
|
+
return { id, customFields: Object.fromEntries(Object.entries(cf)) };
|
|
19
20
|
}
|
|
20
21
|
// fw#2914 — selectCustomFieldsHostRows runs raw SQL against a dynamic host
|
|
21
22
|
// table name (opts.entityTable varies per call site), so it can't go through
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export type { EffectiveRetentionPolicy, ResolveForTenantArgs, ResolveRetentionPolicyArgs, ResolveTenantPresetArgs, RetentionOverride, RetentionPreset, RetentionPresetKey, } from "./feature.js";
|
|
2
2
|
export { createDataRetentionFeature, RETENTION_PRESETS, resolveRetentionPolicy, resolveRetentionPolicyForTenant, resolveTenantRetentionPreset, retentionOverrideSchema, SELECTABLE_RETENTION_PRESETS, tenantRetentionOverrideEntity, tenantRetentionOverrideTable, } from "./feature.js";
|
|
3
|
+
export { computeCutoff, type Instant } from "./keep-for.js";
|
|
@@ -1 +1,2 @@
|
|
|
1
1
|
export { createDataRetentionFeature, RETENTION_PRESETS, resolveRetentionPolicy, resolveRetentionPolicyForTenant, resolveTenantRetentionPreset, retentionOverrideSchema, SELECTABLE_RETENTION_PRESETS, tenantRetentionOverrideEntity, tenantRetentionOverrideTable, } from "./feature.js";
|
|
2
|
+
export { computeCutoff } from "./keep-for.js";
|
|
@@ -43,6 +43,7 @@ import { createEventStoreExecutor, createTenantDb, nullBlindIndexesForSubject, W
|
|
|
43
43
|
import { deleteStoredFileAndDerivatives } from "@cosmicdrift/kumiko-framework/derivatives";
|
|
44
44
|
import { createSystemUser, entityHasAnonymizableSubjectField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
45
45
|
import { fileRefEntity, fileRefsTable, } from "@cosmicdrift/kumiko-framework/files";
|
|
46
|
+
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
46
47
|
import { runInSubTransaction } from "../shared/index.js";
|
|
47
48
|
import { computeCutoff } from "./keep-for.js";
|
|
48
49
|
import { resolveRetentionPolicyForTenant } from "./resolve-for-tenant.js";
|
|
@@ -219,10 +220,9 @@ function collectSingleFileHolders(registry) {
|
|
|
219
220
|
const { singleFields } = planFileFields(entity.fields);
|
|
220
221
|
if (singleFields.length === 0)
|
|
221
222
|
continue;
|
|
222
|
-
const table = proj.table; // @cast-boundary column-presence probe
|
|
223
223
|
holders.push({
|
|
224
224
|
table: proj.table,
|
|
225
|
-
tableHasTenantId: table
|
|
225
|
+
tableHasTenantId: propertyOf(proj.table, "tenantId") !== undefined,
|
|
226
226
|
singleFields,
|
|
227
227
|
});
|
|
228
228
|
}
|
|
@@ -473,10 +473,9 @@ export async function runRetentionCleanup(args) {
|
|
|
473
473
|
const entity = registry.getEntity(entityName);
|
|
474
474
|
if (!entity)
|
|
475
475
|
continue;
|
|
476
|
-
const table = proj.table; // @cast-boundary column-presence probe
|
|
477
476
|
const declaredReference = policy.reference ?? DEFAULT_REFERENCE_FIELD;
|
|
478
477
|
const referenceField = FRAMEWORK_REFERENCE_ALIAS[declaredReference] ?? declaredReference;
|
|
479
|
-
if (table
|
|
478
|
+
if (propertyOf(proj.table, referenceField) === undefined) {
|
|
480
479
|
skipped.push({ entityName, reason: "missing_reference_column" });
|
|
481
480
|
continue;
|
|
482
481
|
}
|
|
@@ -485,7 +484,7 @@ export async function runRetentionCleanup(args) {
|
|
|
485
484
|
// Tenant-Scope nur wenn die Tabelle eine tenantId-Spalte hat — identisch zu
|
|
486
485
|
// soft-delete-cleanup. Ohne diesen Filter wuerde ein Tenant die Rows eines
|
|
487
486
|
// anderen treffen.
|
|
488
|
-
if (table
|
|
487
|
+
if (propertyOf(proj.table, "tenantId") !== undefined) {
|
|
489
488
|
where["tenantId"] = tenantId;
|
|
490
489
|
}
|
|
491
490
|
switch (policy.strategy) {
|
|
@@ -531,7 +530,8 @@ export async function runRetentionCleanup(args) {
|
|
|
531
530
|
break;
|
|
532
531
|
}
|
|
533
532
|
case "softDelete": {
|
|
534
|
-
if (table
|
|
533
|
+
if (propertyOf(proj.table, "isDeleted") === undefined ||
|
|
534
|
+
propertyOf(proj.table, "deletedAt") === undefined) {
|
|
535
535
|
skipped.push({ entityName, reason: "missing_softdelete_columns" });
|
|
536
536
|
break;
|
|
537
537
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import type { FileAttachmentRef, InlineAttachmentRef, RenderedPdfAttachmentRef } from "../renderer-foundation/index.js";
|
|
3
|
+
export type { FileAttachmentRef, InlineAttachmentRef, RenderedPdfAttachmentRef };
|
|
4
|
+
export type EmailAttachmentRef = InlineAttachmentRef | FileAttachmentRef | RenderedPdfAttachmentRef;
|
|
5
|
+
export declare const MAX_EMAIL_ATTACHMENTS = 20;
|
|
6
|
+
export declare const MAX_RENDERED_PDF_VARIABLES_BYTES = 64000;
|
|
7
|
+
export declare const DELIVERY_ENVELOPE_DATA_KEYS: readonly ["attachments", "from", "fromName", "replyTo", "headers", "unsubscribeUrl"];
|
|
8
|
+
export declare function withoutDeliveryEnvelopeKeys(variables: Readonly<Record<string, unknown>>): Readonly<Record<string, unknown>>;
|
|
9
|
+
export declare const inlineAttachmentRefSchema: z.ZodObject<{
|
|
10
|
+
kind: z.ZodLiteral<"inline">;
|
|
11
|
+
cid: z.ZodString;
|
|
12
|
+
fileRefId: z.ZodString;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
export declare const fileAttachmentRefSchema: z.ZodObject<{
|
|
15
|
+
kind: z.ZodLiteral<"file">;
|
|
16
|
+
fileRefId: z.ZodString;
|
|
17
|
+
fileName: z.ZodString;
|
|
18
|
+
}, z.core.$strict>;
|
|
19
|
+
export declare const renderedPdfAttachmentRefSchema: z.ZodObject<{
|
|
20
|
+
kind: z.ZodLiteral<"rendered-pdf">;
|
|
21
|
+
templateSlug: z.ZodString;
|
|
22
|
+
variables: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
23
|
+
fileName: z.ZodString;
|
|
24
|
+
locale: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
export declare const emailAttachmentRefSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
27
|
+
kind: z.ZodLiteral<"inline">;
|
|
28
|
+
cid: z.ZodString;
|
|
29
|
+
fileRefId: z.ZodString;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
kind: z.ZodLiteral<"file">;
|
|
32
|
+
fileRefId: z.ZodString;
|
|
33
|
+
fileName: z.ZodString;
|
|
34
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
35
|
+
kind: z.ZodLiteral<"rendered-pdf">;
|
|
36
|
+
templateSlug: z.ZodString;
|
|
37
|
+
variables: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
38
|
+
fileName: z.ZodString;
|
|
39
|
+
locale: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, z.core.$strict>], "kind">;
|
|
41
|
+
export declare function toAttachmentRef(ref: EmailAttachmentRef): EmailAttachmentRef;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { attachmentFileNameSchema } from "../shared/index.js";
|
|
3
|
+
import { isDocumentResourceKey, templateSlugSchema } from "../template-resolver/index.js";
|
|
4
|
+
export const MAX_EMAIL_ATTACHMENTS = 20;
|
|
5
|
+
export const MAX_RENDERED_PDF_VARIABLES_BYTES = 64_000;
|
|
6
|
+
// Channel-data keys that steer delivery itself (envelope, headers, attachments);
|
|
7
|
+
// they are not document variables and must not be copied into attached PDF refs.
|
|
8
|
+
export const DELIVERY_ENVELOPE_DATA_KEYS = [
|
|
9
|
+
"attachments",
|
|
10
|
+
"from",
|
|
11
|
+
"fromName",
|
|
12
|
+
"replyTo",
|
|
13
|
+
"headers",
|
|
14
|
+
"unsubscribeUrl",
|
|
15
|
+
];
|
|
16
|
+
const DELIVERY_ENVELOPE_DATA_KEY_SET = new Set(DELIVERY_ENVELOPE_DATA_KEYS);
|
|
17
|
+
export function withoutDeliveryEnvelopeKeys(variables) {
|
|
18
|
+
return Object.fromEntries(Object.entries(variables).filter(([key]) => !DELIVERY_ENVELOPE_DATA_KEY_SET.has(key)));
|
|
19
|
+
}
|
|
20
|
+
const MAX_ID_LENGTH = 64;
|
|
21
|
+
const fileRefIdSchema = z.string().min(1).max(MAX_ID_LENGTH);
|
|
22
|
+
export const inlineAttachmentRefSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
kind: z.literal("inline"),
|
|
25
|
+
cid: z.string().min(1).max(MAX_ID_LENGTH).refine(isDocumentResourceKey),
|
|
26
|
+
fileRefId: fileRefIdSchema,
|
|
27
|
+
})
|
|
28
|
+
.strict();
|
|
29
|
+
export const fileAttachmentRefSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
kind: z.literal("file"),
|
|
32
|
+
fileRefId: fileRefIdSchema,
|
|
33
|
+
fileName: attachmentFileNameSchema,
|
|
34
|
+
})
|
|
35
|
+
.strict();
|
|
36
|
+
export const renderedPdfAttachmentRefSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
kind: z.literal("rendered-pdf"),
|
|
39
|
+
templateSlug: templateSlugSchema,
|
|
40
|
+
variables: z
|
|
41
|
+
.record(z.string(), z.unknown())
|
|
42
|
+
.refine((value) => Buffer.byteLength(JSON.stringify(value)) <= MAX_RENDERED_PDF_VARIABLES_BYTES, {
|
|
43
|
+
message: `variables must not exceed ${MAX_RENDERED_PDF_VARIABLES_BYTES} bytes as JSON`,
|
|
44
|
+
}),
|
|
45
|
+
fileName: attachmentFileNameSchema.refine((name) => name.toLowerCase().endsWith(".pdf"), {
|
|
46
|
+
message: "file name must end with .pdf",
|
|
47
|
+
}),
|
|
48
|
+
locale: z
|
|
49
|
+
.string()
|
|
50
|
+
.min(2)
|
|
51
|
+
.max(8)
|
|
52
|
+
.regex(/^[a-z]{2}(-[a-z]{2})?$/i, "locale must be ISO 639-1 (e.g. de, en, en-us)")
|
|
53
|
+
.optional(),
|
|
54
|
+
})
|
|
55
|
+
.strict();
|
|
56
|
+
export const emailAttachmentRefSchema = z.discriminatedUnion("kind", [
|
|
57
|
+
inlineAttachmentRefSchema,
|
|
58
|
+
fileAttachmentRefSchema,
|
|
59
|
+
renderedPdfAttachmentRefSchema,
|
|
60
|
+
]);
|
|
61
|
+
// Rebuilds only the contract fields so bytes a caller attached to a ref object
|
|
62
|
+
// can never ride into a job payload.
|
|
63
|
+
export function toAttachmentRef(ref) {
|
|
64
|
+
switch (ref.kind) {
|
|
65
|
+
case "inline":
|
|
66
|
+
return { kind: "inline", cid: ref.cid, fileRefId: ref.fileRefId };
|
|
67
|
+
case "file":
|
|
68
|
+
return { kind: "file", fileRefId: ref.fileRefId, fileName: ref.fileName };
|
|
69
|
+
case "rendered-pdf":
|
|
70
|
+
return {
|
|
71
|
+
kind: "rendered-pdf",
|
|
72
|
+
templateSlug: ref.templateSlug,
|
|
73
|
+
variables: ref.variables,
|
|
74
|
+
fileName: ref.fileName,
|
|
75
|
+
...(ref.locale !== undefined && { locale: ref.locale }),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { SseBroker } from "@cosmicdrift/kumiko-framework/api";
|
|
2
|
-
import { type DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
3
|
-
import type { Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { type DbConnection, type TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
3
|
+
import type { ConfigAccessor, Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
|
+
import type { FileContext } from "@cosmicdrift/kumiko-framework/files";
|
|
4
5
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
5
|
-
import type
|
|
6
|
-
|
|
6
|
+
import { type MailPayload } from "../renderer-foundation/index.js";
|
|
7
|
+
import type { ChannelContext, RenderedMail } from "./types.js";
|
|
8
|
+
export declare function createTemplateMailRenderer(db: DbConnection | TenantDb, registry: Registry, tenantId: TenantId, config: ConfigAccessor | undefined): (payload: MailPayload) => Promise<RenderedMail>;
|
|
9
|
+
export declare function createEmailAttachmentReader(db: DbConnection | TenantDb, registry: Registry, tenantId: TenantId, config: ConfigAccessor | undefined, filesForTenant: (tenantId: string) => FileContext | undefined): NonNullable<ChannelContext["readAttachment"]>;
|
|
10
|
+
export declare function buildChannelContext(db: DbConnection, registry: Registry, sseBroker: SseBroker | undefined, tenantId: TenantId, secrets?: SecretsContext, tenantConfig?: ConfigAccessor, filesForTenant?: (tenantId: string) => FileContext | undefined): ChannelContext;
|
|
@@ -1,8 +1,100 @@
|
|
|
1
1
|
import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
+
import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
|
|
4
|
+
import { readFileRefContent } from "../file-foundation/index.js";
|
|
5
|
+
import { collectRendererPlugins, createRendererFoundationApi, RendererError, } from "../renderer-foundation/index.js";
|
|
6
|
+
import { FALLBACK_LOCALE } from "../template-resolver/index.js";
|
|
7
|
+
export function createTemplateMailRenderer(db, registry, tenantId, config) {
|
|
8
|
+
return async (payload) => {
|
|
9
|
+
const plugin = createRendererFoundationApi(collectRendererPlugins(registry)).createRendererForTenant({ tenantId, kind: "mail" });
|
|
10
|
+
const response = await plugin.render({ kind: "mail", payload }, { db, registry, tenantId, ...(config !== undefined && { config }) });
|
|
11
|
+
if (response.kind !== "mail") {
|
|
12
|
+
throw new RendererError(`[delivery] renderer "${plugin.name}" answered a mail request with kind "${response.kind}"`, "other");
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
subject: response.subject,
|
|
16
|
+
html: response.html,
|
|
17
|
+
text: response.text,
|
|
18
|
+
...(response.previewText !== undefined && { previewText: response.previewText }),
|
|
19
|
+
...(response.fromName !== undefined && { fromName: response.fromName }),
|
|
20
|
+
...(response.replyTo !== undefined && { replyTo: response.replyTo }),
|
|
21
|
+
...(response.attachments !== undefined && { attachments: response.attachments }),
|
|
22
|
+
...(response.layout !== undefined && { layout: response.layout }),
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const INLINE_IMAGE_CONTENT_TYPE_PREFIX = "image/";
|
|
27
|
+
const PDF_CONTENT_TYPE = "application/pdf";
|
|
28
|
+
// Renders at send time so the job payload carries variables, not bytes. A failure throws:
|
|
29
|
+
// the send job retries instead of mailing without the document the recipient expects.
|
|
30
|
+
function createPdfRenderer(db, registry, tenantId, config, filesForTenant) {
|
|
31
|
+
return async (ref) => {
|
|
32
|
+
const plugin = createRendererFoundationApi(collectRendererPlugins(registry)).createRendererForTenant({ tenantId, kind: "document-pdf" });
|
|
33
|
+
const response = await plugin.render({
|
|
34
|
+
kind: "document-pdf",
|
|
35
|
+
payload: {
|
|
36
|
+
slug: ref.templateSlug,
|
|
37
|
+
locale: ref.locale ?? FALLBACK_LOCALE,
|
|
38
|
+
variables: ref.variables,
|
|
39
|
+
},
|
|
40
|
+
}, { db, registry, tenantId, filesForTenant, ...(config !== undefined && { config }) });
|
|
41
|
+
if (response.kind !== "document-pdf") {
|
|
42
|
+
throw new RendererError(`[delivery] renderer "${plugin.name}" answered a document-pdf request with kind "${response.kind}"`, "other");
|
|
43
|
+
}
|
|
44
|
+
return { content: response.pdfBytes, contentType: PDF_CONTENT_TYPE };
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// A decorative inline image (logo) that cannot be read must not fail the whole mail.
|
|
48
|
+
async function readInlineImageOrNull(fileRefId, read) {
|
|
49
|
+
try {
|
|
50
|
+
return await read();
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
createFallbackLogger("delivery").warn("inline image could not be read, sending without it", {
|
|
54
|
+
fileRefId,
|
|
55
|
+
errorName: err instanceof Error ? err.name : typeof err,
|
|
56
|
+
});
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Inline images and file attachments the renderer took from a template may come from the system
|
|
61
|
+
// tenant (system template or tenant override of one). A file ref from notify data stays limited to
|
|
62
|
+
// the job's own tenant, since a caller picks it. Inline content that is not an image is dropped, so
|
|
63
|
+
// a swapped fileRef id cannot smuggle a document into the mail body.
|
|
64
|
+
export function createEmailAttachmentReader(db, registry, tenantId, config, filesForTenant) {
|
|
65
|
+
const renderPdf = createPdfRenderer(db, registry, tenantId, config, filesForTenant);
|
|
66
|
+
return async (ref, origin = "message") => {
|
|
67
|
+
if (ref.kind === "rendered-pdf")
|
|
68
|
+
return renderPdf(ref);
|
|
69
|
+
const readRef = () => readFileRefContent({
|
|
70
|
+
db,
|
|
71
|
+
filesForTenant,
|
|
72
|
+
fileRefId: ref.fileRefId,
|
|
73
|
+
allowedTenantIds: ref.kind === "file" && origin === "message" ? [tenantId] : [tenantId, SYSTEM_TENANT_ID],
|
|
74
|
+
});
|
|
75
|
+
const found = ref.kind === "inline" ? await readInlineImageOrNull(ref.fileRefId, readRef) : await readRef();
|
|
76
|
+
if (found === null)
|
|
77
|
+
return null;
|
|
78
|
+
if (ref.kind === "inline" && !found.contentType.startsWith(INLINE_IMAGE_CONTENT_TYPE_PREFIX)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return { content: found.content, contentType: found.contentType };
|
|
82
|
+
};
|
|
83
|
+
}
|
|
2
84
|
// Build the per-tenant context a channel's resolve/render/send receives.
|
|
3
85
|
// Shared by the synchronous delivery-service path and the async job handlers
|
|
4
86
|
// (which pass sseBroker=undefined — only the inline inApp channel uses SSE,
|
|
5
87
|
// and it never runs through a job).
|
|
6
|
-
export function buildChannelContext(db, registry, sseBroker, tenantId, secrets) {
|
|
7
|
-
return {
|
|
88
|
+
export function buildChannelContext(db, registry, sseBroker, tenantId, secrets, tenantConfig, filesForTenant) {
|
|
89
|
+
return {
|
|
90
|
+
db: createTenantDb(db, tenantId),
|
|
91
|
+
registry,
|
|
92
|
+
sseBroker,
|
|
93
|
+
tenantId,
|
|
94
|
+
secrets,
|
|
95
|
+
renderMail: createTemplateMailRenderer(db, registry, tenantId, tenantConfig),
|
|
96
|
+
...(filesForTenant !== undefined && {
|
|
97
|
+
readAttachment: createEmailAttachmentReader(db, registry, tenantId, tenantConfig, filesForTenant),
|
|
98
|
+
}),
|
|
99
|
+
};
|
|
8
100
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { NotifyPriority } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
export declare const DELIVERY_CHANNEL_EXTENSION: "deliveryChannel";
|
|
3
|
+
export declare const EMAIL_CHANNEL_NAME: "email";
|
|
3
4
|
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_ATTEMPT_EVENT, DELIVERY_CHANNEL_CELL_COMPONENT, DELIVERY_ERROR_CELL_COMPONENT, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_RESUBSCRIBE_PATH, DELIVERY_STATUS_CELL_COMPONENT, DELIVERY_TIME_CELL_COMPONENT, DELIVERY_TYPE_CELL_COMPONENT, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobNames, DeliveryQueries, DeliveryStatus, type DeliveryStatusValue, } from "./public-names.js";
|
|
4
5
|
export declare function deliveryIdempotencyRedisKey(tenantId: string, key: string): string;
|
|
5
6
|
export declare const deliveryPriorityRank: Record<NotifyPriority, number>;
|
|
@@ -3,6 +3,7 @@ import { DELIVERY_FEATURE, DeliveryJobNames } from "./public-names.js";
|
|
|
3
3
|
// Extension-point name for delivery-channel plugins (channel-email,
|
|
4
4
|
// channel-in-app, channel-push, ...).
|
|
5
5
|
export const DELIVERY_CHANNEL_EXTENSION = "deliveryChannel";
|
|
6
|
+
export const EMAIL_CHANNEL_NAME = "email";
|
|
6
7
|
export { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, DELIVERY_ATTEMPT_EVENT, DELIVERY_CHANNEL_CELL_COMPONENT, DELIVERY_ERROR_CELL_COMPONENT, DELIVERY_FEATURE, DELIVERY_LOG_SCREEN_ID, DELIVERY_RESUBSCRIBE_PATH, DELIVERY_STATUS_CELL_COMPONENT, DELIVERY_TIME_CELL_COMPONENT, DELIVERY_TYPE_CELL_COMPONENT, DELIVERY_UNSUBSCRIBE_PATH, DeliveryErrors, DeliveryHandlers, DeliveryJobNames, DeliveryQueries, DeliveryStatus, } from "./public-names.js";
|
|
7
8
|
// Single source for claim (delivery-service) and terminal-failure release (jobs).
|
|
8
9
|
export function deliveryIdempotencyRedisKey(tenantId, key) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SseBroker } from "@cosmicdrift/kumiko-framework/api";
|
|
2
2
|
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
3
|
-
import type { EscapeHatchAuditSink, NotifyJobDispatcher, Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
+
import type { ConfigAccessor, EscapeHatchAuditSink, NotifyJobDispatcher, Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
|
+
import type { FileContext } from "@cosmicdrift/kumiko-framework/files";
|
|
4
5
|
import { type Logger } from "@cosmicdrift/kumiko-framework/logging";
|
|
5
6
|
import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
|
|
6
7
|
import type { Redis } from "ioredis";
|
|
@@ -23,6 +24,8 @@ export type DeliveryServiceOptions = {
|
|
|
23
24
|
readonly idempotencyRedis?: Redis;
|
|
24
25
|
readonly jobRunner?: NotifyJobDispatcher;
|
|
25
26
|
readonly secrets?: SecretsContext;
|
|
27
|
+
readonly filesForTenant?: (tenantId: string) => FileContext | undefined;
|
|
28
|
+
readonly tenantConfigFor?: (tenantId: TenantId) => ConfigAccessor;
|
|
26
29
|
readonly escapeHatchAuditSink?: EscapeHatchAuditSink;
|
|
27
30
|
readonly log?: Logger;
|
|
28
31
|
};
|