@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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// compliance-profiles-ops — platform-wide SystemAdmin visibility into
|
|
2
|
-
// tenants missing a compliance-profile selection
|
|
2
|
+
// tenants missing a compliance-profile selection.
|
|
3
3
|
//
|
|
4
4
|
// needs-profile (compliance-profiles) tells a TenantAdmin they must pick a
|
|
5
|
-
// profile, but stays TenantAdmin-only by design
|
|
5
|
+
// profile, but stays TenantAdmin-only by design — a SystemAdmin who
|
|
6
6
|
// owns a picker narrowed to access.systemAdmin has no query at all. Kept as
|
|
7
7
|
// a separate feature (mirrors folders-user-data/notes-history-user-data)
|
|
8
8
|
// rather than folded into compliance-profiles: this is the one genuinely
|
|
@@ -9,10 +9,10 @@ export type ReadinessMissingKey = {
|
|
|
9
9
|
export type RequiredKeyGate = (qualifiedName: string) => boolean;
|
|
10
10
|
export declare function buildProviderSelectionGate(ctx: HandlerContext, callerQn: string, user: SessionUser, db: TenantDb): Promise<RequiredKeyGate>;
|
|
11
11
|
export declare function collectMissingRequiredConfig(ctx: HandlerContext, callerQn: string, user: SessionUser, db: TenantDb, gate?: RequiredKeyGate, options?: {
|
|
12
|
-
/** Verdict
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
/** Verdict paths (rollup, themselves role-gated) MUST count without filtering:
|
|
13
|
+
* the per-key read filter protects the openToAll handler from information
|
|
14
|
+
* disclosure, but in the verdict it dropped SystemAdmin-gated required keys
|
|
15
|
+
* and incorrectly reported ready:true despite the gap. */
|
|
16
16
|
readonly skipAccessFilter?: boolean;
|
|
17
17
|
}): Promise<ReadinessMissingKey[]>;
|
|
18
18
|
export declare const readinessQuery: import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"readiness", z.ZodObject<{}, z.core.$strip>, {
|
|
@@ -95,7 +95,7 @@ export const readinessQuery = defineQueryHandler({
|
|
|
95
95
|
const db = requireSystemDb(ctx, "config:query:readiness", query.user.tenantId);
|
|
96
96
|
const missing = await collectMissingRequiredConfig(ctx, "config:query:readiness", query.user, db);
|
|
97
97
|
// Additive, display-ready fields for the admin-shell dashboard stat
|
|
98
|
-
// panel
|
|
98
|
+
// panel — `missing` itself stays untouched for existing
|
|
99
99
|
// consumers that read the array directly.
|
|
100
100
|
return {
|
|
101
101
|
missing,
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
// the NEW envelope: after a full run even a from-scratch rebuild only
|
|
17
17
|
// ever sees the current-KEK envelope.
|
|
18
18
|
//
|
|
19
|
-
// systemScope() fail-closed pattern
|
|
20
|
-
//
|
|
19
|
+
// systemScope() fail-closed pattern: the initial scan is intentionally
|
|
20
|
+
// cross-tenant (system-wide key rotation), acknowledged via
|
|
21
21
|
// UncheckedSystemDb.acknowledgeCrossTenant(). Rows are bucketed by tenant,
|
|
22
22
|
// and assertRowsTenant() re-verifies each row against its bucket's tenant
|
|
23
23
|
// right before the write — both checks are built locally from the exported
|
|
@@ -163,9 +163,8 @@ export const reencryptJob = async (rawPayload, ctx) => {
|
|
|
163
163
|
return "failed";
|
|
164
164
|
}
|
|
165
165
|
// Re-verify the row's own tenantId against the bucket it was scanned
|
|
166
|
-
// into, right before the write
|
|
167
|
-
//
|
|
168
|
-
// whole job.
|
|
166
|
+
// into, right before the write — a mismatch here fails this row only
|
|
167
|
+
// (via onRowError below), it does not abort the whole job.
|
|
169
168
|
sdbFor(tenantId).assertRowsTenant([row], "tenantId");
|
|
170
169
|
const plaintext = await cipher.decrypt(row.value, { tenantId });
|
|
171
170
|
const reencrypted = await cipher.encrypt(plaintext, { tenantId });
|
|
@@ -45,7 +45,8 @@ export const setWrite = defineWriteHandler({
|
|
|
45
45
|
// rejected), but an admin override write can still target scope=
|
|
46
46
|
// "system" for a tenant/user-scoped key (validateScope allows any
|
|
47
47
|
// requestedScope <= definedScope) — system-row has no subject.
|
|
48
|
-
|
|
48
|
+
const piiScope = keyDef.piiEncrypted && scope !== ConfigScopes.system ? scope : undefined;
|
|
49
|
+
if (keyDef.piiEncrypted && piiScope === undefined) {
|
|
49
50
|
return writeFailure(new UnprocessableError("invalid_scope", {
|
|
50
51
|
i18nKey: "config.errors.invalidScope",
|
|
51
52
|
details: { key: event.payload.key, definedScope: keyDef.scope, requestedScope: scope },
|
|
@@ -110,7 +111,7 @@ export const setWrite = defineWriteHandler({
|
|
|
110
111
|
const cipher = requireConfigEncryption(ctx, "config:write:set");
|
|
111
112
|
serialized = await cipher.encrypt(serialized, { tenantId });
|
|
112
113
|
}
|
|
113
|
-
else if (
|
|
114
|
+
else if (piiScope !== undefined) {
|
|
114
115
|
const kms = configuredPiiSubjectKms();
|
|
115
116
|
if (!kms) {
|
|
116
117
|
throw new InternalError({
|
|
@@ -119,8 +120,7 @@ export const setWrite = defineWriteHandler({
|
|
|
119
120
|
`configurePiiSubjectKms(adapter) at boot.`,
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
|
-
|
|
123
|
-
const subject = resolvePiiSubject(scope, tenantId, userId);
|
|
123
|
+
const subject = resolvePiiSubject(piiScope, tenantId, userId);
|
|
124
124
|
const kmsCtx = {
|
|
125
125
|
requestId: requestContext.get()?.requestId ?? "config:write:set",
|
|
126
126
|
tenantId,
|
package/dist/config/resolver.js
CHANGED
|
@@ -402,10 +402,10 @@ export function validateAppOverrides(registry, overrides) {
|
|
|
402
402
|
if (keyDef.computed) {
|
|
403
403
|
throw new Error(`App-Boot-Override for "${key}": this key has a computed resolver (plan-based / derived). App-overrides would silently bypass that logic — remove the override, or remove the computed resolver if a flat deploy-default is intended.`);
|
|
404
404
|
}
|
|
405
|
-
//
|
|
406
|
-
// `typeof value !== typeForKey(...)
|
|
407
|
-
//
|
|
408
|
-
//
|
|
405
|
+
// Narrow by keyDef.type inline because TypeScript cannot narrow through
|
|
406
|
+
// `typeof value !== typeForKey(...)`, whose return type is string rather
|
|
407
|
+
// than a discriminator. This avoids `value as string|number` casts below;
|
|
408
|
+
// value is correctly typed within each branch.
|
|
409
409
|
if (keyDef.type === "number") {
|
|
410
410
|
if (typeof value !== "number") {
|
|
411
411
|
throw new Error(`App-Boot-Override for "${key}": expected number, got ${typeof value}`);
|
package/dist/config/table.js
CHANGED
|
@@ -2,19 +2,19 @@ import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
// Config values are event-sourced. Each (key, scope) is its own aggregate
|
|
4
4
|
// stream — lifecycle events `configValue.created / .updated / .deleted`
|
|
5
|
-
// flow through createEventStoreExecutor, which writes the stream
|
|
6
|
-
// projection in one TX. Reads
|
|
5
|
+
// flow through createEventStoreExecutor, which writes the stream and this
|
|
6
|
+
// projection in one TX. Reads remain O(1) against the projection.
|
|
7
7
|
//
|
|
8
8
|
// System-scope rows use SYSTEM_TENANT_ID (not null) — buildBaseColumns
|
|
9
|
-
// (via buildEntityTable) forces tenant_id NOT NULL, so
|
|
10
|
-
// means system" convention is replaced with a fixed sentinel.
|
|
11
|
-
// index
|
|
12
|
-
// level —
|
|
9
|
+
// (via buildEntityTable) forces tenant_id NOT NULL, so the pre-ES "NULL
|
|
10
|
+
// means system" convention is replaced with a fixed sentinel. The unique
|
|
11
|
+
// index on (key, tenant_id, user_id) prevents duplicate writes at the DB
|
|
12
|
+
// level — declared via entity.indexes.
|
|
13
13
|
//
|
|
14
|
-
// Single
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
14
|
+
// Single source of truth: `configValueEntity`. The DB table is derived from
|
|
15
|
+
// the EntityDefinition through buildEntityTable, and the unique index is
|
|
16
|
+
// declared via entity.indexes. The plural re-export `configValuesTable`
|
|
17
|
+
// provides handlers (`reset.write.ts` etc.) with a typed Drizzle table ref.
|
|
18
18
|
export const configValueEntity = createEntity({
|
|
19
19
|
table: "read_config_values",
|
|
20
20
|
fields: {
|
|
@@ -138,7 +138,7 @@ export function resolveScopeIds(scope, tenantId, userId) {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
// The subject a piiEncrypted config value is encrypted under, for the scope
|
|
141
|
-
// actually written to
|
|
141
|
+
// actually written to. Pure — no I/O — so a bug
|
|
142
142
|
// here (e.g. picking the writer's identity instead of the row's target,
|
|
143
143
|
// see entity fields' explicit userOwned.ownerField for why that
|
|
144
144
|
// distinction matters) is caught by a fast unit test, not only the DB-
|
|
@@ -7,7 +7,7 @@ export declare const forgetSubjectSchema: z.ZodObject<{
|
|
|
7
7
|
userId: z.ZodUUID;
|
|
8
8
|
}, z.core.$strip>, z.ZodObject<{
|
|
9
9
|
kind: z.ZodLiteral<"tenant">;
|
|
10
|
-
tenantId: z.
|
|
10
|
+
tenantId: z.ZodUUID;
|
|
11
11
|
}, z.core.$strip>, z.ZodObject<{
|
|
12
12
|
kind: z.ZodLiteral<"record">;
|
|
13
13
|
entity: z.ZodString;
|
|
@@ -39,7 +39,7 @@ export declare const forgetSubjectWrite: import("@cosmicdrift/kumiko-types/defin
|
|
|
39
39
|
userId: z.ZodUUID;
|
|
40
40
|
}, z.core.$strip>, z.ZodObject<{
|
|
41
41
|
kind: z.ZodLiteral<"tenant">;
|
|
42
|
-
tenantId: z.
|
|
42
|
+
tenantId: z.ZodUUID;
|
|
43
43
|
}, z.core.$strip>, z.ZodObject<{
|
|
44
44
|
kind: z.ZodLiteral<"record">;
|
|
45
45
|
entity: z.ZodString;
|
|
@@ -54,7 +54,7 @@ function subjectAggregateId(raw) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
// The record subject names its own entity — resolve it against the registry
|
|
57
|
-
// instead of trusting the payload straight into resolveTableName/SQL
|
|
57
|
+
// instead of trusting the payload straight into resolveTableName/SQL.
|
|
58
58
|
function findRegisteredEntity(features, entityName) {
|
|
59
59
|
for (const feature of features.values()) {
|
|
60
60
|
const entity = feature.entities?.[entityName];
|
|
@@ -63,7 +63,7 @@ function findRegisteredEntity(features, entityName) {
|
|
|
63
63
|
}
|
|
64
64
|
return undefined;
|
|
65
65
|
}
|
|
66
|
-
// Tenant-scope guard
|
|
66
|
+
// Tenant-scope guard: DataProtectionOfficer is a tenant-scoped role,
|
|
67
67
|
// but the handler otherwise erases ANY subject cross-tenant on a raw
|
|
68
68
|
// (un-scoped) client — a Tenant-A DPO who learns a Tenant-B subject id
|
|
69
69
|
// (export, support ticket, log line) could destroy it. SystemAdmin
|
|
@@ -111,7 +111,7 @@ async function resolveTenantScopeDenial(db, features, user, raw) {
|
|
|
111
111
|
const ownedInTenant = await subjectRowExistsInTenant(db, features, raw.userId, user.tenantId);
|
|
112
112
|
return ownedInTenant ? undefined : memberDenied;
|
|
113
113
|
}
|
|
114
|
-
//
|
|
114
|
+
// blockDelete (legally mandated physical retention, e.g.
|
|
115
115
|
// ledger/invoice text) means this command must refuse, not silently
|
|
116
116
|
// anonymize or proceed. Refused when the host entity itself declares
|
|
117
117
|
// blockDelete OR the owning tenant's effective data-retention policy
|
|
@@ -162,8 +162,8 @@ function denialReasonOf(failure) {
|
|
|
162
162
|
}
|
|
163
163
|
return failure.error.code;
|
|
164
164
|
}
|
|
165
|
-
// Denied cross-tenant probes must still leave an audit trail
|
|
166
|
-
// Appended outside the handler tx
|
|
165
|
+
// Denied cross-tenant probes must still leave an audit trail.
|
|
166
|
+
// Appended outside the handler tx: the caller's
|
|
167
167
|
// `return tenantScopeDenial` rolls that tx back.
|
|
168
168
|
async function appendDenialAuditEvent(ctx, event, subjectKey, subjectKind, denialCode, denialAuditRunner) {
|
|
169
169
|
if (!denialAuditRunner) {
|
|
@@ -195,7 +195,7 @@ async function appendDenialAuditEvent(ctx, event, subjectKey, subjectKind, denia
|
|
|
195
195
|
registry: ctx.registry,
|
|
196
196
|
db: denialAuditRunner,
|
|
197
197
|
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw
|
|
198
|
-
// bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event
|
|
198
|
+
// bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event.
|
|
199
199
|
tenantId: event.user.tenantId,
|
|
200
200
|
userId: String(event.user.id),
|
|
201
201
|
callSiteLabel: "forget-subject denial audit",
|
|
@@ -235,10 +235,10 @@ async function sweepDerivedSubjectData(ctx, subject, subjectKey, crossTenantRunn
|
|
|
235
235
|
}
|
|
236
236
|
};
|
|
237
237
|
await runStep(async (crossTenantSubjectRunner) => {
|
|
238
|
-
// Blind-index sweep
|
|
238
|
+
// Blind-index sweep: nulls bidx columns now so the deterministic
|
|
239
239
|
// HMAC doesn't stay equality-matchable; raw because the ciphertext prefix addresses the subject across tenants.
|
|
240
240
|
await nullBlindIndexesForSubject(crossTenantSubjectRunner, ctx.registry.features, subjectKey);
|
|
241
|
-
// Derived search index still holds plaintext
|
|
241
|
+
// Derived search index still holds plaintext — purge next to the
|
|
242
242
|
// blind-index sweep. No adapter → no-op (apps without search).
|
|
243
243
|
if (ctx.searchAdapter) {
|
|
244
244
|
await purgeSearchDocumentsForSubject(crossTenantSubjectRunner, ctx.registry.features, ctx.searchAdapter, subjectKey, subject);
|
|
@@ -310,7 +310,8 @@ async function appendSubjectForgotten(ctx, event, aggregateId, payload, outsideR
|
|
|
310
310
|
await appendDomainEventCore({
|
|
311
311
|
registry: ctx.registry,
|
|
312
312
|
db: outsideRunner,
|
|
313
|
-
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's
|
|
313
|
+
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's
|
|
314
|
+
// scoping.
|
|
314
315
|
tenantId: event.user.tenantId,
|
|
315
316
|
userId: String(event.user.id),
|
|
316
317
|
callSiteLabel: "forget-subject audit",
|
|
@@ -331,7 +332,7 @@ async function appendSubjectForgotten(ctx, event, aggregateId, payload, outsideR
|
|
|
331
332
|
// The automated Art.-17 path (user-data-rights forget-cleanup) calls
|
|
332
333
|
// kms.eraseKey directly inside its per-user sub-tx; this command is the
|
|
333
334
|
// standalone trigger for cases outside that pipeline (authority requests,
|
|
334
|
-
// tenant-destroy
|
|
335
|
+
// tenant-destroy, operator recovery).
|
|
335
336
|
export const forgetSubjectWrite = defineWriteHandler({
|
|
336
337
|
name: "forget-subject",
|
|
337
338
|
schema: forgetSubjectSchema,
|
|
@@ -393,7 +394,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
393
394
|
// callable. Mirror of the automated Art.-17 path (userDeleteHook:
|
|
394
395
|
// status=Deleted; apiTokenDeleteHook: revoke):
|
|
395
396
|
// - user.updated as lifecycle event (updateUserLifecycle), so a
|
|
396
|
-
// read_users rebuild doesn't wipe the flip
|
|
397
|
+
// read_users rebuild doesn't wipe the flip
|
|
397
398
|
// - sessions don't need active revocation — session-callbacks
|
|
398
399
|
// re-validate user.status on every request (isPrincipalBlocked
|
|
399
400
|
// blocks Deleted).
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deterministic aggregate
|
|
3
|
-
*
|
|
4
|
-
* FieldKey)
|
|
2
|
+
* Deterministic aggregate ID for a fieldDefinition aggregate from the tuple
|
|
3
|
+
* (tenantId, entityName, fieldKey). Exactly one aggregate exists per
|
|
4
|
+
* (Tenant|System, Entity, FieldKey).
|
|
5
5
|
*
|
|
6
|
-
* **Scope
|
|
7
|
-
* - System
|
|
8
|
-
*
|
|
9
|
-
* - Tenant
|
|
6
|
+
* **Scope semantics:**
|
|
7
|
+
* - System scope: `tenantId = SYSTEM_TENANT_ID` → the fieldDefinition applies
|
|
8
|
+
* to all tenants (vendor-defined).
|
|
9
|
+
* - Tenant scope: `tenantId = <tenant-uuid>` → each tenant has its own
|
|
10
10
|
* fieldDefinition.
|
|
11
11
|
*
|
|
12
|
-
* **Conflict
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* beim Read.
|
|
12
|
+
* **Conflict rule** (enforced in the write handler, NOT via a DB constraint):
|
|
13
|
+
* Only ONE definition may exist per (entityName, fieldKey)—system or tenant,
|
|
14
|
+
* but not both. If system defines `customer.internalNumber`, a tenant cannot
|
|
15
|
+
* define its own `customer.internalNumber` (422 `fieldKey_conflict`). This
|
|
16
|
+
* prevents ambiguity when resolving the field during reads.
|
|
18
17
|
*/
|
|
19
18
|
export declare function fieldDefinitionAggregateId(tenantId: string, entityName: string, fieldKey: string): string;
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
|
-
// Fixed UUID
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// Fixed UUID namespace for deriving custom-field definition aggregate IDs.
|
|
3
|
+
// Generated once; changing it would re-key every existing fieldDefinition stream,
|
|
4
|
+
// breaking event replay and definition history. Drift is pinned in
|
|
5
|
+
// __tests__/drift.test.ts.
|
|
6
6
|
const FIELD_DEFINITION_NAMESPACE = "f1d3b2c7-4e5a-4b9c-8d1f-2a3b4c5d6e7f";
|
|
7
7
|
/**
|
|
8
|
-
* Deterministic aggregate
|
|
9
|
-
*
|
|
10
|
-
* FieldKey)
|
|
8
|
+
* Deterministic aggregate ID for a fieldDefinition aggregate from the tuple
|
|
9
|
+
* (tenantId, entityName, fieldKey). Exactly one aggregate exists per
|
|
10
|
+
* (Tenant|System, Entity, FieldKey).
|
|
11
11
|
*
|
|
12
|
-
* **Scope
|
|
13
|
-
* - System
|
|
14
|
-
*
|
|
15
|
-
* - Tenant
|
|
12
|
+
* **Scope semantics:**
|
|
13
|
+
* - System scope: `tenantId = SYSTEM_TENANT_ID` → the fieldDefinition applies
|
|
14
|
+
* to all tenants (vendor-defined).
|
|
15
|
+
* - Tenant scope: `tenantId = <tenant-uuid>` → each tenant has its own
|
|
16
16
|
* fieldDefinition.
|
|
17
17
|
*
|
|
18
|
-
* **Conflict
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* beim Read.
|
|
18
|
+
* **Conflict rule** (enforced in the write handler, NOT via a DB constraint):
|
|
19
|
+
* Only ONE definition may exist per (entityName, fieldKey)—system or tenant,
|
|
20
|
+
* but not both. If system defines `customer.internalNumber`, a tenant cannot
|
|
21
|
+
* define its own `customer.internalNumber` (422 `fieldKey_conflict`). This
|
|
22
|
+
* prevents ambiguity when resolving the field during reads.
|
|
24
23
|
*/
|
|
25
24
|
// @wrapper-known uuid-domain
|
|
26
25
|
export function fieldDefinitionAggregateId(tenantId, entityName, fieldKey) {
|
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
import { createBooleanField, createEntity, createNumberField, createTextField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
|
-
// fieldDefinition — Tenant-
|
|
2
|
+
// fieldDefinition — Tenant- or system-scoped custom-field definition.
|
|
3
3
|
//
|
|
4
|
-
// **Tenant
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// **Tenant scope:** The `tenantId` base column is set automatically by the
|
|
5
|
+
// framework. For system-scope definitions, `tenantId = SYSTEM_TENANT_ID`;
|
|
6
|
+
// for tenant-scope definitions, it is the current tenant. Both use the same
|
|
7
|
+
// table; the scope is determined by the tenantId value (no separate `scope`
|
|
8
|
+
// column).
|
|
8
9
|
//
|
|
9
|
-
// **Conflict
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
10
|
+
// **Conflict rule:** only one definition may exist per (entityName, fieldKey)
|
|
11
|
+
// — either system or tenant, not both. Resolution on read = `WHERE tenantId IN
|
|
12
|
+
// (SYSTEM_TENANT_ID, <current-tenant>)`. The conflict check is performed by
|
|
13
|
+
// the write handler, NOT enforced by a DB constraint (the DB has a natural
|
|
14
|
+
// UNIQUE constraint on (tenantId, entityName, fieldKey) through aggregate-ID
|
|
15
|
+
// construction).
|
|
15
16
|
//
|
|
16
|
-
// **Spec
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
17
|
+
// **Spec drift**: Spec Z.40-54 defines a separate `custom_field_value` table.
|
|
18
|
+
// Plan-Doc v2 replaced it with jsonb on the host entity (pure jsonb storage).
|
|
19
|
+
// This defines ONLY the definition entity; values land in
|
|
20
|
+
// `read_<entity>.customFields` jsonb via MSP.
|
|
20
21
|
//
|
|
21
|
-
// **
|
|
22
|
-
// - `defaultValue`, `options`, `fieldAccess`, `label` —
|
|
23
|
-
// `serializedField` jsonb
|
|
24
|
-
// r.field.X()-
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
// - `version` (optimistic
|
|
28
|
-
// stream
|
|
29
|
-
// - `createdAt/updatedAt/createdBy/updatedBy` — automatic
|
|
30
|
-
// columns
|
|
22
|
+
// **What is NOT stored as a base-field column here**:
|
|
23
|
+
// - `defaultValue`, `options`, `fieldAccess`, `label` — all packed into
|
|
24
|
+
// `serializedField` jsonb (builder reuse: dehydrated
|
|
25
|
+
// r.field.X()-output). Spec Z.18-38 lists them as separate columns, but
|
|
26
|
+
// builder reuse makes that redundant — the serialized builder contains all
|
|
27
|
+
// these aspects in a type-safe form.
|
|
28
|
+
// - `version` (optimistic lock) — redundant with event sourcing; we use the
|
|
29
|
+
// aggregate stream version.
|
|
30
|
+
// - `createdAt/updatedAt/createdBy/updatedBy` — automatic through base
|
|
31
|
+
// columns and events.
|
|
31
32
|
export const fieldDefinitionEntity = createEntity({
|
|
32
33
|
table: "read_custom_field_definitions",
|
|
33
34
|
description: "One custom-field definition: the host entity it extends, the field key, its type and required/searchable flags, a display order, and the serialized field builder that carries the type options, default value and labels. Rows owned by the system tenant apply to every tenant; all others belong to the tenant that defined them.",
|
|
@@ -40,55 +41,56 @@ export const fieldDefinitionEntity = createEntity({
|
|
|
40
41
|
// NB: `retention.strategy` below is the data-retention purge policy, a
|
|
41
42
|
// SEPARATE knob from this executor flag — it does not drive executor.delete.
|
|
42
43
|
softDelete: true,
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
44
|
+
// Retention policy — field definitions are tenant-schema metadata, not PII.
|
|
45
|
+
// Long retention supports audits (compliance can ask when a tenant defined,
|
|
46
|
+
// changed, or deleted the field).
|
|
46
47
|
//
|
|
47
|
-
// 10-
|
|
48
|
-
// tenantRetentionOverride
|
|
49
|
-
// (
|
|
48
|
+
// The 10-year keepFor is a conservative default; tenants can override it
|
|
49
|
+
// through tenantRetentionOverride for their own edge cases
|
|
50
|
+
// (e.g. shorter retention for test tenants).
|
|
50
51
|
retention: {
|
|
51
52
|
keepFor: "10y",
|
|
52
53
|
strategy: "softDelete",
|
|
53
54
|
},
|
|
54
55
|
fields: {
|
|
55
|
-
//
|
|
56
|
-
// "customer").
|
|
56
|
+
// The entity name for which this field is defined (e.g. "property",
|
|
57
|
+
// "customer"). The 64-character maximum follows Kumiko's entity-name
|
|
58
|
+
// convention.
|
|
57
59
|
entityName: createTextField({
|
|
58
60
|
required: true,
|
|
59
61
|
maxLength: 64,
|
|
60
62
|
personal: false,
|
|
61
63
|
reason: "technical_reference",
|
|
62
64
|
}),
|
|
63
|
-
// Field
|
|
64
|
-
//
|
|
65
|
+
// Field key (e.g. "internalNumber", "vipFlag") — kebab-case and camelCase
|
|
66
|
+
// are allowed; UI rendering uses label instead of fieldKey.
|
|
65
67
|
fieldKey: createTextField({
|
|
66
68
|
required: true,
|
|
67
69
|
maxLength: 64,
|
|
68
70
|
personal: false,
|
|
69
71
|
reason: "technical_reference",
|
|
70
72
|
}),
|
|
71
|
-
// Field
|
|
72
|
-
// write
|
|
73
|
+
// Field type from the SUPPORTED_FIELD_TYPES set. Validated with Zod in the
|
|
74
|
+
// write handler.
|
|
73
75
|
type: createTextField({
|
|
74
76
|
required: true,
|
|
75
77
|
maxLength: 16,
|
|
76
78
|
personal: false,
|
|
77
79
|
reason: "technical_reference",
|
|
78
80
|
}),
|
|
79
|
-
// Required
|
|
80
|
-
// (
|
|
81
|
+
// Required flag — checked against the value during entity writes
|
|
82
|
+
// (the same semantics as a base field).
|
|
81
83
|
required: createBooleanField({ required: true }),
|
|
82
|
-
// Searchable
|
|
83
|
-
//
|
|
84
|
+
// Searchable flag — when true, the field contributes to the search document
|
|
85
|
+
// through the search-payload extension.
|
|
84
86
|
searchable: createBooleanField({ required: true }),
|
|
85
|
-
// UI
|
|
87
|
+
// UI display order, allowing tenants to sort their fields in the UI.
|
|
86
88
|
displayOrder: createNumberField({ required: true, integer: true }),
|
|
87
|
-
// Builder
|
|
88
|
-
//
|
|
89
|
-
// defaultValue, fieldAccess, i18n
|
|
90
|
-
//
|
|
91
|
-
//
|
|
89
|
+
// Builder reuse: serialized r.field.X(opts) output stored as jsonb.
|
|
90
|
+
// It includes type options (enum values, money currency, embedded schema),
|
|
91
|
+
// defaultValue, fieldAccess, and i18n labels. During write validation, the
|
|
92
|
+
// handler dehydrates this back into an r.field.X() instance and uses its
|
|
93
|
+
// .schema for value validation.
|
|
92
94
|
serializedField: createTextField({
|
|
93
95
|
required: true,
|
|
94
96
|
maxLength: 65536,
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
-
// Domain
|
|
3
|
-
//
|
|
4
|
-
// auf demselben Stream wie die host-entity's eigene Events).
|
|
2
|
+
// Domain events for custom-field values. customField.set and .cleared live
|
|
3
|
+
// on the host aggregate stream, alongside the host entity's own events.
|
|
5
4
|
//
|
|
6
|
-
//
|
|
7
|
-
// aggregate
|
|
8
|
-
//
|
|
9
|
-
// aggregate-type
|
|
5
|
+
// The event's aggregate type is the host entity name (for example, "property"),
|
|
6
|
+
// and its aggregate ID is the host entity row ID (for example, property-uuid).
|
|
7
|
+
// This ensures customFields-MSPs consume only events for their wired entities,
|
|
8
|
+
// filtered by aggregate-type match in each consumer-side-MSP registration.
|
|
10
9
|
export const customFieldSetSchema = z.object({
|
|
11
10
|
fieldKey: z.string().min(1).max(64),
|
|
12
|
-
// Every set carries its value (custom fields hold no PII
|
|
11
|
+
// Every set carries its value (custom fields hold no PII) — replay
|
|
13
12
|
// reproduces the projection fully. Stays optional at the type layer only
|
|
14
13
|
// because z.unknown() is inherently optional; the apply side treats
|
|
15
14
|
// `value === undefined` as an anomaly and warns.
|
|
@@ -15,24 +15,24 @@ declare const defaultCustomFieldsFeature: import("@cosmicdrift/kumiko-types/feat
|
|
|
15
15
|
};
|
|
16
16
|
};
|
|
17
17
|
export type CustomFieldsFeatureOptions = {
|
|
18
|
-
/**
|
|
18
|
+
/** Quota for define-tenant-field. */
|
|
19
19
|
readonly fieldDefinitionLimitPerTenant?: number;
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
/** Roles for set-/clear-custom-field, used by the save paths in
|
|
21
|
+
* CustomFieldsFormSection. Default ["TenantAdmin","TenantMember"];
|
|
22
|
+
* apps with their own role vocabulary (for example ["Admin","Editor"])
|
|
23
|
+
* MUST set this, otherwise value saving is access_denied for every app user
|
|
24
|
+
* (role-naming drift). */
|
|
25
25
|
readonly valueWriteRoles?: readonly string[];
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
26
|
+
/** Roles for custom-fields:query:field-definition:list, used by the loading
|
|
27
|
+
* path in CustomFieldsFormSection. Default ["TenantAdmin"]. If
|
|
28
|
+
* valueWriteRoles is set but this is not, the value roles are inherited here
|
|
29
|
+
* (unioned with the default so admins retain list access); otherwise the
|
|
30
|
+
* FormSection cannot load for value writers (access_denied) while the save
|
|
31
|
+
* path remains open (an asymmetric break). */
|
|
32
32
|
readonly fieldDefinitionListRoles?: readonly string[];
|
|
33
33
|
/** Access roles for the definition-CRUD triad (`define-tenant-field`,
|
|
34
|
-
* `update-tenant-field`, `delete-tenant-field`) — hard-wired to ["TenantAdmin"]
|
|
35
|
-
*
|
|
34
|
+
* `update-tenant-field`, `delete-tenant-field`) — hard-wired to ["TenantAdmin"].
|
|
35
|
+
* Apps with their own role vocabulary (e.g. ["Admin","Editor"])
|
|
36
36
|
* MUST set this, else field-definition management is access_denied for every
|
|
37
37
|
* app-user without a "TenantAdmin" role. Only covers the tenant-scope triad —
|
|
38
38
|
* define-/delete-system-field stay hard-wired to ["SystemAdmin"], since
|