@cosmicdrift/kumiko-bundled-features 0.385.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/agent-tools/tool-dispatch.js +0 -2
- 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
|
@@ -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";
|
|
@@ -151,11 +151,11 @@ export async function seedSystemTemplate(db, opts) {
|
|
|
151
151
|
}
|
|
152
152
|
throw new Error(`seedSystemTemplate create failed: ${JSON.stringify(result)}`);
|
|
153
153
|
}
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
154
|
+
const createdId = propertyOf(result.data, "id");
|
|
155
|
+
if (createdId === undefined) {
|
|
156
156
|
throw new Error("seedSystemTemplate: executor.create did not return an id");
|
|
157
157
|
}
|
|
158
|
-
return { id: String(
|
|
158
|
+
return { id: String(createdId) };
|
|
159
159
|
},
|
|
160
160
|
update: (row) => applyUpdate(row, existingRow),
|
|
161
161
|
});
|
|
@@ -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",
|
|
@@ -107,7 +107,7 @@ function makeTreeProvider(tenantIdOverride, collectionId) {
|
|
|
107
107
|
const csrf = readCsrfToken();
|
|
108
108
|
if (csrf !== undefined)
|
|
109
109
|
headers[CSRF_HEADER_NAME] = csrf;
|
|
110
|
-
// kumiko-lint-ignore no-raw-hooks
|
|
110
|
+
// kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
|
|
111
111
|
fetch("/api/query", {
|
|
112
112
|
method: "POST",
|
|
113
113
|
headers,
|
|
@@ -224,7 +224,7 @@ function TextBlockEditor({ target, }) {
|
|
|
224
224
|
const [savedMsg, setSavedMsg] = useState(null);
|
|
225
225
|
// Sync loaded data into the form state. loaded === null means the block does
|
|
226
226
|
// not exist yet — empty form for the create flow.
|
|
227
|
-
// kumiko-lint-ignore no-raw-hooks
|
|
227
|
+
// kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
|
|
228
228
|
useEffect(() => {
|
|
229
229
|
if (loading)
|
|
230
230
|
return;
|
package/dist/tenant/feature.js
CHANGED
|
@@ -54,10 +54,10 @@ export function createTenantFeature(options) {
|
|
|
54
54
|
r.entity({ name: "tenant-invitation", ...tenantInvitationEntity });
|
|
55
55
|
r.config({
|
|
56
56
|
keys: {
|
|
57
|
-
//
|
|
57
|
+
// Core tenant settings — tenant admins can change them; all users can read them.
|
|
58
58
|
companyName: createTenantConfig("text", { default: "" }),
|
|
59
|
-
//
|
|
60
|
-
//
|
|
59
|
+
// Curated subset of IANA time zones covering the most relevant practical cases.
|
|
60
|
+
// Extend it when a real need arises.
|
|
61
61
|
timezone: createTenantConfig("select", {
|
|
62
62
|
default: "Europe/Berlin",
|
|
63
63
|
options: [
|
|
@@ -79,16 +79,16 @@ export function createTenantFeature(options) {
|
|
|
79
79
|
default: "de",
|
|
80
80
|
options: ["de", "en", "fr", "es"],
|
|
81
81
|
}),
|
|
82
|
-
// SMTP —
|
|
83
|
-
//
|
|
82
|
+
// SMTP settings — only SystemAdmin (platform operator) can change them; smtpPass is
|
|
83
|
+
// encrypted and readable only by SystemAdmin.
|
|
84
84
|
smtpHost: createTenantConfig("text", { write: access.systemAdmin, read: access.admin }),
|
|
85
85
|
smtpPass: createTenantConfig("text", {
|
|
86
86
|
write: access.systemAdmin,
|
|
87
87
|
read: access.systemAdmin,
|
|
88
88
|
encrypted: true,
|
|
89
89
|
}),
|
|
90
|
-
// System
|
|
91
|
-
//
|
|
90
|
+
// System settings — changeable only programmatically by SYSTEM_USER;
|
|
91
|
+
// tenant admins see them as read-only.
|
|
92
92
|
priceModel: createSystemConfig("select", {
|
|
93
93
|
default: "basic",
|
|
94
94
|
options: ["basic", "pro", "enterprise"],
|
|
@@ -22,7 +22,7 @@ async function loadMemberUserIds(db, tenantId) {
|
|
|
22
22
|
const memberships = await selectMany(db, tenantMembershipsTable, { tenantId });
|
|
23
23
|
return [...new Set(memberships.map((row) => String(row["userId"])))].sort(compareIds);
|
|
24
24
|
}
|
|
25
|
-
// Label source behind every `user:user` reference column
|
|
25
|
+
// Label source behind every `user:user` reference column. The
|
|
26
26
|
// entity-convention lookup, user:query:user:list, is a SystemAdmin
|
|
27
27
|
// cross-tenant roster, so a TenantAdmin got a 403 and every actor cell fell
|
|
28
28
|
// back to the raw UUID. Deliberately narrower than tenant:query:members:
|
|
@@ -16,7 +16,7 @@ export const membersQuery = defineQueryHandler({
|
|
|
16
16
|
name: "members",
|
|
17
17
|
schema: z.object({
|
|
18
18
|
// Optional single-user filter — audit detail (and similar) only need one
|
|
19
|
-
// member's display name, not the full decrypted roster
|
|
19
|
+
// member's display name, not the full decrypted roster.
|
|
20
20
|
userId: z.string().min(1).optional(),
|
|
21
21
|
}),
|
|
22
22
|
access: { roles: access.admin },
|
|
@@ -38,7 +38,7 @@ function compareTeamRows(a, b, field, dir) {
|
|
|
38
38
|
const bv = field === "email" ? (b.email ?? "") : b.status;
|
|
39
39
|
return av.localeCompare(bv) * sign;
|
|
40
40
|
}
|
|
41
|
-
// User-selected facet filters (payload.filters
|
|
41
|
+
// User-selected facet filters (payload.filters) — `status` is the
|
|
42
42
|
// only filterable field here: it's synthesized from which table a row came
|
|
43
43
|
// from, not a stored column, so there is nothing else meaningful to filter
|
|
44
44
|
// on server-side yet. `filter` (singular, screen-level static filter) is
|
|
@@ -5,7 +5,7 @@ import * as z from "zod";
|
|
|
5
5
|
import { decryptTenantNames, takeTenantsMatchingDecryptedName } from "../decrypt-tenant-names.js";
|
|
6
6
|
import { tenantTable } from "../schema/tenant.js";
|
|
7
7
|
import { isSystemAdmin } from "./is-system-admin.js";
|
|
8
|
-
// Label source
|
|
8
|
+
// Label source for every `tenant:tenant` reference column. The
|
|
9
9
|
// entity-convention lookup, tenant:query:tenant:list, is a SystemAdmin-only
|
|
10
10
|
// entity-list handler, so a TenantAdmin got a 403 and every tenant cell fell
|
|
11
11
|
// back to the raw UUID. A SystemAdmin keeps the global reach tenant:list gave
|
|
@@ -1,44 +1,42 @@
|
|
|
1
|
-
// Tenant-
|
|
1
|
+
// Tenant invitations are pre-membership records using a magic-link token flow.
|
|
2
2
|
//
|
|
3
3
|
// Lifecycle:
|
|
4
|
-
// 1.
|
|
5
|
-
//
|
|
6
|
-
// 2.
|
|
7
|
-
// 3.
|
|
8
|
-
// a)
|
|
9
|
-
// b) Anonymous +
|
|
10
|
-
// c) Anonymous +
|
|
11
|
-
// 4.
|
|
12
|
-
// 5.
|
|
13
|
-
// 6.
|
|
14
|
-
// (
|
|
4
|
+
// 1. An admin invites an email → a DB row is created with status="pending",
|
|
5
|
+
// and a random token is stored in Redis (signup-style bidirectional flow).
|
|
6
|
+
// 2. An email containing the activation URL is sent to the invitee.
|
|
7
|
+
// 3. Clicking the link follows one of three branches:
|
|
8
|
+
// a) Logged in + email matches the session user → membership is added
|
|
9
|
+
// b) Anonymous + email exists in users → login → automatic acceptance
|
|
10
|
+
// c) Anonymous + new email → set a password → user and membership are created
|
|
11
|
+
// 4. On success: status="accepted", and the Redis token is deleted (single-use).
|
|
12
|
+
// 5. When cancelled by an admin: status="cancelled", and the Redis token is deleted.
|
|
13
|
+
// 6. When the TTL expires: Redis removes the token, while the DB row remains
|
|
14
|
+
// status="pending" (a cleanup job marks it as "expired" separately).
|
|
15
15
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// invalid-token.
|
|
16
|
+
// Redis-TTL is the single source of truth for expiry. DB-row.expiresAt is only
|
|
17
|
+
// for UI display ("expires in 6 days"). On lookup, a pending DB row without
|
|
18
|
+
// a Redis token is effectively expired, so acceptance fails with invalid-token.
|
|
20
19
|
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// (
|
|
20
|
+
// Idempotency: a second invite for the same (tenantId, email) while pending
|
|
21
|
+
// reuses the existing row, refreshes the Redis token, and sends the email
|
|
22
|
+
// (analogous to signup resend).
|
|
24
23
|
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
25
24
|
import { createEntity, createMultiSelectField, createNumberField, createSelectField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
26
25
|
// kumiko-lint-ignore cross-feature-import global-role options are owned by the user feature
|
|
27
26
|
import { GLOBAL_ROLE_OPTIONS } from "../user/web/constants.js";
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
27
|
+
// The status constant object prevents handler code from using magic strings.
|
|
28
|
+
// If a value is renamed (for example, "cancelled" → "revoked"), every caller
|
|
29
|
+
// fails at once instead of having stale values scattered across five locations.
|
|
31
30
|
export const INVITATION_STATUS = {
|
|
32
31
|
pending: "pending",
|
|
33
32
|
accepted: "accepted",
|
|
34
33
|
cancelled: "cancelled",
|
|
35
34
|
expired: "expired",
|
|
36
35
|
};
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// Refactoring der Object-Keys.
|
|
36
|
+
// The order MUST be bit-for-bit identical to the database migration. Object.values
|
|
37
|
+
// preserves insertion order (stable for string keys under the JS spec). Reordering
|
|
38
|
+
// INVITATION_STATUS generates a new drizzle-kit migration. The hardcoded tuple
|
|
39
|
+
// also guards against accidental refactoring of the object keys.
|
|
42
40
|
export const INVITATION_STATUSES = [
|
|
43
41
|
INVITATION_STATUS.pending,
|
|
44
42
|
INVITATION_STATUS.accepted,
|
|
@@ -48,11 +46,11 @@ export const INVITATION_STATUSES = [
|
|
|
48
46
|
export const tenantInvitationEntity = createEntity({
|
|
49
47
|
table: "read_tenant_invitations",
|
|
50
48
|
fields: {
|
|
51
|
-
//
|
|
52
|
-
//
|
|
49
|
+
// The invited email is normalized case-insensitively on insert.
|
|
50
|
+
// It remains PII until acceptance; afterward, the user owns the email in users.
|
|
53
51
|
email: createTextField({ required: true, maxLength: 320, personal: "self", find: "exact" }),
|
|
54
|
-
//
|
|
55
|
-
//
|
|
52
|
+
// The membership role granted to the user on acceptance. The handler defaults
|
|
53
|
+
// to "Admin" (a co-admin pattern for small teams).
|
|
56
54
|
role: createTextField({
|
|
57
55
|
required: true,
|
|
58
56
|
maxLength: 50,
|
|
@@ -73,11 +71,11 @@ export const tenantInvitationEntity = createEntity({
|
|
|
73
71
|
required: true,
|
|
74
72
|
default: "pending",
|
|
75
73
|
}),
|
|
76
|
-
//
|
|
74
|
+
// ID of the inviting admin, retained for the audit trail ("who invited").
|
|
77
75
|
// Self-referencing ownerField: the field's own value IS the owner userId.
|
|
78
|
-
// lookupable: the delete
|
|
79
|
-
//
|
|
80
|
-
//
|
|
76
|
+
// lookupable: the delete hook filters "invitations sent by this user"
|
|
77
|
+
// through the generated blind-index column instead of decrypting and scanning
|
|
78
|
+
// the entire tenant (see user-data-rights-defaults' invitation hook).
|
|
81
79
|
invitedBy: createTextField({
|
|
82
80
|
required: true,
|
|
83
81
|
personal: { of: "invitedBy" },
|
|
@@ -91,11 +89,10 @@ export const tenantInvitationEntity = createEntity({
|
|
|
91
89
|
// UI-Anzeige — Wahrheit liegt in Redis-TTL.
|
|
92
90
|
expiresAt: createTimestampField({ required: true }),
|
|
93
91
|
},
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
// im handler trivial.
|
|
92
|
+
// One invitation row per (tenantId, email). On re-invite after cancellation or
|
|
93
|
+
// acceptance, the existing row is updated: status pending → cancelled → pending,
|
|
94
|
+
// and expiresAt is refreshed. This prevents duplicate tokens and makes resend
|
|
95
|
+
// idempotency trivial in the handler.
|
|
99
96
|
indexes: [
|
|
100
97
|
{
|
|
101
98
|
unique: true,
|
|
@@ -11,9 +11,9 @@ import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/eng
|
|
|
11
11
|
// the old serial-id design and keeps duplicate-write protection at the
|
|
12
12
|
// database level independent of the handler lookup.
|
|
13
13
|
//
|
|
14
|
-
// Single
|
|
15
|
-
//
|
|
16
|
-
// unique
|
|
14
|
+
// Single source of truth: `tenantMembershipEntity`. The database table is
|
|
15
|
+
// derived from the EntityDefinition through buildEntityTable, and the
|
|
16
|
+
// unique index is declared via entity.indexes.
|
|
17
17
|
export const tenantMembershipEntity = createEntity({
|
|
18
18
|
table: "read_tenant_memberships",
|
|
19
19
|
fields: {
|
|
@@ -10,9 +10,9 @@ export const TENANT_LIFECYCLE_STATUSES = [
|
|
|
10
10
|
export const tenantEntity = createEntity({
|
|
11
11
|
description: "A tenant, the isolated workspace every other record belongs to, holding its key and display name, whether it is enabled, and its destruction-lifecycle state.",
|
|
12
12
|
table: "read_tenants",
|
|
13
|
-
// tenant.id
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// `tenant.id` is the `tenantId` value referenced by every other table as a foreign key.
|
|
14
|
+
// Every `tenantId` column is UUID, so `tenant.id` must also be UUID; otherwise
|
|
15
|
+
// the tenant lookup never finds a match. The default is `gen_random_uuid()`.
|
|
16
16
|
fields: {
|
|
17
17
|
key: createTextField({
|
|
18
18
|
required: true,
|
|
@@ -48,12 +48,10 @@ export const tenantEntity = createEntity({
|
|
|
48
48
|
destroyStartedAt: createTimestampField({}),
|
|
49
49
|
destroyedAt: createTimestampField({}),
|
|
50
50
|
},
|
|
51
|
-
// tenant.key
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
// Slug claimen, beide commits durch, der dritte User landet auf einem
|
|
56
|
-
// shared admin-URL-prefix.
|
|
51
|
+
// `tenant.key` appears in admin URLs (`admin.<host>/<key>/...`) and must be unique.
|
|
52
|
+
// Without a unique constraint, concurrent self-signup confirmation could pass
|
|
53
|
+
// the `generateUniqueName` `isAvailable` check before either insert, allowing
|
|
54
|
+
// two tabs to claim the same slug and causing users to share an admin URL prefix.
|
|
57
55
|
indexes: [{ unique: true, columns: ["key"] }],
|
|
58
56
|
});
|
|
59
57
|
export const tenantTable = buildEntityTable("tenant", tenantEntity);
|
package/dist/tenant/screens.js
CHANGED
|
@@ -141,7 +141,7 @@ export function createMembersScreen(options) {
|
|
|
141
141
|
// feature.ts when `TenantFeatureOptions.inviteScreen` is set — see
|
|
142
142
|
// createMembersScreen's doc comment above for why.
|
|
143
143
|
export function createInviteCreateScreen(assignableAppRoles = new Map()) {
|
|
144
|
-
// Admin sees this screen too, so only app roles Admin may grant are offered
|
|
144
|
+
// Admin sees this screen too, so only app roles Admin may grant are offered.
|
|
145
145
|
const appRoleOptions = [...assignableAppRoles]
|
|
146
146
|
.filter(([, assignableFrom]) => isAssignableByRole(assignableFrom, "Admin"))
|
|
147
147
|
.map(([role]) => role);
|
package/dist/tenant/seeding.d.ts
CHANGED
|
@@ -14,12 +14,13 @@ export type SeedTenantMembershipOptions = {
|
|
|
14
14
|
readonly by?: SessionUser;
|
|
15
15
|
};
|
|
16
16
|
export type SeedTenantOptions = {
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
/**
|
|
18
|
+
* Stable UUID required for fixtures so the FE/BE can hardcode the same ID. The sample switcher
|
|
19
|
+
* displays the tenant by name, while tests verify memberships against this exact ID; without it,
|
|
20
|
+
* callers would need an extra lookup by key.
|
|
21
|
+
*/
|
|
21
22
|
readonly id: TenantId;
|
|
22
|
-
/** URL
|
|
23
|
+
/** URL/slug form (for example, "dev" or "acme"). Indexed unique in the database. */
|
|
23
24
|
readonly key: string;
|
|
24
25
|
/** Human-readable label (im Switcher angezeigt). */
|
|
25
26
|
readonly name: string;
|
package/dist/tenant/seeding.js
CHANGED
|
@@ -69,14 +69,14 @@ function buildSeedHookNotify(context, scopedUser, targetTenantId, notifyTiming)
|
|
|
69
69
|
// registered entity/handler hooks fire (search-index/SSE system hooks are
|
|
70
70
|
// wired at server-boot and out of reach here).
|
|
71
71
|
//
|
|
72
|
-
// Tenant re-scope
|
|
72
|
+
// Tenant re-scope: when `targetTenantId` is set we rebuild the
|
|
73
73
|
// tenant-bound pieces of the context (`_tenantId`, `db`, `notify`,
|
|
74
74
|
// `hasFeature`, `user.tenantId`) — a shallow `{ ...ctx, _tenantId }` left
|
|
75
75
|
// closures over the caller's tenant (self-signup is anonymous/system).
|
|
76
76
|
// `query`/`write` bridges still share the caller's identity; hooks that
|
|
77
77
|
// need a full identity switch use `writeAs`/`queryAs`.
|
|
78
78
|
//
|
|
79
|
-
// afterCommit
|
|
79
|
+
// afterCommit: when `hooks.context.scheduleAfterCommit` is present
|
|
80
80
|
// (HandlerContext from a live write), afterCommit hooks are queued onto the
|
|
81
81
|
// dispatcher's sink and flush post-commit. Without a sink (fixture / plain
|
|
82
82
|
// Connection) they still fire immediately — there is no outer TX to wait for.
|
|
@@ -161,19 +161,19 @@ target) {
|
|
|
161
161
|
*/
|
|
162
162
|
export async function seedTenant(db, options, hooks) {
|
|
163
163
|
const by = options.by ?? TestUsers.systemAdmin;
|
|
164
|
-
// executor.create
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
// seedTenantMembership nötig.
|
|
164
|
+
// executor.create expects a TenantDb with an .insert()-API, not the raw
|
|
165
|
+
// DbConnection. Although the tenant aggregate is not tenant-scoped, the
|
|
166
|
+
// wrapper is required by the runtime API. by.tenantId is sufficient; unlike
|
|
167
|
+
// seedTenantMembership, no override semantics are needed.
|
|
169
168
|
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
170
169
|
const existing = await fetchOne(db, tenantTable, { id: options.id });
|
|
171
170
|
if (existing)
|
|
172
171
|
return { id: options.id };
|
|
173
|
-
//
|
|
174
|
-
// (
|
|
175
|
-
//
|
|
176
|
-
//
|
|
172
|
+
// Idempotency: the aggregate may exist in the event store without a
|
|
173
|
+
// projection row (projection drift after a rebuild, manual DELETE, or async
|
|
174
|
+
// lag). If the stream version is > 0, skip create() to avoid
|
|
175
|
+
// version_conflict. Return the ID; the next dispatcher cycle can rebuild the
|
|
176
|
+
// projection.
|
|
177
177
|
const streamVersion = await getUnscopedAggregateStreamMaxVersion(db, options.id);
|
|
178
178
|
if (streamVersion > 0)
|
|
179
179
|
return { id: options.id };
|
|
@@ -206,7 +206,7 @@ export async function seedTenant(db, options, hooks) {
|
|
|
206
206
|
*/
|
|
207
207
|
export async function seedTenantMembership(db, options,
|
|
208
208
|
// Optional, append-only — same rationale as seedTenant's hooks param
|
|
209
|
-
//
|
|
209
|
+
// fires tenantMembership's postSave hooks (e.g. a Welcome-
|
|
210
210
|
// notification or default-notification-preferences hook keyed off
|
|
211
211
|
// `allOf: "tenantMembership"`) for fixtures/self-signup that opt in.
|
|
212
212
|
// Omit to keep today's hook-less behavior.
|
package/dist/tenant/testing.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// einen lockout-test-Knopf einbaut).
|
|
1
|
+
// `/testing` re-exports `/seeding`; it is no longer the home of the seed helpers.
|
|
2
|
+
// The helpers live in `/seeding` because they are also consumed by the
|
|
3
|
+
// development-server bootstrap (`runDevApp`), not only by tests. Keep their
|
|
4
|
+
// stable contract here; test-specific options do not belong in this module,
|
|
5
|
+
// because they could break development boots when a lockout-test option is added.
|
|
7
6
|
export * from "./seeding.js";
|
|
@@ -14,11 +14,11 @@ export const MEMBER_STATUS_CELL_COMPONENT = "MemberStatusCell";
|
|
|
14
14
|
export const MEMBER_ROLES_CELL_COMPONENT = "MemberRolesCell";
|
|
15
15
|
/** Closed allowlist for invite-role picker — never free text (escalation guard). */
|
|
16
16
|
// Admin (rank 2) shares the invite-create screen with TenantAdmin — TenantAdmin
|
|
17
|
-
// must not appear here or Admin sees an unassignable option
|
|
17
|
+
// must not appear here or Admin sees an unassignable option.
|
|
18
18
|
export const DEFAULT_INVITE_ROLE_OPTIONS = ["User", "Editor", "Admin"];
|
|
19
19
|
// Full rank list for memberRolesEditScreen: it is prefilled with a member's
|
|
20
20
|
// *current* roles, so it must represent every rank a membership can hold,
|
|
21
|
-
// including TenantAdmin
|
|
21
|
+
// including TenantAdmin. The screen hides what the caller may not
|
|
22
22
|
// assign via TenantQueries.memberRoleAvailability.
|
|
23
23
|
export const OWNER_INVITE_ROLE_OPTIONS = [
|
|
24
24
|
"User",
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
// Audit trail for a completed claim (
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// no predecessor version and can never conflict with a concurrent write on
|
|
8
|
-
// the entity it describes.
|
|
2
|
+
// Audit trail for a completed claim (audit-entry requirement: names the source tenant, destination
|
|
3
|
+
// tenant, entities and their counts). Its own aggregate, decoupled from the transferred root's
|
|
4
|
+
// stream — same reasoning as sessions' SESSION_REVOKED_EVENT: a fresh aggregate id per occurrence
|
|
5
|
+
// needs no predecessor version and can never conflict with a concurrent write on the entity it
|
|
6
|
+
// describes.
|
|
9
7
|
//
|
|
10
8
|
// _SHORT — r.defineEvent(short, schema) in feature.ts, framework prefixes it
|
|
11
9
|
// to the QN below.
|
|
@@ -3,7 +3,7 @@ import { EXT_SIGNUP_HANDOVER } from "../shared/index.js";
|
|
|
3
3
|
import { TENANT_HANDOVER_CLAIMED_EVENT_SHORT, tenantHandoverClaimedSchema } from "./events.js";
|
|
4
4
|
import { createClaimTenantHandoverHandler, } from "./handlers/claim.write.js";
|
|
5
5
|
import { createSignupHandoverProvider } from "./signup-handover-provider.js";
|
|
6
|
-
// tenant-handover —
|
|
6
|
+
// tenant-handover — the ONE write a
|
|
7
7
|
// try-before-signup (or guest-checkout, demo-to-account) flow needs once an
|
|
8
8
|
// anonymous run is done and the visitor has a fresh tenant. No general
|
|
9
9
|
// tenant-merge tool, no copy — this is an ownership change on rows a
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Try-before-signup ownership handover
|
|
1
|
+
// Try-before-signup ownership handover, expressed as a
|
|
2
2
|
// row-bound grant: the subject is the transferred run's own row id, the
|
|
3
3
|
// anchor is the SOURCE tenant id it currently lives under. Redeeming the
|
|
4
4
|
// grant is the ownership change itself — the claim handler's commitAnchor
|
|
@@ -17,7 +17,7 @@ function notTransferable(entityType) {
|
|
|
17
17
|
details: { entityType },
|
|
18
18
|
}));
|
|
19
19
|
}
|
|
20
|
-
// The try-before-signup ownership handover
|
|
20
|
+
// The try-before-signup ownership handover: claims an
|
|
21
21
|
// anonymous run into the caller's own tenant, legitimized by a row-bound
|
|
22
22
|
// grant the anonymous flow minted (see ../grant.ts). Idempotent — a second
|
|
23
23
|
// call with the same token fails the same way a forged one would, because
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// The actual ownership change
|
|
1
|
+
// The actual ownership change: raw SQL against the
|
|
2
2
|
// read-model tables, because moving a row across the tenant boundary is
|
|
3
3
|
// exactly the kind of write the framework's entity write map cannot express
|
|
4
4
|
// (it is single-tenant-scoped by design — that boundary is the whole point
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
// `transaction()` call, rolling back everything the handler already did).
|
|
16
16
|
// `moveRootRow` — called as row-bound-grant's `commitAnchor` — is therefore
|
|
17
17
|
// the ONLY statement that must itself combine the anchor-spend with the
|
|
18
|
-
// first write
|
|
19
|
-
// its work to a crash while the grant is already burned
|
|
18
|
+
// first write: a write issued after `ok: true` can lose
|
|
19
|
+
// its work to a crash while the grant is already burned. Everything after
|
|
20
20
|
// it rides the same transaction: if a later step throws (an undeclared
|
|
21
|
-
// child entity,
|
|
21
|
+
// child entity, the named-error requirement), the WHOLE
|
|
22
22
|
// transaction — root row included — rolls back, so a caller can safely
|
|
23
23
|
// retry the same token after fixing the app's `transferable` declarations.
|
|
24
24
|
import { entityTableFromRegistry, executeRawQuery, extractTableName, physicalColumnName, toPostgresArrayLiteral, } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -41,8 +41,7 @@ export async function moveRootRow(args) {
|
|
|
41
41
|
// history + storage-usage counters — fileRef is a standard ES entity (see
|
|
42
42
|
// files-storage-tracking.md), so without those two follow-ups a later write
|
|
43
43
|
// against a moved fileRef can't load its stream, and a projection rebuild
|
|
44
|
-
// would put the row back into the source tenant
|
|
45
|
-
// gap, item 4).
|
|
44
|
+
// would put the row back into the source tenant.
|
|
46
45
|
async function moveFileRefs(args) {
|
|
47
46
|
if (args.entityIds.length === 0)
|
|
48
47
|
return 0;
|
|
@@ -136,7 +135,7 @@ async function moveEdgeRows(args) {
|
|
|
136
135
|
// Everything the root ownership write does NOT cover: the root's own event
|
|
137
136
|
// history + attached files, plus the rows, event history and attached files of
|
|
138
137
|
// every descendant the declared transfer graph reaches, however deep and by
|
|
139
|
-
// however many paths
|
|
138
|
+
// however many paths.
|
|
140
139
|
// Returns a count per moved entity name (the
|
|
141
140
|
// write handler turns this into the audit entry) — `fileRef` is a single
|
|
142
141
|
// pooled count across root + every child, since it is not itself part of the
|
|
@@ -170,7 +169,7 @@ export async function moveTransferGraph(args) {
|
|
|
170
169
|
transferredBy,
|
|
171
170
|
}));
|
|
172
171
|
const adjacency = resolveTransferAdjacency(registry, rootEntityName);
|
|
173
|
-
// A worklist, not a level-wise walk
|
|
172
|
+
// A worklist, not a level-wise walk: each batch of rows that actually
|
|
174
173
|
// changed hands becomes the parent ids for the edges leading away from its
|
|
175
174
|
// type. The same edge therefore runs again whenever a later round discovers
|
|
176
175
|
// more rows of its parent type, which is what a type reachable by two paths
|
|
@@ -180,7 +179,7 @@ export async function moveTransferGraph(args) {
|
|
|
180
179
|
// every statement filters on `tenantCol = sourceTenantId` and RETURNS only
|
|
181
180
|
// the rows it flipped, so a row enters this worklist exactly once and the
|
|
182
181
|
// source tenant holds finitely many. Do not add an edge-level visited set to
|
|
183
|
-
// "bound" this — that
|
|
182
|
+
// "bound" this — that would reintroduce the bug.
|
|
184
183
|
let pending = [
|
|
185
184
|
{ entityName: rootEntityName, rowIds: [rootRowId] },
|
|
186
185
|
];
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// tenant-handover's implementation of the shared signup-handover extension
|
|
2
|
-
// point
|
|
3
|
-
// auth-email-password's signup-request verify a grant against its root row
|
|
2
|
+
// point: lets auth-email-password's signup-request verify a grant against its root row
|
|
4
3
|
// WITHOUT spending the anchor (the anchor is spent once, by the claim
|
|
5
4
|
// signup-confirm runs afterwards, via a fresh short-lived grant this module
|
|
6
5
|
// mints) — see shared/signup-handover.ts for the extension contract and
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
// Resolves the declared transfer graph for a root entity type: the root
|
|
2
2
|
// itself, plus every registered entity that reaches it through a declared
|
|
3
|
-
// schema edge (
|
|
4
|
-
// the
|
|
5
|
-
// maintained per-app list).
|
|
3
|
+
// schema edge (framework CLAUDE.md premise 4 — the graph depth is read off
|
|
4
|
+
// the existing declarations, never a hand-maintained per-app list).
|
|
6
5
|
//
|
|
7
6
|
// The edge definition (parentRef + single-valued reference fields, minus
|
|
8
7
|
// `handover: "stay"`) lives in the framework so the boot validator's depth
|
|
9
8
|
// limit and the mover's traversal measure the same graph. What comes out is
|
|
10
9
|
// static adjacency, not a walk: the mover drives the actual traversal from the
|
|
11
|
-
// row ids it moves
|
|
12
|
-
//
|
|
10
|
+
// row ids it moves, because how deep a type sits depends on the rows found,
|
|
11
|
+
// not on the schema alone.
|
|
13
12
|
//
|
|
14
13
|
// `transferable: true` stays the only gate on what actually moves, and it is
|
|
15
14
|
// enforced by the caller against edges that turn out to have rows rather than
|
|
@@ -4,7 +4,7 @@ import { entitiesOf } from "../shared/index.js";
|
|
|
4
4
|
const log = createFallbackLogger("kumiko:boot");
|
|
5
5
|
// V4: tenantOwned-entity-without-hook gate. Mirrors user-data-rights' V3
|
|
6
6
|
// (validateGdprPiiHookCoverage) but for EXT_TENANT_DATA. Registered as this
|
|
7
|
-
// feature's own `r.bootCheck()` (
|
|
7
|
+
// feature's own `r.bootCheck()` (moved off the framework-internal
|
|
8
8
|
// boot-validator) — tenant-lifecycle owns EXT_TENANT_DATA
|
|
9
9
|
// (r.extendsRegistrar), so its own mount is the trigger, matching the
|
|
10
10
|
// original guard's "tenant-lifecycle mounted" gate exactly (unlike gating on
|
|
@@ -31,7 +31,7 @@ export function createTenantLifecycleFeature() {
|
|
|
31
31
|
// AND fulfils tenantLifecycleStatus so teardown state is visible with no per-app wiring.
|
|
32
32
|
r.extendsRegistrar(EXT_TENANT_LIFECYCLE_STATUS, {});
|
|
33
33
|
r.useExtension(EXT_TENANT_LIFECYCLE_STATUS, "tenant-lifecycle", tenantLifecycleStatusPlugin);
|
|
34
|
-
// GDPR-storage guard V4
|
|
34
|
+
// GDPR-storage guard V4 — moved off the framework-internal
|
|
35
35
|
// boot-validator onto this feature's own r.bootCheck(), since it owns
|
|
36
36
|
// EXT_TENANT_DATA: its own mount is the trigger, matching the original
|
|
37
37
|
// guard's "tenant-lifecycle mounted" gate exactly.
|