@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.387.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/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/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 +3 -3
- 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-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- 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/create-checkout-session.write.js +18 -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/process-event.write.js +20 -20
- 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 +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- 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 +47 -48
- 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 +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- 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/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/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- 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/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- 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-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- 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 +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -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/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.js +11 -11
- 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/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- 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 +57 -56
- 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.js +5 -6
- 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/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- 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 +2 -2
- package/dist/mail-foundation/feature.js +24 -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.js +5 -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/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.js +8 -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.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- 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/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 +35 -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 +1 -1
- 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.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- 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/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- 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.js +1 -1
- 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/feature.js +1 -1
- 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 +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- 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 +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- 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/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 +10 -10
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// mail-transport-inmemory — In-
|
|
4
|
-
// foundation
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// mail-transport-inmemory — In-memory email transport for the mail-
|
|
4
|
+
// foundation plugin API. Collects emails in a per-tenant buffer
|
|
5
|
+
// instead of sending them through a real SMTP server. Designed for
|
|
6
|
+
// demos, sample apps, and tests that should run without Mailpit,
|
|
7
|
+
// Mailcrab, or real SMTP.
|
|
8
8
|
//
|
|
9
|
-
// **
|
|
10
|
-
// 1. Plugin
|
|
11
|
-
// "inmemory", { build })`. Tenants
|
|
12
|
-
// "mail-foundation:config:provider"
|
|
13
|
-
//
|
|
14
|
-
// 2. **
|
|
15
|
-
//
|
|
16
|
-
//
|
|
9
|
+
// **What this feature provides:**
|
|
10
|
+
// 1. Plugin registration via `r.useExtension("mailTransport",
|
|
11
|
+
// "inmemory", { build })`. Tenants set
|
|
12
|
+
// "mail-foundation:config:provider" to "inmemory" and receive
|
|
13
|
+
// the buffered variant.
|
|
14
|
+
// 2. **Per-tenant inbox.** Each tenant has its own mail buffer
|
|
15
|
+
// (Map<tenantId, EmailMessage[]>). Demo apps can read the inbox
|
|
16
|
+
// via `getInbox(tenantId)` and render a UI.
|
|
17
17
|
//
|
|
18
|
-
// **Pattern
|
|
18
|
+
// **Pattern reference:** mirrors mail-transport-smtp.
|
|
19
19
|
//
|
|
20
|
-
// **
|
|
21
|
-
//
|
|
22
|
-
//
|
|
20
|
+
// **NOT for production.** The buffer is in process memory and is lost
|
|
21
|
+
// on restart. Cap counters and the audit trail remain correct because
|
|
22
|
+
// they are tied to the event store, not the transport.
|
|
23
23
|
import { createInMemoryTransport } from "@cosmicdrift/kumiko-bundled-features/channel-email";
|
|
24
24
|
import { MAIL_TRANSPORT_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
|
|
25
25
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -28,9 +28,9 @@ const FEATURE_NAME = "mail-transport-inmemory";
|
|
|
28
28
|
// Per-tenant in-memory buffer
|
|
29
29
|
// =============================================================================
|
|
30
30
|
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
31
|
+
// The module-level Map is needed because the plugin build call creates
|
|
32
|
+
// a new transport wrapper for each send, while all wrappers for the
|
|
33
|
+
// same tenant must point to the same buffer. Map<tenantId,
|
|
34
34
|
// InMemoryTransport>.
|
|
35
35
|
const transportsByTenant = new Map();
|
|
36
36
|
function getOrCreateTransportForTenant(tenantId) {
|
|
@@ -42,15 +42,15 @@ function getOrCreateTransportForTenant(tenantId) {
|
|
|
42
42
|
return transport;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
-
* Demo/
|
|
46
|
-
*
|
|
45
|
+
* Demo/test helper: reads the emails "sent" for a tenant. A query
|
|
46
|
+
* handler in the sample app uses this to render the inbox UI.
|
|
47
47
|
*/
|
|
48
48
|
export function getInbox(tenantId) {
|
|
49
49
|
return transportsByTenant.get(tenantId)?.sent ?? [];
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* Demo/
|
|
53
|
-
*
|
|
52
|
+
* Demo/test helper: clears a tenant's buffer, for example between
|
|
53
|
+
* test scenarios.
|
|
54
54
|
*/
|
|
55
55
|
export function clearInbox(tenantId) {
|
|
56
56
|
const t = transportsByTenant.get(tenantId);
|
|
@@ -63,10 +63,9 @@ export function clearInbox(tenantId) {
|
|
|
63
63
|
export function createMailTransportInMemoryFeature() {
|
|
64
64
|
return defineFeature(FEATURE_NAME, (r) => {
|
|
65
65
|
r.describe('Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).');
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
// extension-point "mailTransport" definiert.
|
|
66
|
+
// No `config` or `secrets` requirement: the in-memory transport has
|
|
67
|
+
// no configuration and no secret. The only hard requirement is
|
|
68
|
+
// mail-foundation, which defines the "mailTransport" extension point.
|
|
70
69
|
r.requires({ features: ["mail-foundation"] });
|
|
71
70
|
const plugin = {
|
|
72
71
|
// Solon and studio mount it next to smtp in production; offering it there would
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// mail-transport-smtp — concrete SMTP
|
|
4
|
-
// mail-foundation plugin
|
|
3
|
+
// mail-transport-smtp — concrete SMTP implementation for the
|
|
4
|
+
// mail-foundation plugin API.
|
|
5
5
|
//
|
|
6
|
-
// **
|
|
7
|
-
// 1. Provider-
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// API
|
|
11
|
-
// 2. **Plugin
|
|
12
|
-
// "smtp", { build })`.
|
|
13
|
-
//
|
|
14
|
-
// 3. `build(ctx, tenantId)`
|
|
15
|
-
// `createSmtpTransport()`
|
|
16
|
-
//
|
|
17
|
-
//
|
|
6
|
+
// **What this feature provides:**
|
|
7
|
+
// 1. Provider-specific tenant config (host/port/secure/from/authUser)
|
|
8
|
+
// and secret (smtp.password). Self-contained — mail-foundation does not
|
|
9
|
+
// know these keys; when an app owner switches between SMTP and the Brevo
|
|
10
|
+
// API, each plugin has its own independent config sets.
|
|
11
|
+
// 2. **Plugin registration** via `r.useExtension("mailTransport",
|
|
12
|
+
// "smtp", { build })`. At boot, mail-foundation's factory lookup maps
|
|
13
|
+
// the name "smtp" to the build function.
|
|
14
|
+
// 3. `build(ctx, tenantId)` reads the config keys and secret, then calls
|
|
15
|
+
// `createSmtpTransport()` from channel-email. This is the plugin's
|
|
16
|
+
// ONLY cross-feature import, deliberately kept local so
|
|
17
|
+
// mail-foundation remains provider-independent.
|
|
18
18
|
//
|
|
19
|
-
// **Pattern
|
|
20
|
-
// `delivery`.
|
|
21
|
-
// mail-foundation's "mailTransport"
|
|
19
|
+
// **Pattern reference:** mirrors `channel-email` registering itself for
|
|
20
|
+
// `delivery`. This feature is analogous: it registers for
|
|
21
|
+
// mail-foundation's "mailTransport" extension point.
|
|
22
22
|
//
|
|
23
|
-
// **Boot
|
|
23
|
+
// **Boot dependencies:**
|
|
24
24
|
// - `mail-foundation` — extension-point owner
|
|
25
|
-
// - `config` —
|
|
26
|
-
// - `secrets` —
|
|
25
|
+
// - `config` — for the tenant config keys
|
|
26
|
+
// - `secrets` — for the encrypted SMTP password
|
|
27
27
|
import { createSmtpTransport, } from "@cosmicdrift/kumiko-bundled-features/channel-email";
|
|
28
28
|
import { BlockedHostError, HostResolutionError, mailAllowedPrivateHostsEnvSchema, readAllowedPrivateMailHostsFromEnv, requireDefined, requireNonEmpty, requireSecretSet, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
29
29
|
import { MAIL_TRANSPORT_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
|
|
@@ -14,13 +14,13 @@ import { EMPTY_BRANDING } from "../page-render/index.js";
|
|
|
14
14
|
// `write: access.withSystem(access.admin)` — tenant admins self-service via
|
|
15
15
|
// configEdit AND the system actor (ctx.systemWriteAs) may provision/migrate
|
|
16
16
|
// these keys. The scope default (`access.admin`, admin-only) has no system
|
|
17
|
-
// path, so a continuity migration could not set them
|
|
18
|
-
//
|
|
17
|
+
// path, so a continuity migration could not set them. Adding SYSTEM_ROLE
|
|
18
|
+
// keeps the keys human-writable (checkWriteAccess collapses to
|
|
19
19
|
// system-only only when system is the SOLE writer), so self-service survives.
|
|
20
20
|
//
|
|
21
|
-
// CONTINUITY (
|
|
21
|
+
// CONTINUITY (Prod trap): these keys land under
|
|
22
22
|
// `managed-pages:config:branding-*`, NOT the live `publicstatus:config:
|
|
23
|
-
// branding-*`. The publicstatus consumer
|
|
23
|
+
// branding-*`. The publicstatus consumer MUST migrate the existing
|
|
24
24
|
// read_config_values rows to the new QNs per tenant BEFORE switching the read
|
|
25
25
|
// path, or every tenant resets to defaults on deploy. The migration is
|
|
26
26
|
// deliberately NOT built here — the source QNs belong to the consumer app.
|
|
@@ -30,7 +30,7 @@ import { EMPTY_BRANDING } from "../page-render/index.js";
|
|
|
30
30
|
// also renders. text keys carry an explicit length cap too — `validateType`
|
|
31
31
|
// only checks the JS type, and the configEdit `maxLength` is client-side, so a
|
|
32
32
|
// direct config:write:set would otherwise be unbounded (the page body is
|
|
33
|
-
// likewise capped
|
|
33
|
+
// likewise capped).
|
|
34
34
|
const HEX_PATTERN = {
|
|
35
35
|
regex: "^$|^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
|
|
36
36
|
};
|
|
@@ -56,7 +56,7 @@ export const MANAGED_PAGES_CSS_FEATURE = "managed-pages-css";
|
|
|
56
56
|
// site-url`. BRANDING_QN below is the single source those QN strings are read
|
|
57
57
|
// from (configEdit screen + render read); the integration test pins write-
|
|
58
58
|
// target == read-source end-to-end.
|
|
59
|
-
// Admin self-service + system provisioning
|
|
59
|
+
// Admin self-service + system provisioning.
|
|
60
60
|
const BRANDING_WRITE = access.withSystem(access.admin);
|
|
61
61
|
export const BRANDING_KEYS = {
|
|
62
62
|
brandingTitle: createTenantConfig("text", {
|
|
@@ -10,36 +10,36 @@ export type ManagedPagesWrapLayout = (opts: {
|
|
|
10
10
|
readonly branding: BrandingTokens;
|
|
11
11
|
}) => string;
|
|
12
12
|
export type ManagedPagesOptions = {
|
|
13
|
-
/** Host → tenantId
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* tenantId (
|
|
17
|
-
*
|
|
13
|
+
/** Host → tenantId for anonymous per-tenant delivery. NULL → 404 (no
|
|
14
|
+
* tenant for this host). Apex/marketing apps provide their subdomain or
|
|
15
|
+
* custom-domain resolution here; single-tenant apps return a constant
|
|
16
|
+
* tenantId (or SYSTEM_TENANT_ID). Required because the apex host has no
|
|
17
|
+
* ambient ctx.tenantId. */
|
|
18
18
|
readonly resolveApexTenant: (host: string) => Promise<string | null> | string | null;
|
|
19
|
-
/** Custom
|
|
20
|
-
*
|
|
21
|
-
* **`branding`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* (
|
|
25
|
-
* `brandingHeaderHtml(branding)` + `brandingStyleBlock(branding)` (
|
|
26
|
-
*
|
|
27
|
-
* customCss)`
|
|
28
|
-
*
|
|
29
|
-
*
|
|
19
|
+
/** Custom layout wrapper (branding/chrome). Default: a minimal page-render
|
|
20
|
+
* skeleton. Receives slug + SEO meta for free use.
|
|
21
|
+
* **`branding` is RAW, untrusted tenant input.** `title`/`description`
|
|
22
|
+
* are only length-capped on write, NOT HTML-escaped; `customCss` is
|
|
23
|
+
* unsanitized. The wrapper MUST emit them through the boundary helpers
|
|
24
|
+
* (all re-exported from `@cosmicdrift/kumiko-bundled-features/managed-pages`):
|
|
25
|
+
* `brandingHeaderHtml(branding)` + `brandingStyleBlock(branding)` (which
|
|
26
|
+
* escape header/theme) and, with allowCustomCss, `tenantStyleBlock(branding.
|
|
27
|
+
* customCss)` in the `<head>` plus `TENANT_CONTENT_ATTR` on the body
|
|
28
|
+
* container. A custom wrapper that interpolates `branding.title` itself is
|
|
29
|
+
* stored XSS; the default wrapper uses the helpers throughout. */
|
|
30
30
|
readonly wrapLayout?: ManagedPagesWrapLayout;
|
|
31
|
-
/**
|
|
31
|
+
/** Base path for page routes. Default "/p" → GET /p/:slug. */
|
|
32
32
|
readonly basePath?: string;
|
|
33
|
-
/** Default
|
|
33
|
+
/** Default language when `?lang=` is missing. Default "en". */
|
|
34
34
|
readonly defaultLang?: string;
|
|
35
|
-
/**
|
|
36
|
-
* `branding-custom-css`
|
|
37
|
-
*
|
|
38
|
-
* Default **false** (fail-closed — opt-in
|
|
39
|
-
*
|
|
40
|
-
* `managed-pages-css
|
|
41
|
-
*
|
|
42
|
-
*
|
|
35
|
+
/** Enables the per-tenant custom CSS capability (raw, untrusted): a
|
|
36
|
+
* `branding-custom-css` config key + a CSS field in the branding editor +
|
|
37
|
+
* render emission as a scoped, allowlist-sanitized `<style data-tenant-css>`.
|
|
38
|
+
* Default **false** (fail-closed — opt-in for untrusted tenant input). Even
|
|
39
|
+
* when true, emission is additionally gated per tenant by the
|
|
40
|
+
* `managed-pages-css` toggle (createManagedPagesCssFeature) once a
|
|
41
|
+
* feature-toggles/tier-engine runtime is wired. The render-time sanitizer
|
|
42
|
+
* (page-render/css-sanitize) is the safety boundary. */
|
|
43
43
|
readonly allowCustomCss?: boolean;
|
|
44
44
|
};
|
|
45
45
|
export declare function createManagedPagesFeature(opts: ManagedPagesOptions): FeatureDefinition;
|
|
@@ -15,9 +15,9 @@ import { pageEntity } from "./table.js";
|
|
|
15
15
|
import { MANAGED_PAGES_I18N } from "./web/i18n.js";
|
|
16
16
|
// 60s-shared-cache saves the origin-revalidate roundtrip; CMS edits are live within 60s.
|
|
17
17
|
const PUBLIC_PAGE_CACHE = { kind: "revalidate", maxAgeSeconds: 60 };
|
|
18
|
-
// QN
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// QN constant as a documented public contract — the render path calls
|
|
19
|
+
// the by-slug query in-process via systemQuery (without importing the
|
|
20
|
+
// handler's code, symmetrically with the legal-pages pattern).
|
|
21
21
|
const BY_SLUG_QN = "managed-pages:query:by-slug";
|
|
22
22
|
function brandingRevisionSeed(branding) {
|
|
23
23
|
return JSON.stringify([
|
|
@@ -45,28 +45,28 @@ async function readBrandingViaSystemQuery(systemQuery, tenantId) {
|
|
|
45
45
|
return EMPTY_BRANDING;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
// managed-pages —
|
|
49
|
-
//
|
|
50
|
-
// (`GET /p/:slug`)
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
48
|
+
// managed-pages — tenant-editable, server-rendered public pages.
|
|
49
|
+
// Generalizes the legal-pages rendering pattern: a dynamic slug route
|
|
50
|
+
// (`GET /p/:slug`) that resolves the tenant from the Host (resolveApexTenant),
|
|
51
|
+
// loads the published page, renders hardened Markdown (page-render), and wraps
|
|
52
|
+
// it in chrome through an optional wrapLayout. Drafts → 404. Per-tenant
|
|
53
|
+
// content is cache-isolated through `Vary: Host`.
|
|
54
54
|
//
|
|
55
|
-
// Admin
|
|
56
|
-
// SystemAdmin)
|
|
57
|
-
//
|
|
58
|
-
// same
|
|
55
|
+
// Admin authoring: registers entityList + entityEdit for `page` (TenantAdmin/
|
|
56
|
+
// SystemAdmin) and the convention CRUD handlers dispatched by the renderer.
|
|
57
|
+
// The screens MUST live here (the boot validator requires the entity reference
|
|
58
|
+
// in the same feature); navigation/workspace remains the app's responsibility.
|
|
59
59
|
//
|
|
60
|
-
//
|
|
61
|
-
// • anonymousAccess
|
|
62
|
-
// —
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// • Admin
|
|
66
|
-
// page-list" })`
|
|
67
|
-
// (cross-feature Nav→Screen
|
|
68
|
-
// TenantAdmin.
|
|
69
|
-
// flat-nav
|
|
60
|
+
// App bootstrap requirements:
|
|
61
|
+
// • anonymousAccess must be wired to honor the X-Tenant header
|
|
62
|
+
// — multi-tenant apps use a tenantResolver (or no defaultTenantId).
|
|
63
|
+
// A fixed defaultTenantId locks the app to single-tenant mode and rejects
|
|
64
|
+
// the per-page X-Tenant with 400 tenant_mismatch.
|
|
65
|
+
// • Admin UI: the app exposes these screens via `r.nav({ screen:
|
|
66
|
+
// "managed-pages:screen:page-list" })` plus a workspace entry
|
|
67
|
+
// (cross-feature Nav→Screen is globally validated) and grants its admins
|
|
68
|
+
// TenantAdmin. Without navigation, the screens remain dormant — no leak in
|
|
69
|
+
// flat-nav apps that use managed-pages only for public rendering.
|
|
70
70
|
export function createManagedPagesFeature(opts) {
|
|
71
71
|
const wrapLayout = opts.wrapLayout ??
|
|
72
72
|
((o) => wrapInLayout({
|
|
@@ -112,8 +112,8 @@ export function createManagedPagesFeature(opts) {
|
|
|
112
112
|
path: `${basePath}/:slug`,
|
|
113
113
|
anonymous: true,
|
|
114
114
|
handler: async (c, { systemQuery }) => {
|
|
115
|
-
// `param("slug")`
|
|
116
|
-
//
|
|
115
|
+
// `param("slug")` is string|undefined because `path` is a computed
|
|
116
|
+
// template (Hono infers `:slug` only from string literals).
|
|
117
117
|
const slug = c.req.param("slug");
|
|
118
118
|
if (!slug)
|
|
119
119
|
return c.text("not found", 404);
|
|
@@ -124,13 +124,13 @@ export function createManagedPagesFeature(opts) {
|
|
|
124
124
|
const tenantId = await opts.resolveApexTenant(host);
|
|
125
125
|
if (!tenantId)
|
|
126
126
|
return c.text("not found", 404);
|
|
127
|
-
// Page
|
|
128
|
-
// process
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
127
|
+
// Page and branding are read in parallel, both forced through systemQuery
|
|
128
|
+
// in-process for the host-resolved tenantId (no X-Tenant header trick
|
|
129
|
+
// through app.fetch — for a host-based anonymousAccess resolver, that
|
|
130
|
+
// would look like a client override and would rightly be rejected by
|
|
131
|
+
// resolverTrust: "authoritative"; see systemQuery's documentation in
|
|
132
|
+
// http-route.ts). Branding is decorative → a failure degrades to the
|
|
133
|
+
// unbranded default and never blocks the page.
|
|
134
134
|
let pageSettled;
|
|
135
135
|
let brandingResult;
|
|
136
136
|
try {
|
|
@@ -168,8 +168,8 @@ export function createManagedPagesFeature(opts) {
|
|
|
168
168
|
"content-type": "text/html; charset=utf-8",
|
|
169
169
|
vary: "Host",
|
|
170
170
|
};
|
|
171
|
-
// 304 (
|
|
172
|
-
//
|
|
171
|
+
// 304 (unchanged revision) and HEAD both skip Markdown rendering — the body
|
|
172
|
+
// would be discarded anyway.
|
|
173
173
|
if (etagMatches(c.req.raw.headers.get("if-none-match"), etag) || c.req.method === "HEAD") {
|
|
174
174
|
return cachedSecurePageResponse(c.req.raw, {
|
|
175
175
|
body: null,
|
|
@@ -2,12 +2,11 @@ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
import { pagesTable } from "../table.js";
|
|
5
|
-
// Public
|
|
6
|
-
//
|
|
7
|
-
// via X-Tenant = Host-resolved-tenant
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// diese Query.
|
|
5
|
+
// Public read by (tenantId, slug, lang), including anonymous access for landing and
|
|
6
|
+
// marketing pages. The tenant comes from query.user.tenantId, set on the render path
|
|
7
|
+
// via X-Tenant = Host-resolved-tenant. Returns ONLY published pages with a body:
|
|
8
|
+
// drafts and empty pages are invisible to anonymous visitors (the route returns 404).
|
|
9
|
+
// Admin editing uses the entity list/edit screens instead of this query.
|
|
11
10
|
export const bySlugQuery = defineQueryHandler({
|
|
12
11
|
name: "by-slug",
|
|
13
12
|
schema: z.object({
|
|
@@ -5,8 +5,8 @@ import { pagesTable } from "../table.js";
|
|
|
5
5
|
export const byTenantPublishedQuery = defineQueryHandler({
|
|
6
6
|
name: "by-tenant-published",
|
|
7
7
|
schema: z.object({
|
|
8
|
-
/** Optional cross-tenant read —
|
|
9
|
-
* by-slug.query
|
|
8
|
+
/** Optional cross-tenant read — only for SystemAdmin. Matches the override
|
|
9
|
+
* logic in by-slug.query. */
|
|
10
10
|
tenantIdOverride: z.string().min(1).optional(),
|
|
11
11
|
}),
|
|
12
12
|
access: { roles: ["anonymous", "User", "TenantAdmin", "SystemAdmin"] },
|
|
@@ -14,12 +14,10 @@ const langSchema = z
|
|
|
14
14
|
.max(8)
|
|
15
15
|
.regex(/^[a-z]{2}(-[a-z]{2})?$/i, "lang must be ISO 639-1 (e.g. de, en, en-us)");
|
|
16
16
|
const executor = createEventStoreExecutor(pagesTable, pageEntity, { entityName: "page" });
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// wenn im Payload weggelassen (undefined) — damit ein Publish-Toggle nicht
|
|
22
|
-
// den Body überschreiben muss und umgekehrt.
|
|
17
|
+
// Upserts one page per (tenantId, slug, lang). The tenant scope defaults to event.user;
|
|
18
|
+
// SystemAdmin can write to another tenant via `tenantIdOverride` (typically SYSTEM_TENANT_ID
|
|
19
|
+
// for app-wide pages). On update, omitted published/description/ogImage values are preserved
|
|
20
|
+
// so a publish toggle does not overwrite the body, and vice versa.
|
|
23
21
|
export const setWrite = defineWriteHandler({
|
|
24
22
|
name: "set",
|
|
25
23
|
schema: z.object({
|
|
@@ -30,7 +28,7 @@ export const setWrite = defineWriteHandler({
|
|
|
30
28
|
description: z.string().max(500).nullable().optional(),
|
|
31
29
|
ogImage: z.string().max(2000).nullable().optional(),
|
|
32
30
|
published: z.boolean().optional(),
|
|
33
|
-
/** Cross-tenant write —
|
|
31
|
+
/** Cross-tenant write — only SystemAdmin (for example, SYSTEM_TENANT_ID pages). */
|
|
34
32
|
tenantIdOverride: z.string().min(1).optional(),
|
|
35
33
|
}),
|
|
36
34
|
access: { roles: ["TenantAdmin", "SystemAdmin"] },
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// Admin
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// (
|
|
7
|
-
//
|
|
8
|
-
//
|
|
1
|
+
// Admin authoring screens for the `page` entity. These are JSON-safe data only —
|
|
2
|
+
// the generic DataTable/form renderer mounts them, so no React component is
|
|
3
|
+
// needed. Both MUST be registered in the managed-pages feature (not in the
|
|
4
|
+
// app): the boot validator requires `entity: "page"` to be declared in the
|
|
5
|
+
// same feature as the screen. Navigation and workspace placement remain app-
|
|
6
|
+
// specific (`default` workspace is an app singleton) — the app points to this
|
|
7
|
+
// via `r.nav({ screen: "managed-pages:screen:page-list" })`.
|
|
8
|
+
// Cross-feature Nav→Screen is validated against the global screen QN set.
|
|
9
9
|
const ADMIN_ROLES = ["TenantAdmin", "SystemAdmin"];
|
|
10
10
|
export const pageListScreen = {
|
|
11
11
|
id: "page-list",
|
|
@@ -64,9 +64,9 @@ export const pageEditScreen = {
|
|
|
64
64
|
{ field: "title", span: 2 },
|
|
65
65
|
{ field: "description", span: 2 },
|
|
66
66
|
{ field: "ogImage", span: 2 },
|
|
67
|
-
// Publish/Unpublish:
|
|
68
|
-
//
|
|
69
|
-
// rowAction-payload
|
|
67
|
+
// Publish/Unpublish: the `published` toggle here IS the publishing
|
|
68
|
+
// mechanism (there is no separate one-click list action —
|
|
69
|
+
// rowAction-payload cannot inject constants).
|
|
70
70
|
{ field: "published", span: 1 },
|
|
71
71
|
],
|
|
72
72
|
},
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// Test
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// Test/seed helper for managed-pages. Creates a page directly through the
|
|
2
|
+
// event-store executor—the same path as the real set handler, but without an
|
|
3
|
+
// access check. Default ifExists="skip".
|
|
4
4
|
import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
5
5
|
import { runEventStoreSeed, TestUsers, } from "@cosmicdrift/kumiko-framework/seeding";
|
|
6
6
|
import { pageEntity, pagesTable } from "./table.js";
|
|
7
7
|
const executor = createEventStoreExecutor(pagesTable, pageEntity, { entityName: "page" });
|
|
8
8
|
export async function seedPage(db, opts) {
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
9
|
+
// The default user must have user.tenantId === opts.tenantId; otherwise the
|
|
10
|
+
// event-store stream ends up in the wrong tenant bucket → version_conflict
|
|
11
|
+
// on subsequent real writes. TestUsers.systemAdmin is testTenantId(1).
|
|
12
12
|
const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
|
|
13
13
|
const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
|
|
14
14
|
const existing = await fetchOne(db, pagesTable, {
|
|
@@ -36,8 +36,8 @@ export async function seedPage(db, opts) {
|
|
|
36
36
|
if (!result.isSuccess) {
|
|
37
37
|
throw new Error(`seedPage create failed: ${JSON.stringify(result)}`);
|
|
38
38
|
}
|
|
39
|
-
// @cast-boundary db-row: executor.create result.data
|
|
40
|
-
// Drizzle
|
|
39
|
+
// @cast-boundary db-row: executor.create result.data is the inserted
|
|
40
|
+
// Drizzle row (Record<string, unknown>), projected from RETURNING.
|
|
41
41
|
const data = result.data;
|
|
42
42
|
if (data.id === undefined) {
|
|
43
43
|
throw new Error("seedPage: executor.create did not return an id");
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { createBooleanField, createEntity, createTextField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
// Page —
|
|
4
|
-
//
|
|
5
|
-
// Markdown
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
3
|
+
// Page — a tenant-editable, server-rendered public page (landing,
|
|
4
|
+
// about, custom). Exactly one row per (tenantId, slug, lang). The body is
|
|
5
|
+
// Markdown, rendered securely on the server via page-render. `published`
|
|
6
|
+
// gates delivery to anonymous visitors: drafts return 404. description and
|
|
7
|
+
// ogImage support SEO and social previews. SYSTEM_TENANT_ID is used for
|
|
8
|
+
// app-wide pages; otherwise the page belongs to the tenant resolved from the
|
|
9
|
+
// host via resolveApexTenant during rendering.
|
|
9
10
|
export const pageEntity = createEntity({
|
|
10
11
|
table: "read_pages",
|
|
11
12
|
description: "One tenant-editable public web page, unique per slug and language, holding a markdown body plus the title, SEO description and OG image, with a published flag that decides whether anonymous visitors are served it or get a 404.",
|
|
@@ -32,12 +33,12 @@ export const pageEntity = createEntity({
|
|
|
32
33
|
personal: false,
|
|
33
34
|
reason: "is_business_data",
|
|
34
35
|
}),
|
|
35
|
-
// Body
|
|
36
|
-
// (Markdown),
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// maxLengths
|
|
40
|
-
//
|
|
36
|
+
// Body and description are tenant-admin-authored business content
|
|
37
|
+
// (Markdown), not user-generated PII. `multiline` makes the entityEdit
|
|
38
|
+
// renderer output a <textarea> (createLongTextField currently has a
|
|
39
|
+
// rendering gap: edit.ts/render-field.tsx only gates on type==="text").
|
|
40
|
+
// maxLengths mirror the handler schemas (set.write and convention CRUD
|
|
41
|
+
// derive their zod caps from these field maxLengths).
|
|
41
42
|
body: createTextField({
|
|
42
43
|
multiline: { rows: 16 },
|
|
43
44
|
maxLength: 100_000,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
2
2
|
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
3
3
|
export type ManagedPagesClientOptions = {
|
|
4
|
-
/** Key-wise
|
|
4
|
+
/** Key-wise overrides of the default bundles (de/en). */
|
|
5
5
|
readonly translations?: TranslationsByLocale;
|
|
6
6
|
};
|
|
7
7
|
export declare function managedPagesClient(options?: ManagedPagesClientOptions): ClientFeatureDefinition;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// Client
|
|
2
|
-
//
|
|
3
|
-
// (entityList/entityEdit/configEdit),
|
|
4
|
-
//
|
|
5
|
-
// [managedPagesClient()] })
|
|
1
|
+
// Client feature factory for managed-pages. It provides ONLY translations —
|
|
2
|
+
// the screens (page-list/page-edit/branding-settings) are schema-driven
|
|
3
|
+
// (entityList/entityEdit/configEdit), so no custom React components are
|
|
4
|
+
// registered. Apps mount it in createKumikoApp({ clientFeatures:
|
|
5
|
+
// [managedPagesClient()] }) so the admin labels render translated.
|
|
6
6
|
import { mergeTranslations } from "@cosmicdrift/kumiko-renderer";
|
|
7
7
|
import { defaultTranslations } from "./default-translations.js";
|
|
8
8
|
export function managedPagesClient(options) {
|
|
@@ -48,7 +48,7 @@ export const MANAGED_PAGES_I18N = {
|
|
|
48
48
|
"managed-pages:confirms.page-delete": {
|
|
49
49
|
en: "Delete this page?",
|
|
50
50
|
},
|
|
51
|
-
//
|
|
51
|
+
// Only used when allowCustomCss:true in the screen; supplied unconditionally
|
|
52
52
|
"managed-pages:entity:__config-edit__:field:customCss": { en: "Custom CSS" },
|
|
53
53
|
"managed-pages:branding.section.custom-css": { en: "Custom CSS" },
|
|
54
54
|
};
|