@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.388.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/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.d.ts +7 -7
- package/dist/agent-tools/tool-dispatch.js +9 -9
- package/dist/audit/handlers/audit-events.js +1 -1
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/feature-exports.d.ts +2 -2
- package/dist/auth-mfa/feature.js +8 -0
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +8 -4
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-code-or-recovery-field.d.ts +11 -0
- package/dist/auth-mfa/web/mfa-code-or-recovery-field.js +12 -0
- package/dist/auth-mfa/web/mfa-disable-dialog.js +14 -3
- package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +14 -3
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +10 -5
- package/dist/auth-mfa/web/mfa-verify-screen.js +32 -11
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/checkout-core.d.ts +9 -14
- package/dist/billing-foundation/checkout-core.js +24 -39
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +8 -2
- package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +1 -0
- package/dist/billing-foundation/consumer-protection/consent-gate.js +1 -0
- package/dist/billing-foundation/consumer-protection/issue-confirmation.js +9 -3
- package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +4 -2
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +6 -5
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +5 -1
- package/dist/billing-foundation/consumer-protection/termination-record.js +27 -17
- package/dist/billing-foundation/consumer-protection/termination-request.js +12 -7
- package/dist/billing-foundation/consumer-protection/termination-revoke.js +12 -7
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/termination-texts.js +3 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +5 -2
- package/dist/billing-foundation/consumer-protection/withdrawal-period.js +8 -9
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.d.ts +1 -0
- package/dist/billing-foundation/events.js +19 -17
- package/dist/billing-foundation/feature.js +45 -44
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/billing-plans.query.js +35 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +19 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/plan-switch-preview.query.d.ts +13 -0
- package/dist/billing-foundation/handlers/plan-switch-preview.query.js +48 -0
- package/dist/billing-foundation/handlers/process-event.write.d.ts +6 -0
- package/dist/billing-foundation/handlers/process-event.write.js +28 -22
- package/dist/billing-foundation/handlers/start-plan-checkout.write.js +32 -5
- package/dist/billing-foundation/handlers/switch-plan.write.d.ts +2 -2
- package/dist/billing-foundation/handlers/switch-plan.write.js +56 -64
- package/dist/billing-foundation/handlers/sync-subscription.write.js +12 -1
- package/dist/billing-foundation/i18n.js +22 -0
- package/dist/billing-foundation/index.d.ts +1 -1
- package/dist/billing-foundation/plan-catalog.d.ts +21 -5
- package/dist/billing-foundation/plan-catalog.js +25 -16
- package/dist/billing-foundation/plan-switch.d.ts +12 -0
- package/dist/billing-foundation/plan-switch.js +60 -0
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +97 -42
- package/dist/billing-foundation/types.js +29 -20
- package/dist/billing-foundation/validate-options.js +17 -0
- package/dist/billing-foundation/web/billing-plans-panel.js +82 -36
- package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +17 -3
- package/dist/billing-foundation/web/checkout-consent-dialog.js +14 -10
- package/dist/billing-foundation/web/constants.d.ts +4 -0
- package/dist/billing-foundation/web/constants.js +4 -0
- package/dist/billing-foundation/web/plan-price.d.ts +15 -0
- package/dist/billing-foundation/web/plan-price.js +32 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.d.ts +15 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +66 -0
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/cap-reservation.js +5 -1
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +49 -49
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +8 -2
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/feature.js +1 -1
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/cascade.query.d.ts +5 -0
- package/dist/config/handlers/cascade.query.js +4 -3
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/handlers/values.query.d.ts +5 -0
- package/dist/config/handlers/values.query.js +4 -3
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.d.ts +1 -0
- package/dist/config/write-helpers.js +19 -10
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +25 -21
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/channel-context.js +6 -3
- package/dist/delivery/db/queries/preferences.js +2 -2
- package/dist/delivery/delivery-service.js +22 -7
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/handlers/preferences.query.d.ts +1 -1
- package/dist/delivery/handlers/preferences.query.js +20 -1
- package/dist/delivery/handlers/unsubscribe-page-chrome.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe-link.d.ts +3 -1
- package/dist/delivery/unsubscribe-page-strings.d.ts +1 -0
- package/dist/delivery/unsubscribe-page-strings.js +1 -0
- package/dist/delivery/unsubscribe-page.d.ts +2 -0
- package/dist/delivery/unsubscribe-page.js +5 -0
- package/dist/delivery/unsubscribe.js +29 -11
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-foundation/index.d.ts +1 -1
- package/dist/file-foundation/index.js +1 -1
- package/dist/file-foundation/read-file-ref-content.d.ts +3 -0
- package/dist/file-foundation/read-file-ref-content.js +6 -1
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/env-named-feature.d.ts +0 -2
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +3 -3
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/decrypt-draft.js +5 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/host-routing/dispatch.js +11 -20
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +2 -2
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +22 -14
- package/dist/inbound-mail-foundation/i18n.js +0 -1
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/screens.js +0 -3
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +49 -49
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +85 -67
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.d.ts +1 -0
- package/dist/jobs/feature.js +13 -10
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/handlers/tenant-failures.query.d.ts +1 -1
- package/dist/jobs/handlers/tenant-failures.query.js +45 -41
- package/dist/jobs/handlers/tenant-runs.query.d.ts +1 -1
- package/dist/jobs/handlers/tenant-runs.query.js +54 -50
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +15 -15
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +5 -5
- package/dist/mail-foundation/feature.js +27 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.d.ts +1 -1
- package/dist/personal-access-tokens/feature.js +9 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/renderer-pdf/render-table-pdf.d.ts +1 -1
- package/dist/renderer-pdf/render-table-pdf.js +22 -10
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.d.ts +2 -2
- package/dist/sessions/feature.js +12 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.d.ts +1 -0
- package/dist/shared/decrypt-stored-pii.js +7 -2
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/mail-template-body.d.ts +6 -2
- package/dist/shared/mail-template-body.js +7 -4
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/step-dispatcher/feature.js +1 -0
- package/dist/subscription-dodo/client.d.ts +17 -0
- package/dist/subscription-dodo/client.js +31 -0
- package/dist/subscription-dodo/constants.d.ts +12 -0
- package/dist/subscription-dodo/constants.js +19 -0
- package/dist/subscription-dodo/feature.d.ts +37 -0
- package/dist/subscription-dodo/feature.js +144 -0
- package/dist/subscription-dodo/index.d.ts +2 -0
- package/dist/subscription-dodo/index.js +4 -0
- package/dist/subscription-dodo/plugin-methods.d.ts +23 -0
- package/dist/subscription-dodo/plugin-methods.js +260 -0
- package/dist/subscription-dodo/runtime.d.ts +27 -0
- package/dist/subscription-dodo/runtime.js +89 -0
- package/dist/subscription-dodo/verify-webhook.d.ts +37 -0
- package/dist/subscription-dodo/verify-webhook.js +189 -0
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +36 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +8 -7
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.d.ts +3 -2
- package/dist/template-resolver/api.js +34 -12
- package/dist/template-resolver/compile-document-body.js +1 -0
- package/dist/template-resolver/feature.js +2 -2
- package/dist/template-resolver/handlers/bundle-import.js +3 -3
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +5 -1
- package/dist/template-resolver/handlers/copy-locale.write.js +22 -7
- package/dist/template-resolver/handlers/diff-to-system.query.js +3 -2
- package/dist/template-resolver/handlers/document-base.js +3 -2
- package/dist/template-resolver/handlers/find-by-id.query.js +8 -7
- package/dist/template-resolver/handlers/list.query.js +6 -7
- package/dist/template-resolver/handlers/overview.query.d.ts +3 -0
- package/dist/template-resolver/handlers/overview.query.js +6 -3
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/tenant-override-counts.query.js +1 -3
- package/dist/template-resolver/handlers/tenant-override-selection.d.ts +2 -1
- package/dist/template-resolver/handlers/tenant-overrides.query.js +28 -5
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/handlers/usage.query.d.ts +2 -1
- package/dist/template-resolver/handlers/usage.query.js +26 -16
- package/dist/template-resolver/handlers/validate.query.js +7 -2
- package/dist/template-resolver/seeding.js +30 -14
- package/dist/template-resolver/store-template-resource.d.ts +1 -0
- package/dist/template-resolver/store-template-resource.js +19 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/template-delivery-policy.d.ts +0 -5
- package/dist/template-resolver/template-delivery-policy.js +0 -6
- package/dist/template-resolver/template-meta.js +7 -4
- package/dist/template-resolver/template-preview.js +4 -3
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/template-resolver/web/constants.d.ts +2 -2
- package/dist/template-resolver/web/constants.js +3 -3
- package/dist/template-resolver/web/index.d.ts +1 -0
- package/dist/template-resolver/web/index.js +1 -0
- package/dist/template-resolver/web/mail-layout-constants.d.ts +5 -0
- package/dist/template-resolver/web/mail-layout-constants.js +7 -0
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.d.ts +1 -0
- package/dist/tenant/handlers/member-directory.query.js +11 -4
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.d.ts +1 -0
- package/dist/tenant/handlers/tenant-directory.query.js +9 -5
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/constants.d.ts +1 -0
- package/dist/tenant-lifecycle/constants.js +4 -0
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -2
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +7 -8
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +7 -4
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/constants.js +2 -2
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +130 -237
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +65 -83
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/waitlist/handlers/export-purge.write.js +2 -1
- package/dist/waitlist/handlers/submit.write.js +5 -5
- package/dist/waitlist/import.d.ts +1 -0
- package/dist/waitlist/import.js +4 -0
- package/dist/waitlist/legacy-migrate.js +17 -6
- package/dist/waitlist/link-on-signup.js +18 -6
- package/dist/waitlist/options.d.ts +3 -0
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +20 -10
- package/src/agent-tools/changes.json +6 -0
- package/src/audit/changes.json +12 -0
- package/src/auth-mfa/changes.json +6 -0
- package/src/billing-foundation/changes.json +55 -0
- package/src/cap-counter/changes.json +18 -0
- package/src/channel-email/changes.json +6 -0
- package/src/config/changes.json +12 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/delivery/changes.json +30 -0
- package/src/form-draft/changes.json +6 -0
- package/src/host-routing/changes.json +6 -0
- package/src/inbound-mail-foundation/changes.json +18 -0
- package/src/jobs/changes.json +13 -0
- package/src/mail-foundation/changes.json +6 -0
- package/src/renderer-pdf/changes.json +6 -0
- package/src/step-dispatcher/changes.json +6 -0
- package/src/subscription-dodo/changes.json +14 -0
- package/src/subscription-stripe/changes.json +12 -0
- package/src/template-resolver/changes.json +48 -0
- package/src/tenant/changes.json +6 -0
- package/src/tenant-lifecycle/changes.json +6 -0
- package/src/tier-engine/changes.json +6 -0
- package/src/waitlist/changes.json +18 -0
- package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +0 -1
- package/dist/billing-foundation/consumer-protection/stored-user-email.js +0 -8
|
@@ -2,8 +2,9 @@ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { NotFoundError } from "@cosmicdrift/kumiko-framework/errors";
|
|
4
4
|
import * as z from "zod";
|
|
5
|
+
import { isRowDeliveredTo } from "../api.js";
|
|
5
6
|
import { templateResourcesTable } from "../table.js";
|
|
6
|
-
import { deliveryPolicyOf
|
|
7
|
+
import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
7
8
|
import { isHiddenSystemDraft } from "../template-draft.js";
|
|
8
9
|
import { buildOverrideDiff } from "./override-diff.js";
|
|
9
10
|
export const diffToSystemQuery = defineQueryHandler({
|
|
@@ -18,7 +19,7 @@ export const diffToSystemQuery = defineQueryHandler({
|
|
|
18
19
|
if (!tenantRow ||
|
|
19
20
|
tenantRow.tenantId !== query.user.tenantId ||
|
|
20
21
|
tenantRow.scope !== "tenant" ||
|
|
21
|
-
!
|
|
22
|
+
!(await isRowDeliveredTo(ctx.db, deliveryPolicyOf(ctx.registry), query.user, tenantRow))) {
|
|
22
23
|
throw new NotFoundError("template-resource", query.payload.id);
|
|
23
24
|
}
|
|
24
25
|
const systemRow = await fetchOne(ctx.db, templateResourcesTable, {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
4
|
+
import { isRowDeliveredTo } from "../api.js";
|
|
4
5
|
import { templateResourcesTable } from "../table.js";
|
|
5
|
-
import { deliveryPolicyOf
|
|
6
|
+
import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
6
7
|
import { isHiddenSystemDraft, toWorkingRow } from "../template-draft.js";
|
|
7
8
|
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
8
9
|
import { parseStoredJson } from "./template-gates.js";
|
|
@@ -20,7 +21,7 @@ export async function loadDocumentBase(ctx, user, where) {
|
|
|
20
21
|
// A locked override is neither shown nor edited by a non-SystemAdmin; the served system default is.
|
|
21
22
|
const ownIsVisible = own !== undefined &&
|
|
22
23
|
!isSystemOnlyTemplateHiddenFrom(user, ctx.registry, own) &&
|
|
23
|
-
|
|
24
|
+
(await isRowDeliveredTo(ctx.db, deliveryPolicyOf(ctx.registry), user, own));
|
|
24
25
|
if (own !== undefined && ownIsVisible) {
|
|
25
26
|
const working = toWorkingRow(own, user.tenantId);
|
|
26
27
|
return {
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
|
+
import { isRowDeliveredTo } from "../api.js";
|
|
4
5
|
import { templateResourcesTable } from "../table.js";
|
|
5
|
-
import { deliveryPolicyOf
|
|
6
|
+
import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
6
7
|
import { draftViewerTenantId, isHiddenSystemDraft, toWorkingRow } from "../template-draft.js";
|
|
7
8
|
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
8
|
-
// Admin
|
|
9
|
-
// archived
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
9
|
+
// Admin lookup for the UI editing flow. Returns the raw template, including draft/
|
|
10
|
+
// archived status. Tenant isolation: users see only templates belonging to their own
|
|
11
|
+
// tenant or SYSTEM_TENANT (system defaults are publicly readable); ctx.db is tenant-
|
|
12
|
+
// scoped for every role, so the check below is defense in depth. Anonymous access is
|
|
13
|
+
// excluded—public reads go through resolveTemplate in the API, not here.
|
|
13
14
|
export const findByIdQuery = defineQueryHandler({
|
|
14
15
|
name: "find-by-id",
|
|
15
16
|
schema: z.object({ id: z.string().min(1) }),
|
|
@@ -22,7 +23,7 @@ export const findByIdQuery = defineQueryHandler({
|
|
|
22
23
|
if (!stored ||
|
|
23
24
|
isHiddenSystemDraft(query.user, stored) ||
|
|
24
25
|
isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, stored) ||
|
|
25
|
-
!
|
|
26
|
+
!(await isRowDeliveredTo(ctx.db, deliveryPolicyOf(ctx.registry), query.user, stored))) {
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
28
29
|
const row = toWorkingRow(stored, draftViewerTenantId(query.user, stored));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
|
+
import { filterDeliveredTo } from "../api.js";
|
|
4
5
|
import { templateResourcesTable } from "../table.js";
|
|
5
|
-
import { deliveryPolicyOf
|
|
6
|
+
import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
6
7
|
import { isHiddenSystemDraft } from "../template-draft.js";
|
|
7
8
|
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.js";
|
|
8
9
|
import { TEMPLATE_KINDS, TEMPLATE_STATUSES } from "../web/constants.js";
|
|
@@ -35,17 +36,15 @@ export const listQuery = defineQueryHandler({
|
|
|
35
36
|
if (query.payload.status) {
|
|
36
37
|
where["status"] = query.payload.status;
|
|
37
38
|
}
|
|
38
|
-
// @cast-boundary db-row — selectMany
|
|
39
|
+
// @cast-boundary db-row — selectMany returns unknown[]; Row shape is
|
|
39
40
|
// durch templateResourcesTable + buildBaseColumns garantiert.
|
|
40
41
|
const rows = (await selectMany(ctx.db, templateResourcesTable, where, {
|
|
41
42
|
limit: 500,
|
|
42
43
|
}));
|
|
43
44
|
const deliveryPolicy = deliveryPolicyOf(ctx.registry);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
isRowServedTo(deliveryPolicy, query.user, row))
|
|
48
|
-
.map((row) => ({
|
|
45
|
+
const candidates = rows.filter((row) => !isHiddenSystemDraft(query.user, row) &&
|
|
46
|
+
!isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, row));
|
|
47
|
+
return (await filterDeliveredTo(ctx.db, deliveryPolicy, query.user, candidates)).map((row) => ({
|
|
49
48
|
id: String(row.id),
|
|
50
49
|
tenantId: row.tenantId,
|
|
51
50
|
slug: row.slug,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { type TemplateResourceRow } from "../table.ts";
|
|
3
3
|
import { type TemplateDeliveryPolicy } from "../template-delivery-policy.ts";
|
|
4
|
+
import { isHiddenSystemDraft } from "../template-draft.ts";
|
|
4
5
|
import { type TemplateEditPolicy } from "../template-edit-policy.ts";
|
|
6
|
+
import { isSystemOnlyTemplateHiddenFrom } from "../template-system-only.ts";
|
|
5
7
|
import { type EffectiveMailLayoutSlugs } from "../template-usage.ts";
|
|
6
8
|
import { type TemplateStatus } from "../web/constants.ts";
|
|
7
9
|
declare const OVERVIEW_KINDS: readonly ["mail", "document-pdf", "mail-layout", "pdf-layout"];
|
|
@@ -51,6 +53,7 @@ export type OverviewResponse = {
|
|
|
51
53
|
/** True when the tenant has more template rows than the overview reads; rows and total are then incomplete. */
|
|
52
54
|
readonly truncated: boolean;
|
|
53
55
|
};
|
|
56
|
+
export declare function isRowVisibleToCaller(policy: TemplateEditPolicy, user: Parameters<typeof isHiddenSystemDraft>[0], registry: Parameters<typeof isSystemOnlyTemplateHiddenFrom>[1], row: TemplateResourceRow): boolean;
|
|
54
57
|
export declare function effectiveMailLayoutSlugs(rows: readonly TemplateResourceRow[], policy: TemplateDeliveryPolicy): EffectiveMailLayoutSlugs;
|
|
55
58
|
export declare function makeOverviewQuery(policy: TemplateEditPolicy): import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"overview", z.ZodObject<{
|
|
56
59
|
search: z.ZodOptional<z.ZodString>;
|
|
@@ -69,6 +69,11 @@ function effectiveRowsOf(rows, policy) {
|
|
|
69
69
|
? { origin: "tenant", rows: tenantRows, lockedOverride: false, lockedOverrideId: null }
|
|
70
70
|
: null;
|
|
71
71
|
}
|
|
72
|
+
export function isRowVisibleToCaller(policy, user, registry, row) {
|
|
73
|
+
return (!isHiddenSystemDraft(user, row) &&
|
|
74
|
+
!isSystemOnlyTemplateHiddenFrom(user, registry, row) &&
|
|
75
|
+
mayEditTemplate(policy, user, row));
|
|
76
|
+
}
|
|
72
77
|
export function effectiveMailLayoutSlugs(rows, policy) {
|
|
73
78
|
const byLocale = new Map();
|
|
74
79
|
for (const row of rows) {
|
|
@@ -242,9 +247,7 @@ export function makeOverviewQuery(policy) {
|
|
|
242
247
|
limit: OVERVIEW_ROW_LIMIT,
|
|
243
248
|
});
|
|
244
249
|
}
|
|
245
|
-
const visibleRows = rows.filter((row) =>
|
|
246
|
-
!isSystemOnlyTemplateHiddenFrom(query.user, ctx.registry, row) &&
|
|
247
|
-
mayEditTemplate(policy, query.user, row));
|
|
250
|
+
const visibleRows = rows.filter((row) => isRowVisibleToCaller(policy, query.user, ctx.registry, row));
|
|
248
251
|
const deliveryPolicy = deliveryPolicyOf(ctx.registry);
|
|
249
252
|
const { drafts, layoutSlugByDocument } = buildDrafts(groupBySlugAndKind(visibleRows), query.user, deliveryPolicy);
|
|
250
253
|
const effectiveLayouts = effectiveMailLayoutSlugs(visibleRows, deliveryPolicy);
|
|
@@ -30,8 +30,8 @@ export const folderSchema = z
|
|
|
30
30
|
export const titleSchema = z.string().min(1).max(200);
|
|
31
31
|
export const contentFormatSchema = z.enum(CONTENT_FORMATS);
|
|
32
32
|
export const statusSchema = z.enum(TEMPLATE_STATUSES);
|
|
33
|
-
// Common
|
|
34
|
-
//
|
|
33
|
+
// Common upsert payload shared by upsertSystem and upsertTenant.
|
|
34
|
+
// Only ACL and tenantId determination differ.
|
|
35
35
|
export const upsertPayloadSchema = z.object({
|
|
36
36
|
slug: templateSlugSchema,
|
|
37
37
|
kind: kindSchema,
|
|
@@ -148,9 +148,9 @@ export async function writeTemplateRow(args) {
|
|
|
148
148
|
}, user, db, { streamTenantId });
|
|
149
149
|
if (!result.isSuccess)
|
|
150
150
|
return result;
|
|
151
|
-
// @cast-boundary db-row — executor.create
|
|
152
|
-
// INSERT RETURNING;
|
|
153
|
-
//
|
|
151
|
+
// @cast-boundary db-row — executor.create returns a row from
|
|
152
|
+
// INSERT RETURNING; the { id } shape is guaranteed because the primary key is in the
|
|
153
|
+
// RETURNING clause.
|
|
154
154
|
const createdRow = result.data;
|
|
155
155
|
return {
|
|
156
156
|
isSuccess: true,
|
|
@@ -14,9 +14,7 @@ export const tenantOverrideCountsQuery = defineQueryHandler({
|
|
|
14
14
|
description: "Counts, per template slug and kind, the enabled tenants that override it with an active version, next to the number of enabled tenants; one query for the whole template overview instead of one tenant-overrides call per row.",
|
|
15
15
|
escapeHatch: { grants: ["unsafeRaw"], reason: TENANT_OVERRIDES_REASON },
|
|
16
16
|
handler: async (_query, ctx) => {
|
|
17
|
-
const found = await selectMany(ctx.db.unsafeRaw(), templateResourcesTable, {
|
|
18
|
-
scope: "tenant",
|
|
19
|
-
});
|
|
17
|
+
const found = await selectMany(ctx.db.unsafeRaw(), templateResourcesTable, { scope: "tenant" }, { fields: ["tenantId", "slug", "kind", "status", "version"] });
|
|
20
18
|
const enabledTenantIds = await loadEnabledTenantIds(ctx);
|
|
21
19
|
const rowsBySlugAndKind = new Map();
|
|
22
20
|
for (const row of found) {
|
|
@@ -8,5 +8,6 @@ type TenantIdQueryContext = {
|
|
|
8
8
|
};
|
|
9
9
|
/** Null when the tenant feature is not installed: every tenant row then counts. */
|
|
10
10
|
export declare function loadEnabledTenantIds(ctx: TenantIdQueryContext): Promise<ReadonlySet<string> | null>;
|
|
11
|
-
export
|
|
11
|
+
export type OverrideCandidate = Pick<TemplateResourceRow, "tenantId" | "status" | "version">;
|
|
12
|
+
export declare function pickBestRowPerTenant<TRow extends OverrideCandidate>(found: readonly TRow[], enabledTenantIds: ReadonlySet<string> | null): Map<string, TRow>;
|
|
12
13
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
-
import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
+
import { defineQueryHandler, MAX_LIST_LIMIT, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { TenantQueries } from "../../tenant/index.js";
|
|
5
5
|
import { templateResourcesTable } from "../table.js";
|
|
@@ -10,8 +10,31 @@ import { loadEnabledTenantIds, pickBestRowPerTenant, TENANT_OVERRIDES_REASON, }
|
|
|
10
10
|
const directorySchema = z.object({
|
|
11
11
|
rows: z.array(z.object({ id: z.string(), label: z.string() })),
|
|
12
12
|
});
|
|
13
|
-
function
|
|
14
|
-
|
|
13
|
+
function chunksOf(items, size) {
|
|
14
|
+
const chunks = [];
|
|
15
|
+
for (let start = 0; start < items.length; start += size) {
|
|
16
|
+
chunks.push(items.slice(start, start + size));
|
|
17
|
+
}
|
|
18
|
+
return chunks;
|
|
19
|
+
}
|
|
20
|
+
// Looks up only the ids the overrides need, so labels never depend on the directory's default cap.
|
|
21
|
+
async function labelsFor(ctx, queryName, ids) {
|
|
22
|
+
const labels = new Map();
|
|
23
|
+
for (const chunk of chunksOf([...ids], MAX_LIST_LIMIT)) {
|
|
24
|
+
const raw = await ctx.query(queryName, { ids: chunk });
|
|
25
|
+
for (const row of directorySchema.parse(raw).rows)
|
|
26
|
+
labels.set(row.id, row.label);
|
|
27
|
+
}
|
|
28
|
+
return labels;
|
|
29
|
+
}
|
|
30
|
+
function changerIdsOf(rows) {
|
|
31
|
+
const ids = new Set();
|
|
32
|
+
for (const row of rows) {
|
|
33
|
+
const changedById = row.modifiedById ?? row.insertedById;
|
|
34
|
+
if (changedById !== null)
|
|
35
|
+
ids.add(changedById);
|
|
36
|
+
}
|
|
37
|
+
return ids;
|
|
15
38
|
}
|
|
16
39
|
function statusOf(row) {
|
|
17
40
|
return row.status === "active" ? "active" : "draft";
|
|
@@ -55,10 +78,10 @@ export const tenantOverridesQuery = defineQueryHandler({
|
|
|
55
78
|
const bestByTenant = pickBestRowPerTenant(found, enabledTenantIds);
|
|
56
79
|
const best = [...bestByTenant.values()];
|
|
57
80
|
const tenantLabels = hasTenantFeature
|
|
58
|
-
?
|
|
81
|
+
? await labelsFor(ctx, TenantQueries.tenantDirectory, new Set(best.map((row) => row.tenantId)))
|
|
59
82
|
: new Map();
|
|
60
83
|
const userLabels = hasTenantFeature
|
|
61
|
-
?
|
|
84
|
+
? await labelsFor(ctx, TenantQueries.memberDirectory, changerIdsOf(best))
|
|
62
85
|
: new Map();
|
|
63
86
|
const rows = best
|
|
64
87
|
.map((row) => toOverrideRow(row, tenantLabels, userLabels))
|
|
@@ -2,10 +2,9 @@ import { defineWriteHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framew
|
|
|
2
2
|
import { resolveTemplateVariables } from "../template-validation.js";
|
|
3
3
|
import { upsertPayloadSchema } from "./shared.js";
|
|
4
4
|
import { writeTemplateRow } from "./template-write.js";
|
|
5
|
-
//
|
|
6
|
-
// scope='system'.
|
|
7
|
-
//
|
|
8
|
-
// Overrides.
|
|
5
|
+
// Creates or updates a system template under SYSTEM_TENANT_ID with
|
|
6
|
+
// scope='system'. Only SystemAdmin can change these global defaults;
|
|
7
|
+
// TenantAdmin uses upsertTenant for overrides instead.
|
|
9
8
|
export const upsertSystemWrite = defineWriteHandler({
|
|
10
9
|
name: "upsert-system",
|
|
11
10
|
schema: upsertPayloadSchema,
|
|
@@ -4,11 +4,10 @@ import { refuseTemplateEdit, templateEditAccess, } from "../template-edit-policy
|
|
|
4
4
|
import { resolveTemplateVariables } from "../template-validation.js";
|
|
5
5
|
import { upsertPayloadSchema } from "./shared.js";
|
|
6
6
|
import { writeTemplateRow } from "./template-write.js";
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// Tenant-Templates kuratiert).
|
|
7
|
+
// Creates or updates a tenant override under event.user.tenantId with scope='tenant'.
|
|
8
|
+
// The default status is 'draft'; users must publish explicitly via the publish handler.
|
|
9
|
+
// SystemAdmin can write for another tenant through tenantIdOverride, typically to
|
|
10
|
+
// curate tenant templates from a platform admin UI.
|
|
12
11
|
export function makeUpsertTenantWrite(policy) {
|
|
13
12
|
return defineWriteHandler({
|
|
14
13
|
name: "upsert-tenant",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
|
|
2
|
+
import type { TemplateEditPolicy } from "../template-edit-policy.ts";
|
|
3
|
+
export declare function makeUsageQuery(policy: TemplateEditPolicy): import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"usage", z.ZodObject<{
|
|
3
4
|
slug: z.ZodString;
|
|
4
5
|
kind: z.ZodEnum<{
|
|
5
6
|
"ai-prompt": "ai-prompt";
|
|
@@ -6,20 +6,30 @@ import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
|
6
6
|
import { templateSlugSchema } from "../template-meta.js";
|
|
7
7
|
import { collectTemplateUsage } from "../template-usage.js";
|
|
8
8
|
import { TEMPLATE_KINDS } from "../web/constants.js";
|
|
9
|
-
import { effectiveMailLayoutSlugs } from "./overview.query.js";
|
|
9
|
+
import { effectiveMailLayoutSlugs, isRowVisibleToCaller } from "./overview.query.js";
|
|
10
10
|
const MAIL_ROW_LIMIT = 5000;
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
});
|
|
11
|
+
export function makeUsageQuery(policy) {
|
|
12
|
+
return defineQueryHandler({
|
|
13
|
+
name: "usage",
|
|
14
|
+
schema: z.object({ slug: templateSlugSchema, kind: z.enum(TEMPLATE_KINDS) }),
|
|
15
|
+
access: { roles: ["TenantAdmin", "SystemAdmin"] },
|
|
16
|
+
description: "Lists the code-registered notifications that use one template: a mail template is used by the notification whose qualified name is its slug and that has a code template, a mail layout by every mail notification whose effective template (own override, else system) names it, or whose code meta does when no stored template exists, or that falls back to the default layout; use it to show what a change to a template affects.",
|
|
17
|
+
handler: async (query, ctx) => {
|
|
18
|
+
const { slug, kind } = query.payload;
|
|
19
|
+
if (kind !== "mail-layout")
|
|
20
|
+
return { usedBy: collectTemplateUsage(ctx.registry, slug, kind) };
|
|
21
|
+
const fetchedRows = await selectMany(ctx.db, templateResourcesTable, { kind: "mail" }, { orderBy: { col: "id", direction: "asc" }, limit: MAIL_ROW_LIMIT + 1 });
|
|
22
|
+
if (fetchedRows.length > MAIL_ROW_LIMIT) {
|
|
23
|
+
ctx.log?.warn("template usage: row limit reached, result is incomplete", {
|
|
24
|
+
limit: MAIL_ROW_LIMIT,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const visibleRows = fetchedRows
|
|
28
|
+
.slice(0, MAIL_ROW_LIMIT)
|
|
29
|
+
.filter((row) => isRowVisibleToCaller(policy, query.user, ctx.registry, row));
|
|
30
|
+
return {
|
|
31
|
+
usedBy: collectTemplateUsage(ctx.registry, slug, kind, effectiveMailLayoutSlugs(visibleRows, deliveryPolicyOf(ctx.registry))),
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { defineQueryHandler, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
|
+
import { isRowDeliveredTo } from "../api.js";
|
|
4
5
|
import { imageResourceKeysOf } from "../linked-resources.js";
|
|
5
6
|
import { templateResourcesTable } from "../table.js";
|
|
6
|
-
import { deliveryPolicyOf
|
|
7
|
+
import { deliveryPolicyOf } from "../template-delivery-policy.js";
|
|
7
8
|
import { isSystemAdmin } from "../template-draft.js";
|
|
8
9
|
import { resolveTemplateVariables, systemPlaceholdersFor } from "../template-validation.js";
|
|
9
10
|
import { contentFormatSchema, kindSchema, localeSchema, templateSlugSchema } from "./shared.js";
|
|
@@ -31,7 +32,11 @@ export async function knownResourceKeysFor(ctx, user, where) {
|
|
|
31
32
|
locale,
|
|
32
33
|
})),
|
|
33
34
|
...(scope === "tenant" &&
|
|
34
|
-
|
|
35
|
+
(await isRowDeliveredTo(ctx.db, deliveryPolicyOf(ctx.registry), user, {
|
|
36
|
+
tenantId: user.tenantId,
|
|
37
|
+
kind,
|
|
38
|
+
slug,
|
|
39
|
+
}))
|
|
35
40
|
? await knownResourceKeys(ctx.db, { tenantId: user.tenantId, slug, kind, scope, locale })
|
|
36
41
|
: []),
|
|
37
42
|
];
|
|
@@ -12,7 +12,7 @@ import { createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
|
12
12
|
import { createSystemUser, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
13
13
|
import { deleteRowsWithoutReplayableStream, getStreamVersion, getUnscopedStreamMaxVersionForSeed, } from "@cosmicdrift/kumiko-framework/event-store";
|
|
14
14
|
import { runEventStoreSeed } from "@cosmicdrift/kumiko-framework/seeding";
|
|
15
|
-
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
15
|
+
import { isPlainObject, propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
16
16
|
import { executor } from "./handlers/shared.js";
|
|
17
17
|
import { evaluateTemplateWrite } from "./handlers/template-gates.js";
|
|
18
18
|
import { templateResourcesTable } from "./table.js";
|
|
@@ -39,10 +39,16 @@ async function resolveExistingForEventStoreSeed(db, tdb, existingRow, tenantId)
|
|
|
39
39
|
}
|
|
40
40
|
return { id, version: streamVersion };
|
|
41
41
|
}
|
|
42
|
+
// Namespace prefix plus path, no whitespace: keeps free text from passing as a key that the UI
|
|
43
|
+
// would then show raw.
|
|
44
|
+
const I18N_KEY_FORMAT = /^[^\s:]+:\S+$/;
|
|
42
45
|
function seedTitleColumn(opts, label) {
|
|
43
46
|
if (opts.title !== undefined && opts.titleI18nKey !== undefined) {
|
|
44
47
|
throw new Error(`${label} rejected: set either title or titleI18nKey, not both`);
|
|
45
48
|
}
|
|
49
|
+
if (opts.titleI18nKey !== undefined && !I18N_KEY_FORMAT.test(opts.titleI18nKey)) {
|
|
50
|
+
throw new Error(`${label} rejected: titleI18nKey "${opts.titleI18nKey}" is not a "namespace:key" i18n key`);
|
|
51
|
+
}
|
|
46
52
|
return opts.titleI18nKey ?? opts.title ?? null;
|
|
47
53
|
}
|
|
48
54
|
export async function seedSystemTemplate(db, opts) {
|
|
@@ -101,16 +107,18 @@ export async function seedSystemTemplate(db, opts) {
|
|
|
101
107
|
current?.title === rowFields.title &&
|
|
102
108
|
current?.variableSchema === rowFields.variableSchema &&
|
|
103
109
|
current?.meta === rowFields.meta &&
|
|
104
|
-
current?.status === rowFields.status &&
|
|
105
110
|
current?.parentTemplateId === rowFields.parentTemplateId &&
|
|
106
111
|
(linkedResources === undefined || current?.linkedResources === linkedResources)) {
|
|
107
112
|
return { id: String(row.id) };
|
|
108
113
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
// An archived system row is a SystemAdmin decision (reversible with publish-system) that a
|
|
115
|
+
// pod-boot re-seed must not undo; content still follows the code. The seed replaces the
|
|
116
|
+
// content, so an open draft on the old content is dropped with it.
|
|
117
|
+
const { status: _status, ...contentFields } = rowFields;
|
|
118
|
+
const changes = current?.status === "archived"
|
|
119
|
+
? { ...contentFields, status: "archived", draft: null }
|
|
120
|
+
: { ...rowFields, ...activeStampChanges(row), draft: null };
|
|
121
|
+
const result = await executor.update({ id: row.id, version: row.version, changes }, by, tdb);
|
|
114
122
|
if (!result.isSuccess) {
|
|
115
123
|
throw new Error(`seedSystemTemplate update failed: ${JSON.stringify(result)}`);
|
|
116
124
|
}
|
|
@@ -151,11 +159,11 @@ export async function seedSystemTemplate(db, opts) {
|
|
|
151
159
|
}
|
|
152
160
|
throw new Error(`seedSystemTemplate create failed: ${JSON.stringify(result)}`);
|
|
153
161
|
}
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
162
|
+
const createdId = propertyOf(result.data, "id");
|
|
163
|
+
if (createdId === undefined) {
|
|
156
164
|
throw new Error("seedSystemTemplate: executor.create did not return an id");
|
|
157
165
|
}
|
|
158
|
-
return { id: String(
|
|
166
|
+
return { id: String(createdId) };
|
|
159
167
|
},
|
|
160
168
|
update: (row) => applyUpdate(row, existingRow),
|
|
161
169
|
});
|
|
@@ -191,8 +199,10 @@ async function seedSystemTemplateBundleWithResources(db, bundle, opts) {
|
|
|
191
199
|
if (!dispatcher) {
|
|
192
200
|
throw new Error(`${label}: bundles with resources need a file provider; pass opts.dispatcher (the dispatcher of the seed deps) so the files are stored through the import-bundle-system write`);
|
|
193
201
|
}
|
|
194
|
-
|
|
195
|
-
|
|
202
|
+
const skipExisting = (opts.ifExists ?? "skip") === "skip";
|
|
203
|
+
const existingIds = {};
|
|
204
|
+
let bundleToImport = bundle;
|
|
205
|
+
if (skipExisting) {
|
|
196
206
|
for (const locale of Object.keys(bundle.locales)) {
|
|
197
207
|
const row = await fetchOne(db, templateResourcesTable, {
|
|
198
208
|
tenantId: SYSTEM_TENANT_ID,
|
|
@@ -206,12 +216,18 @@ async function seedSystemTemplateBundleWithResources(db, bundle, opts) {
|
|
|
206
216
|
if (Object.keys(existingIds).length === Object.keys(bundle.locales).length) {
|
|
207
217
|
return { ids: existingIds };
|
|
208
218
|
}
|
|
219
|
+
// import-bundle-system always overwrites, so only the missing locales go in: a
|
|
220
|
+
// hand-edited system row of an already seeded locale must survive the new-locale boot.
|
|
221
|
+
bundleToImport = {
|
|
222
|
+
...bundle,
|
|
223
|
+
locales: Object.fromEntries(Object.entries(bundle.locales).filter(([locale]) => !(locale in existingIds))),
|
|
224
|
+
};
|
|
209
225
|
}
|
|
210
|
-
const result = await dispatcher.write(TemplateResolverHandlers.importBundleSystem, { bundle }, opts.by ?? createSystemUser(SYSTEM_TENANT_ID, ["SystemAdmin"]));
|
|
226
|
+
const result = await dispatcher.write(TemplateResolverHandlers.importBundleSystem, { bundle: bundleToImport }, opts.by ?? createSystemUser(SYSTEM_TENANT_ID, ["SystemAdmin"]));
|
|
211
227
|
if (!result.isSuccess) {
|
|
212
228
|
throw new Error(`${label} failed: ${result.error.code}: ${result.error.message}`);
|
|
213
229
|
}
|
|
214
|
-
return { ids: importedIds(result.data) };
|
|
230
|
+
return { ids: { ...existingIds, ...importedIds(result.data) } };
|
|
215
231
|
}
|
|
216
232
|
function importedIds(data) {
|
|
217
233
|
const ids = isPlainObject(data) ? data["ids"] : undefined;
|
|
@@ -42,6 +42,7 @@ export declare function prepareTemplateResourceBeforeTransaction(args: {
|
|
|
42
42
|
}): Promise<BeforeTransactionResult<PreparedTemplateImage>>;
|
|
43
43
|
export type Release = () => Promise<void>;
|
|
44
44
|
export declare function releaseAll(releases: readonly Release[]): Promise<void>;
|
|
45
|
+
export declare function releaseAfterFailure(ctx: HandlerContext, releases: readonly Release[]): Promise<void>;
|
|
45
46
|
export type PreparedLinkedResourceCopy = {
|
|
46
47
|
readonly key: string;
|
|
47
48
|
readonly entry: LinkedResourceEntry;
|
|
@@ -24,6 +24,9 @@ function keyInUse() {
|
|
|
24
24
|
details: { code: "key_in_use" },
|
|
25
25
|
}));
|
|
26
26
|
}
|
|
27
|
+
function isImageKey(links, key) {
|
|
28
|
+
return typeof links[key] === "string";
|
|
29
|
+
}
|
|
27
30
|
function isAttachmentKey(links, key) {
|
|
28
31
|
const occupant = links[key];
|
|
29
32
|
return occupant !== undefined && typeof occupant !== "string";
|
|
@@ -129,6 +132,17 @@ export async function releaseAll(releases) {
|
|
|
129
132
|
if (rejected?.status === "rejected")
|
|
130
133
|
throw rejected.reason;
|
|
131
134
|
}
|
|
135
|
+
// Failure paths: a failing release must not replace the upload error the caller needs to see.
|
|
136
|
+
export async function releaseAfterFailure(ctx, releases) {
|
|
137
|
+
try {
|
|
138
|
+
await releaseAll(releases);
|
|
139
|
+
}
|
|
140
|
+
catch (releaseError) {
|
|
141
|
+
ctx.log?.warn("template upload rollback: releasing stored files failed", {
|
|
142
|
+
error: releaseError instanceof Error ? releaseError.message : String(releaseError),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
132
146
|
// beforeTransaction half: copies the file behind every entry into the target tenant's storage, so a
|
|
133
147
|
// template copied from the system default keeps working once the tenant exports it or measures its
|
|
134
148
|
// attachments. An entry whose source file is gone is left out: it could not be resolved at render
|
|
@@ -148,7 +162,7 @@ export async function prepareLinkedResourceCopiesBeforeTransaction(args) {
|
|
|
148
162
|
continue;
|
|
149
163
|
const uploaded = await uploadToTenant({ ctx, user, tenantId }, { fileName: file.fileName, mimeType: file.contentType, data: file.bytes });
|
|
150
164
|
if (!uploaded.isSuccess) {
|
|
151
|
-
await
|
|
165
|
+
await releaseAfterFailure(ctx, releases);
|
|
152
166
|
return uploaded;
|
|
153
167
|
}
|
|
154
168
|
if (uploaded.release)
|
|
@@ -157,7 +171,7 @@ export async function prepareLinkedResourceCopiesBeforeTransaction(args) {
|
|
|
157
171
|
}
|
|
158
172
|
}
|
|
159
173
|
catch (cause) {
|
|
160
|
-
await
|
|
174
|
+
await releaseAfterFailure(ctx, releases);
|
|
161
175
|
throw cause;
|
|
162
176
|
}
|
|
163
177
|
return { isSuccess: true, data: copies, release: () => releaseAll(releases) };
|
|
@@ -275,8 +289,7 @@ async function checkAttachmentTarget(args) {
|
|
|
275
289
|
if (otherAttachmentCount(linked, key) >= MAX_FILE_ATTACHMENTS_PER_TEMPLATE) {
|
|
276
290
|
return attachmentLimitFailure();
|
|
277
291
|
}
|
|
278
|
-
|
|
279
|
-
if (occupant !== undefined && typeof occupant === "string")
|
|
292
|
+
if (isImageKey(linked, key))
|
|
280
293
|
return keyInUse();
|
|
281
294
|
return { isSuccess: true, data: { row, linked } };
|
|
282
295
|
}
|
|
@@ -387,6 +400,8 @@ export async function linkTemplatePdfAttachment(args) {
|
|
|
387
400
|
if (row.kind !== "mail")
|
|
388
401
|
return attachmentNeedsMailTemplate();
|
|
389
402
|
const linked = parseLinkedResourceEntries(row.linkedResources);
|
|
403
|
+
if (isImageKey(linked, key))
|
|
404
|
+
return keyInUse();
|
|
390
405
|
if (otherAttachmentCount(linked, key) >= MAX_FILE_ATTACHMENTS_PER_TEMPLATE) {
|
|
391
406
|
return attachmentLimitFailure();
|
|
392
407
|
}
|
|
@@ -7,16 +7,15 @@ const renameMailHtmlKind = {
|
|
|
7
7
|
toVersion: 2,
|
|
8
8
|
transform: (fields) => (fields["kind"] === "mail-html" ? { ...fields, kind: "mail" } : fields),
|
|
9
9
|
};
|
|
10
|
-
// TemplateResource —
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// Fassung.
|
|
10
|
+
// TemplateResource — structured template definition with tenant override
|
|
11
|
+
// hierarchy, locale fallback, and resource linking via file-foundation. Exactly
|
|
12
|
+
// one row per (tenantId, slug, kind, locale); scope/status/version distinguish
|
|
13
|
+
// lifecycle states. The draft alongside an active revision is stored in `draft`;
|
|
14
|
+
// the main fields remain the served revision.
|
|
16
15
|
//
|
|
17
|
-
// `variableSchema` + `linkedResources`
|
|
18
|
-
// (
|
|
19
|
-
//
|
|
16
|
+
// `variableSchema` + `linkedResources` are JSON strings in longText
|
|
17
|
+
// (following compliance-profiles because the createEntity DSL has no dedicated
|
|
18
|
+
// jsonbField). The application layer parses the JSON and persists it as a string.
|
|
20
19
|
export const templateResourceEntity = createEntity({
|
|
21
20
|
table: "read_template_resources",
|
|
22
21
|
fields: {
|
|
@@ -31,8 +30,8 @@ export const templateResourceEntity = createEntity({
|
|
|
31
30
|
// Folder path for the content tree, `/`-separated ("page/marketing").
|
|
32
31
|
// null = root node.
|
|
33
32
|
folder: createTextField({ personal: false, reason: "technical_reference" }),
|
|
34
|
-
// Template
|
|
35
|
-
// business data
|
|
33
|
+
// Template body is authored by TenantAdmin/Operator (email-templates, etc.),
|
|
34
|
+
// and is business data—not end-user UGC.
|
|
36
35
|
content: createLongTextField({
|
|
37
36
|
personal: false,
|
|
38
37
|
reason: "is_business_data",
|
|
@@ -13,10 +13,5 @@ export declare function isServedByCollectionOnly(policy: TemplateDeliveryPolicy,
|
|
|
13
13
|
export declare function isRowServed(policy: TemplateDeliveryPolicy, row: DeliveryTarget & {
|
|
14
14
|
readonly tenantId: string;
|
|
15
15
|
}): boolean;
|
|
16
|
-
export declare function isRowServedTo(policy: TemplateDeliveryPolicy, user: {
|
|
17
|
-
readonly roles: readonly string[];
|
|
18
|
-
}, row: DeliveryTarget & {
|
|
19
|
-
readonly tenantId: string;
|
|
20
|
-
}): boolean;
|
|
21
16
|
export declare function deliveryPolicyOf(registry: Registry): TemplateDeliveryPolicy;
|
|
22
17
|
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isPlainObject, propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
|
-
import { isSystemAdmin } from "./template-draft.js";
|
|
3
2
|
import { SYSTEM_TENANT_ID } from "./web/constants.js";
|
|
4
3
|
import { TEMPLATE_RESOLVER_FEATURE } from "./web/qualified-names.js";
|
|
5
4
|
const NOTHING_UNLOCKED = { tenantEditable: [], collectionKinds: [] };
|
|
@@ -16,11 +15,6 @@ export function isServedByCollectionOnly(policy, target) {
|
|
|
16
15
|
export function isRowServed(policy, row) {
|
|
17
16
|
return row.tenantId === SYSTEM_TENANT_ID || isTenantOverrideServed(policy, row);
|
|
18
17
|
}
|
|
19
|
-
// A SystemAdmin sees every stored row, so a locked override can still be reset; everyone else
|
|
20
|
-
// sees only what is delivered, which keeps a locked override out of the template-resolver queries for a TenantAdmin (the audit log keeps the history).
|
|
21
|
-
export function isRowServedTo(policy, user, row) {
|
|
22
|
-
return isSystemAdmin(user) || isRowServed(policy, row);
|
|
23
|
-
}
|
|
24
18
|
function isDeliveryTarget(value) {
|
|
25
19
|
return (typeof propertyOf(value, "kind") === "string" && typeof propertyOf(value, "slug") === "string");
|
|
26
20
|
}
|