@cosmicdrift/kumiko-samples 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/README.md +1 -1
- package/package.json +2 -2
- package/packages/bundled-features/package.json +2 -2
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +0 -2
- package/packages/bundled-features/src/audit/screens.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
- package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
- package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
- package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
- package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
- package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
- package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
- package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
- package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
- package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
- package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
- package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
- package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
- package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
- package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
- package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
- package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
- package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
- package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
- package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
- package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
- package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
- package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
- package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
- package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
- package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
- package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
- package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
- package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
- package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
- package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
- package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
- package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/web/i18n.ts +3 -3
- package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
- package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +6 -6
- package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
- package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
- package/packages/bundled-features/src/billing-foundation/events.ts +22 -21
- package/packages/bundled-features/src/billing-foundation/feature.ts +42 -43
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +18 -17
- package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
- package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +20 -20
- package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
- package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
- package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
- package/packages/bundled-features/src/billing-foundation/types.ts +64 -65
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +4 -4
- package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
- package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
- package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +64 -67
- package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
- package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
- package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
- package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
- package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +1 -1
- package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
- package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
- package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
- package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
- package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
- package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
- package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
- package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
- package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
- package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
- package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
- package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
- package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
- package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
- package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
- package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
- package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
- package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
- package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
- package/packages/bundled-features/src/config/resolver.ts +4 -4
- package/packages/bundled-features/src/config/table.ts +10 -10
- package/packages/bundled-features/src/config/write-helpers.ts +1 -1
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +13 -12
- package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
- package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
- package/packages/bundled-features/src/custom-fields/events.ts +7 -8
- package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
- package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
- package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
- package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
- package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
- package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
- package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
- package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
- package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
- package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
- package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
- package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
- package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
- package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
- package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
- package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
- package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
- package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
- package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
- package/packages/bundled-features/src/data-retention/feature.ts +11 -18
- package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
- package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
- package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
- package/packages/bundled-features/src/data-retention/presets.ts +18 -23
- package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
- package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
- package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
- package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
- package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
- package/packages/bundled-features/src/delivery/feature.ts +3 -3
- package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
- package/packages/bundled-features/src/delivery/tables.ts +9 -8
- package/packages/bundled-features/src/delivery/unsubscribe.ts +4 -4
- package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
- package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
- package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
- package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
- package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
- package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
- package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
- package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
- package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
- package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
- package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
- package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
- package/packages/bundled-features/src/files/feature.ts +6 -6
- package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
- package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
- package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
- package/packages/bundled-features/src/folders/feature.ts +1 -1
- package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
- package/packages/bundled-features/src/folders/web/tree.ts +5 -5
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
- package/packages/bundled-features/src/form-draft/entity.ts +3 -3
- package/packages/bundled-features/src/form-draft/feature.ts +4 -5
- package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
- package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
- package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
- package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
- package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
- package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
- package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
- package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
- package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
- package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
- package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +11 -11
- package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
- package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
- package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
- package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +66 -67
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +69 -68
- package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
- package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
- package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
- package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
- package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
- package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
- package/packages/bundled-features/src/jobs/events.ts +1 -1
- package/packages/bundled-features/src/jobs/feature.ts +6 -7
- package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
- package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
- package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
- package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +14 -15
- package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
- package/packages/bundled-features/src/jobs/screens.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
- package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
- package/packages/bundled-features/src/ledger/entity.ts +5 -5
- package/packages/bundled-features/src/ledger/feature.ts +3 -3
- package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
- package/packages/bundled-features/src/ledger/recurring.ts +12 -12
- package/packages/bundled-features/src/ledger/schemas.ts +1 -1
- package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
- package/packages/bundled-features/src/ledger/web/index.ts +7 -7
- package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
- package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
- package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
- package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
- package/packages/bundled-features/src/mail-foundation/feature.ts +26 -27
- package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
- package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
- package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
- package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
- package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
- package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
- package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
- package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
- package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
- package/packages/bundled-features/src/managed-pages/table.ts +16 -15
- package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
- package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
- package/packages/bundled-features/src/notes-history/entity.ts +4 -4
- package/packages/bundled-features/src/notes-history/feature.ts +2 -2
- package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
- package/packages/bundled-features/src/page-render/layout.ts +9 -9
- package/packages/bundled-features/src/page-render/markdown.ts +11 -11
- package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
- package/packages/bundled-features/src/personal-access-tokens/feature.ts +5 -5
- package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
- package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
- package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
- package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
- package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
- package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
- package/packages/bundled-features/src/secrets/feature.ts +9 -9
- package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
- package/packages/bundled-features/src/seo/feature.ts +3 -3
- package/packages/bundled-features/src/sessions/constants.ts +1 -1
- package/packages/bundled-features/src/sessions/feature.ts +9 -9
- package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
- package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
- package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
- package/packages/bundled-features/src/sessions/screens.ts +2 -2
- package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
- package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
- package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
- package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +1 -1
- package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
- package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
- package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
- package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
- package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
- package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
- package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
- package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
- package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
- package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
- package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
- package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
- package/packages/bundled-features/src/subscription-stripe/feature.ts +44 -43
- package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
- package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
- package/packages/bundled-features/src/subscription-stripe/runtime.ts +2 -2
- package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
- package/packages/bundled-features/src/tags/feature.ts +3 -3
- package/packages/bundled-features/src/tags/screens.ts +1 -1
- package/packages/bundled-features/src/template-resolver/api.ts +10 -10
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +5 -5
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +1 -1
- package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
- package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
- package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
- package/packages/bundled-features/src/template-resolver/seeding.ts +4 -4
- package/packages/bundled-features/src/template-resolver/table.ts +13 -14
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
- package/packages/bundled-features/src/tenant/feature.ts +7 -7
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
- package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
- package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
- package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
- package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
- package/packages/bundled-features/src/tenant/screens.ts +1 -1
- package/packages/bundled-features/src/tenant/seeding.ts +19 -18
- package/packages/bundled-features/src/tenant/testing.ts +5 -6
- package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
- package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
- package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
- package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
- package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
- package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
- package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +2 -2
- package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
- package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
- package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
- package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
- package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
- package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
- package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
- package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
- package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
- package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +8 -8
- package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
- package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
- package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
- package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
- package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
- package/packages/bundled-features/src/user/schema/user.ts +45 -44
- package/packages/bundled-features/src/user/seeding.ts +40 -40
- package/packages/bundled-features/src/user/testing.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
- package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
- package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
- package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
- package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
- package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
- package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
- package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
- package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
- package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
- package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
- package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
- package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
- package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
- package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
- package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
- package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +166 -276
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +85 -107
- package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
- package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
- package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
- package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
- package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
- package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
- package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
- package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
- package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
- package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
- package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
- package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
- package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
- package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
- package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
- package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
- package/packages/bundled-features/src/user-profile/index.ts +3 -3
- package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
- package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
- package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
- package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
- package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
- package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
- package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
- package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
- package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
- package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
- package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
- package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
|
@@ -3,19 +3,19 @@ import { createEntity, createTextField } from "@cosmicdrift/kumiko-framework/eng
|
|
|
3
3
|
|
|
4
4
|
// Config values are event-sourced. Each (key, scope) is its own aggregate
|
|
5
5
|
// stream — lifecycle events `configValue.created / .updated / .deleted`
|
|
6
|
-
// flow through createEventStoreExecutor, which writes the stream
|
|
7
|
-
// projection in one TX. Reads
|
|
6
|
+
// flow through createEventStoreExecutor, which writes the stream and this
|
|
7
|
+
// projection in one TX. Reads remain O(1) against the projection.
|
|
8
8
|
//
|
|
9
9
|
// System-scope rows use SYSTEM_TENANT_ID (not null) — buildBaseColumns
|
|
10
|
-
// (via buildEntityTable) forces tenant_id NOT NULL, so
|
|
11
|
-
// means system" convention is replaced with a fixed sentinel.
|
|
12
|
-
// index
|
|
13
|
-
// level —
|
|
10
|
+
// (via buildEntityTable) forces tenant_id NOT NULL, so the pre-ES "NULL
|
|
11
|
+
// means system" convention is replaced with a fixed sentinel. The unique
|
|
12
|
+
// index on (key, tenant_id, user_id) prevents duplicate writes at the DB
|
|
13
|
+
// level — declared via entity.indexes.
|
|
14
14
|
//
|
|
15
|
-
// Single
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
15
|
+
// Single source of truth: `configValueEntity`. The DB table is derived from
|
|
16
|
+
// the EntityDefinition through buildEntityTable, and the unique index is
|
|
17
|
+
// declared via entity.indexes. The plural re-export `configValuesTable`
|
|
18
|
+
// provides handlers (`reset.write.ts` etc.) with a typed Drizzle table ref.
|
|
19
19
|
export const configValueEntity = createEntity({
|
|
20
20
|
table: "read_config_values",
|
|
21
21
|
fields: {
|
|
@@ -226,7 +226,7 @@ export function resolveScopeIds(
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// The subject a piiEncrypted config value is encrypted under, for the scope
|
|
229
|
-
// actually written to
|
|
229
|
+
// actually written to. Pure — no I/O — so a bug
|
|
230
230
|
// here (e.g. picking the writer's identity instead of the row's target,
|
|
231
231
|
// see entity fields' explicit userOwned.ownerField for why that
|
|
232
232
|
// distinction matters) is caught by a fast unit test, not only the DB-
|
|
@@ -112,7 +112,7 @@ function subjectAggregateId(raw: SubjectIdInput): string {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// The record subject names its own entity — resolve it against the registry
|
|
115
|
-
// instead of trusting the payload straight into resolveTableName/SQL
|
|
115
|
+
// instead of trusting the payload straight into resolveTableName/SQL.
|
|
116
116
|
function findRegisteredEntity(
|
|
117
117
|
features: ReadonlyMap<string, FeatureDefinition>,
|
|
118
118
|
entityName: string,
|
|
@@ -124,7 +124,7 @@ function findRegisteredEntity(
|
|
|
124
124
|
return undefined;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
// Tenant-scope guard
|
|
127
|
+
// Tenant-scope guard: DataProtectionOfficer is a tenant-scoped role,
|
|
128
128
|
// but the handler otherwise erases ANY subject cross-tenant on a raw
|
|
129
129
|
// (un-scoped) client — a Tenant-A DPO who learns a Tenant-B subject id
|
|
130
130
|
// (export, support ticket, log line) could destroy it. SystemAdmin
|
|
@@ -182,7 +182,7 @@ async function resolveTenantScopeDenial(
|
|
|
182
182
|
return ownedInTenant ? undefined : memberDenied;
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
//
|
|
185
|
+
// blockDelete (legally mandated physical retention, e.g.
|
|
186
186
|
// ledger/invoice text) means this command must refuse, not silently
|
|
187
187
|
// anonymize or proceed. Refused when the host entity itself declares
|
|
188
188
|
// blockDelete OR the owning tenant's effective data-retention policy
|
|
@@ -213,7 +213,7 @@ async function resolveRetentionDenial(
|
|
|
213
213
|
const effective = await resolveRetentionPolicyForTenant({
|
|
214
214
|
db: runner,
|
|
215
215
|
registry: ctx.registry,
|
|
216
|
-
tenantId: owningTenantId
|
|
216
|
+
tenantId: owningTenantId,
|
|
217
217
|
entityName: raw.entity,
|
|
218
218
|
});
|
|
219
219
|
return effective.policy?.strategy === "blockDelete" ? deny() : undefined;
|
|
@@ -241,8 +241,8 @@ function denialReasonOf(failure: WriteFailure): string {
|
|
|
241
241
|
return failure.error.code;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
// Denied cross-tenant probes must still leave an audit trail
|
|
245
|
-
// Appended outside the handler tx
|
|
244
|
+
// Denied cross-tenant probes must still leave an audit trail.
|
|
245
|
+
// Appended outside the handler tx: the caller's
|
|
246
246
|
// `return tenantScopeDenial` rolls that tx back.
|
|
247
247
|
async function appendDenialAuditEvent(
|
|
248
248
|
ctx: HandlerContext,
|
|
@@ -285,7 +285,7 @@ async function appendDenialAuditEvent(
|
|
|
285
285
|
registry: ctx.registry,
|
|
286
286
|
db: denialAuditRunner,
|
|
287
287
|
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw
|
|
288
|
-
// bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event
|
|
288
|
+
// bypasses TenantDb's scoping, so this is the only guard against a cross-tenant denial event.
|
|
289
289
|
tenantId: event.user.tenantId,
|
|
290
290
|
userId: String(event.user.id),
|
|
291
291
|
callSiteLabel: "forget-subject denial audit",
|
|
@@ -339,11 +339,11 @@ async function sweepDerivedSubjectData(
|
|
|
339
339
|
};
|
|
340
340
|
|
|
341
341
|
await runStep(async (crossTenantSubjectRunner) => {
|
|
342
|
-
// Blind-index sweep
|
|
342
|
+
// Blind-index sweep: nulls bidx columns now so the deterministic
|
|
343
343
|
// HMAC doesn't stay equality-matchable; raw because the ciphertext prefix addresses the subject across tenants.
|
|
344
344
|
await nullBlindIndexesForSubject(crossTenantSubjectRunner, ctx.registry.features, subjectKey);
|
|
345
345
|
|
|
346
|
-
// Derived search index still holds plaintext
|
|
346
|
+
// Derived search index still holds plaintext — purge next to the
|
|
347
347
|
// blind-index sweep. No adapter → no-op (apps without search).
|
|
348
348
|
if (ctx.searchAdapter) {
|
|
349
349
|
await purgeSearchDocumentsForSubject(
|
|
@@ -442,7 +442,8 @@ async function appendSubjectForgotten(
|
|
|
442
442
|
{
|
|
443
443
|
registry: ctx.registry,
|
|
444
444
|
db: outsideRunner,
|
|
445
|
-
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's
|
|
445
|
+
// MUST be event.user.tenantId, never SYSTEM_TENANT_ID — unsafeRaw bypasses TenantDb's
|
|
446
|
+
// scoping.
|
|
446
447
|
tenantId: event.user.tenantId,
|
|
447
448
|
userId: String(event.user.id),
|
|
448
449
|
callSiteLabel: "forget-subject audit",
|
|
@@ -466,7 +467,7 @@ async function appendSubjectForgotten(
|
|
|
466
467
|
// The automated Art.-17 path (user-data-rights forget-cleanup) calls
|
|
467
468
|
// kms.eraseKey directly inside its per-user sub-tx; this command is the
|
|
468
469
|
// standalone trigger for cases outside that pipeline (authority requests,
|
|
469
|
-
// tenant-destroy
|
|
470
|
+
// tenant-destroy, operator recovery).
|
|
470
471
|
export const forgetSubjectWrite = defineWriteHandler({
|
|
471
472
|
name: "forget-subject",
|
|
472
473
|
schema: forgetSubjectSchema,
|
|
@@ -558,7 +559,7 @@ export const forgetSubjectWrite = defineWriteHandler({
|
|
|
558
559
|
// callable. Mirror of the automated Art.-17 path (userDeleteHook:
|
|
559
560
|
// status=Deleted; apiTokenDeleteHook: revoke):
|
|
560
561
|
// - user.updated as lifecycle event (updateUserLifecycle), so a
|
|
561
|
-
// read_users rebuild doesn't wipe the flip
|
|
562
|
+
// read_users rebuild doesn't wipe the flip
|
|
562
563
|
// - sessions don't need active revocation — session-callbacks
|
|
563
564
|
// re-validate user.status on every request (isPrincipalBlocked
|
|
564
565
|
// blocks Deleted).
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
2
|
|
|
3
|
-
// Fixed UUID
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// Fixed UUID namespace for deriving custom-field definition aggregate IDs.
|
|
4
|
+
// Generated once; changing it would re-key every existing fieldDefinition stream,
|
|
5
|
+
// breaking event replay and definition history. Drift is pinned in
|
|
6
|
+
// __tests__/drift.test.ts.
|
|
7
7
|
const FIELD_DEFINITION_NAMESPACE = "f1d3b2c7-4e5a-4b9c-8d1f-2a3b4c5d6e7f";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Deterministic aggregate
|
|
11
|
-
*
|
|
12
|
-
* FieldKey)
|
|
10
|
+
* Deterministic aggregate ID for a fieldDefinition aggregate from the tuple
|
|
11
|
+
* (tenantId, entityName, fieldKey). Exactly one aggregate exists per
|
|
12
|
+
* (Tenant|System, Entity, FieldKey).
|
|
13
13
|
*
|
|
14
|
-
* **Scope
|
|
15
|
-
* - System
|
|
16
|
-
*
|
|
17
|
-
* - Tenant
|
|
14
|
+
* **Scope semantics:**
|
|
15
|
+
* - System scope: `tenantId = SYSTEM_TENANT_ID` → the fieldDefinition applies
|
|
16
|
+
* to all tenants (vendor-defined).
|
|
17
|
+
* - Tenant scope: `tenantId = <tenant-uuid>` → each tenant has its own
|
|
18
18
|
* fieldDefinition.
|
|
19
19
|
*
|
|
20
|
-
* **Conflict
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* beim Read.
|
|
20
|
+
* **Conflict rule** (enforced in the write handler, NOT via a DB constraint):
|
|
21
|
+
* Only ONE definition may exist per (entityName, fieldKey)—system or tenant,
|
|
22
|
+
* but not both. If system defines `customer.internalNumber`, a tenant cannot
|
|
23
|
+
* define its own `customer.internalNumber` (422 `fieldKey_conflict`). This
|
|
24
|
+
* prevents ambiguity when resolving the field during reads.
|
|
26
25
|
*/
|
|
27
26
|
// @wrapper-known uuid-domain
|
|
28
27
|
export function fieldDefinitionAggregateId(
|
|
@@ -5,35 +5,36 @@ import {
|
|
|
5
5
|
createTextField,
|
|
6
6
|
} from "@cosmicdrift/kumiko-framework/engine";
|
|
7
7
|
|
|
8
|
-
// fieldDefinition — Tenant-
|
|
8
|
+
// fieldDefinition — Tenant- or system-scoped custom-field definition.
|
|
9
9
|
//
|
|
10
|
-
// **Tenant
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
10
|
+
// **Tenant scope:** The `tenantId` base column is set automatically by the
|
|
11
|
+
// framework. For system-scope definitions, `tenantId = SYSTEM_TENANT_ID`;
|
|
12
|
+
// for tenant-scope definitions, it is the current tenant. Both use the same
|
|
13
|
+
// table; the scope is determined by the tenantId value (no separate `scope`
|
|
14
|
+
// column).
|
|
14
15
|
//
|
|
15
|
-
// **Conflict
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
16
|
+
// **Conflict rule:** only one definition may exist per (entityName, fieldKey)
|
|
17
|
+
// — either system or tenant, not both. Resolution on read = `WHERE tenantId IN
|
|
18
|
+
// (SYSTEM_TENANT_ID, <current-tenant>)`. The conflict check is performed by
|
|
19
|
+
// the write handler, NOT enforced by a DB constraint (the DB has a natural
|
|
20
|
+
// UNIQUE constraint on (tenantId, entityName, fieldKey) through aggregate-ID
|
|
21
|
+
// construction).
|
|
21
22
|
//
|
|
22
|
-
// **Spec
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
23
|
+
// **Spec drift**: Spec Z.40-54 defines a separate `custom_field_value` table.
|
|
24
|
+
// Plan-Doc v2 replaced it with jsonb on the host entity (pure jsonb storage).
|
|
25
|
+
// This defines ONLY the definition entity; values land in
|
|
26
|
+
// `read_<entity>.customFields` jsonb via MSP.
|
|
26
27
|
//
|
|
27
|
-
// **
|
|
28
|
-
// - `defaultValue`, `options`, `fieldAccess`, `label` —
|
|
29
|
-
// `serializedField` jsonb
|
|
30
|
-
// r.field.X()-
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// - `version` (optimistic
|
|
34
|
-
// stream
|
|
35
|
-
// - `createdAt/updatedAt/createdBy/updatedBy` — automatic
|
|
36
|
-
// columns
|
|
28
|
+
// **What is NOT stored as a base-field column here**:
|
|
29
|
+
// - `defaultValue`, `options`, `fieldAccess`, `label` — all packed into
|
|
30
|
+
// `serializedField` jsonb (builder reuse: dehydrated
|
|
31
|
+
// r.field.X()-output). Spec Z.18-38 lists them as separate columns, but
|
|
32
|
+
// builder reuse makes that redundant — the serialized builder contains all
|
|
33
|
+
// these aspects in a type-safe form.
|
|
34
|
+
// - `version` (optimistic lock) — redundant with event sourcing; we use the
|
|
35
|
+
// aggregate stream version.
|
|
36
|
+
// - `createdAt/updatedAt/createdBy/updatedBy` — automatic through base
|
|
37
|
+
// columns and events.
|
|
37
38
|
export const fieldDefinitionEntity = createEntity({
|
|
38
39
|
table: "read_custom_field_definitions",
|
|
39
40
|
description:
|
|
@@ -47,20 +48,21 @@ export const fieldDefinitionEntity = createEntity({
|
|
|
47
48
|
// NB: `retention.strategy` below is the data-retention purge policy, a
|
|
48
49
|
// SEPARATE knob from this executor flag — it does not drive executor.delete.
|
|
49
50
|
softDelete: true,
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
51
|
+
// Retention policy — field definitions are tenant-schema metadata, not PII.
|
|
52
|
+
// Long retention supports audits (compliance can ask when a tenant defined,
|
|
53
|
+
// changed, or deleted the field).
|
|
53
54
|
//
|
|
54
|
-
// 10-
|
|
55
|
-
// tenantRetentionOverride
|
|
56
|
-
// (
|
|
55
|
+
// The 10-year keepFor is a conservative default; tenants can override it
|
|
56
|
+
// through tenantRetentionOverride for their own edge cases
|
|
57
|
+
// (e.g. shorter retention for test tenants).
|
|
57
58
|
retention: {
|
|
58
59
|
keepFor: "10y",
|
|
59
60
|
strategy: "softDelete",
|
|
60
61
|
},
|
|
61
62
|
fields: {
|
|
62
|
-
//
|
|
63
|
-
// "customer").
|
|
63
|
+
// The entity name for which this field is defined (e.g. "property",
|
|
64
|
+
// "customer"). The 64-character maximum follows Kumiko's entity-name
|
|
65
|
+
// convention.
|
|
64
66
|
entityName: createTextField({
|
|
65
67
|
required: true,
|
|
66
68
|
maxLength: 64,
|
|
@@ -68,8 +70,8 @@ export const fieldDefinitionEntity = createEntity({
|
|
|
68
70
|
reason: "technical_reference",
|
|
69
71
|
}),
|
|
70
72
|
|
|
71
|
-
// Field
|
|
72
|
-
//
|
|
73
|
+
// Field key (e.g. "internalNumber", "vipFlag") — kebab-case and camelCase
|
|
74
|
+
// are allowed; UI rendering uses label instead of fieldKey.
|
|
73
75
|
fieldKey: createTextField({
|
|
74
76
|
required: true,
|
|
75
77
|
maxLength: 64,
|
|
@@ -77,8 +79,8 @@ export const fieldDefinitionEntity = createEntity({
|
|
|
77
79
|
reason: "technical_reference",
|
|
78
80
|
}),
|
|
79
81
|
|
|
80
|
-
// Field
|
|
81
|
-
// write
|
|
82
|
+
// Field type from the SUPPORTED_FIELD_TYPES set. Validated with Zod in the
|
|
83
|
+
// write handler.
|
|
82
84
|
type: createTextField({
|
|
83
85
|
required: true,
|
|
84
86
|
maxLength: 16,
|
|
@@ -86,22 +88,22 @@ export const fieldDefinitionEntity = createEntity({
|
|
|
86
88
|
reason: "technical_reference",
|
|
87
89
|
}),
|
|
88
90
|
|
|
89
|
-
// Required
|
|
90
|
-
// (
|
|
91
|
+
// Required flag — checked against the value during entity writes
|
|
92
|
+
// (the same semantics as a base field).
|
|
91
93
|
required: createBooleanField({ required: true }),
|
|
92
94
|
|
|
93
|
-
// Searchable
|
|
94
|
-
//
|
|
95
|
+
// Searchable flag — when true, the field contributes to the search document
|
|
96
|
+
// through the search-payload extension.
|
|
95
97
|
searchable: createBooleanField({ required: true }),
|
|
96
98
|
|
|
97
|
-
// UI
|
|
99
|
+
// UI display order, allowing tenants to sort their fields in the UI.
|
|
98
100
|
displayOrder: createNumberField({ required: true, integer: true }),
|
|
99
101
|
|
|
100
|
-
// Builder
|
|
101
|
-
//
|
|
102
|
-
// defaultValue, fieldAccess, i18n
|
|
103
|
-
//
|
|
104
|
-
//
|
|
102
|
+
// Builder reuse: serialized r.field.X(opts) output stored as jsonb.
|
|
103
|
+
// It includes type options (enum values, money currency, embedded schema),
|
|
104
|
+
// defaultValue, fieldAccess, and i18n labels. During write validation, the
|
|
105
|
+
// handler dehydrates this back into an r.field.X() instance and uses its
|
|
106
|
+
// .schema for value validation.
|
|
105
107
|
serializedField: createTextField({
|
|
106
108
|
required: true,
|
|
107
109
|
maxLength: 65536,
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
|
|
3
|
-
// Domain
|
|
4
|
-
//
|
|
5
|
-
// auf demselben Stream wie die host-entity's eigene Events).
|
|
3
|
+
// Domain events for custom-field values. customField.set and .cleared live
|
|
4
|
+
// on the host aggregate stream, alongside the host entity's own events.
|
|
6
5
|
//
|
|
7
|
-
//
|
|
8
|
-
// aggregate
|
|
9
|
-
//
|
|
10
|
-
// aggregate-type
|
|
6
|
+
// The event's aggregate type is the host entity name (for example, "property"),
|
|
7
|
+
// and its aggregate ID is the host entity row ID (for example, property-uuid).
|
|
8
|
+
// This ensures customFields-MSPs consume only events for their wired entities,
|
|
9
|
+
// filtered by aggregate-type match in each consumer-side-MSP registration.
|
|
11
10
|
|
|
12
11
|
export const customFieldSetSchema = z.object({
|
|
13
12
|
fieldKey: z.string().min(1).max(64),
|
|
14
|
-
// Every set carries its value (custom fields hold no PII
|
|
13
|
+
// Every set carries its value (custom fields hold no PII) — replay
|
|
15
14
|
// reproduces the projection fully. Stays optional at the type layer only
|
|
16
15
|
// because z.unknown() is inherently optional; the apply side treats
|
|
17
16
|
// `value === undefined` as an anomaly and warns.
|
|
@@ -1,50 +1,49 @@
|
|
|
1
|
-
// custom-fields —
|
|
2
|
-
//
|
|
1
|
+
// custom-fields — tenant- and system-scoped custom-field definitions plus
|
|
2
|
+
// generic custom-field value write-handlers (host-stream events).
|
|
3
3
|
//
|
|
4
|
-
// **Scope: supplemental business data, NO PII
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
4
|
+
// **Scope: supplemental business data, NO PII.** Custom fields are for
|
|
5
|
+
// tenant-specific additional data (reference numbers, flags, categories),
|
|
6
|
+
// not personally identifiable information. The former `sensitive` flag was
|
|
7
|
+
// removed; the schema rejects it and `parseSerializedField` throws for legacy
|
|
8
|
+
// definitions. Values are stored entirely in the event log (rebuild-safe).
|
|
9
9
|
// PII belongs in schema-entity fields with a `personal` annotation
|
|
10
10
|
// (crypto-shredding, event ciphertext, forget pipeline).
|
|
11
11
|
//
|
|
12
|
-
// **
|
|
13
|
-
// 1. r.entity({ name: "field-definition" }) —
|
|
14
|
-
// 2. define-tenant-field / define-system-field — RBAC write-handlers
|
|
15
|
-
//
|
|
12
|
+
// **This feature provides:**
|
|
13
|
+
// 1. r.entity({ name: "field-definition" }) — event-sourced definition storage.
|
|
14
|
+
// 2. define-tenant-field / define-system-field — RBAC write-handlers for
|
|
15
|
+
// definition CRUD.
|
|
16
16
|
// 3. delete-tenant-field / delete-system-field — RBAC write-handlers.
|
|
17
|
-
// 3b. update-tenant-field —
|
|
18
|
-
// 4. set-custom-field / clear-custom-field — write-handlers
|
|
19
|
-
//
|
|
20
|
-
// 5. r.defineEvent
|
|
21
|
-
// 6. r.extendsRegistrar("customFields") —
|
|
22
|
-
//
|
|
23
|
-
// 7. defineEntityListHandler —
|
|
24
|
-
//
|
|
17
|
+
// 3b. update-tenant-field — full-replacement edit; type is immutable.
|
|
18
|
+
// 4. set-custom-field / clear-custom-field — write-handlers for VALUES.
|
|
19
|
+
// They emit customField.set/.cleared events on the host aggregate stream.
|
|
20
|
+
// 5. r.defineEvent for customField.set/.cleared + fieldDefinition.deleted.
|
|
21
|
+
// 6. r.extendsRegistrar("customFields") — registers the extension name so
|
|
22
|
+
// consumers can opt in via r.useExtension("customFields", "<entity>").
|
|
23
|
+
// 7. defineEntityListHandler — reads fieldDefinitions (currently tenant-
|
|
24
|
+
// scoped; a system+tenant UNION requires a custom query).
|
|
25
25
|
//
|
|
26
|
-
// **Consumer-side
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// + postQuery
|
|
26
|
+
// **Consumer-side wiring** (see wire-for-entity.ts):
|
|
27
|
+
// The consumer calls `wireCustomFieldsFor(r, entityName, entityTable)`,
|
|
28
|
+
// which registers per host entity: useExtension + MSP (JSONB projection)
|
|
29
|
+
// + postQuery hook (flattening) + search-payload extension.
|
|
30
30
|
//
|
|
31
|
-
// **Host-
|
|
32
|
-
//
|
|
33
|
-
// `customFieldsField()` (
|
|
31
|
+
// **Host-entity requirement**:
|
|
32
|
+
// The consumer MUST declare a `customFields` column as
|
|
33
|
+
// `customFieldsField()` (JSONB) in the entity definition.
|
|
34
34
|
//
|
|
35
|
-
// **Exports
|
|
35
|
+
// **Exports pattern**:
|
|
36
36
|
// `createCustomFieldsFeature().exports.{setEvent,clearedEvent,fieldDefinitionDeletedEvent}`
|
|
37
|
-
//
|
|
38
|
-
// `<event>.name`
|
|
39
|
-
// hand-
|
|
40
|
-
//
|
|
37
|
+
// provides typed EventDef handles. Handlers and wire-for-entity use
|
|
38
|
+
// `<event>.name` as a compile-time literal-typed qualified string instead of
|
|
39
|
+
// hand-built template literals, which drifted from the real names once
|
|
40
|
+
// toKebab collapsed them.
|
|
41
41
|
//
|
|
42
|
-
// **
|
|
43
|
-
// - Cross-scope
|
|
44
|
-
// - Cross-
|
|
45
|
-
// (cap-counter
|
|
46
|
-
//
|
|
47
|
-
// alle erledigt.)
|
|
42
|
+
// **Still open:**
|
|
43
|
+
// - Cross-scope conflict detection (a tenant overriding a system fieldKey)
|
|
44
|
+
// - Cross-scope read UNION (system + tenant fieldDefinitions in one list)
|
|
45
|
+
// (cap-counter quota, user-data-rights anonymization, and value validation
|
|
46
|
+
// against serializedField via fieldToZod in set-custom-field are complete.)
|
|
48
47
|
|
|
49
48
|
import {
|
|
50
49
|
defineEntityListHandler,
|
|
@@ -97,10 +96,9 @@ const fieldDefinitionDeletedSchema = z.object({
|
|
|
97
96
|
tenantId: z.string().optional(),
|
|
98
97
|
});
|
|
99
98
|
|
|
100
|
-
// Handler
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
// Options-Variante verfehlt.
|
|
99
|
+
// Handler and access variants can differ between the singleton and options
|
|
100
|
+
// variant. Everything else registers identically through registerCustomFields
|
|
101
|
+
// so a new event or handler cannot silently be omitted from the options variant.
|
|
104
102
|
type RegisterVariant = {
|
|
105
103
|
readonly defineTenantHandler: WriteHandlerDef;
|
|
106
104
|
readonly updateTenantHandler: WriteHandlerDef;
|
|
@@ -125,9 +123,9 @@ function registerCustomFields(
|
|
|
125
123
|
});
|
|
126
124
|
r.entity({ name: "field-definition", ...fieldDefinitionEntity });
|
|
127
125
|
|
|
128
|
-
// Event
|
|
129
|
-
// Returned EventDefs
|
|
130
|
-
//
|
|
126
|
+
// Event types — qualified as "custom-fields:event:<short-name>".
|
|
127
|
+
// Returned EventDefs expose .name as a compile-time literal-typed string,
|
|
128
|
+
// which handlers and MSP keys consume instead of constructing template literals.
|
|
131
129
|
// `value: z.unknown()` has no field-level schema to catalog under piiFields
|
|
132
130
|
// (event PII covers string fields only), so "no PII" is a convention here,
|
|
133
131
|
// not an enforced guarantee.
|
|
@@ -143,31 +141,31 @@ function registerCustomFields(
|
|
|
143
141
|
{ piiFields: "none" },
|
|
144
142
|
);
|
|
145
143
|
|
|
146
|
-
//
|
|
147
|
-
// Consumer-side: r.useExtension("customFields", "<entity>")
|
|
148
|
-
//
|
|
149
|
-
// `wireCustomFieldsFor(r, entity, table)`
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
// wiring
|
|
153
|
-
//
|
|
154
|
-
//
|
|
144
|
+
// Registers that this extension exists.
|
|
145
|
+
// Consumer-side: r.useExtension("customFields", "<entity>") marks opt-in,
|
|
146
|
+
// but does not wire anything automatically. The consumer MUST also call
|
|
147
|
+
// `wireCustomFieldsFor(r, entity, table)` to register the MSP, postQuery hook,
|
|
148
|
+
// and search extension.
|
|
149
|
+
// The empty-options pattern (`{}`) is intentional: boot-time onRegister
|
|
150
|
+
// wiring would require a closure over the Drizzle table, which the consumer
|
|
151
|
+
// does not provide during extendsRegistrar registration. Explicit consumer-
|
|
152
|
+
// side wiring therefore avoids implicit magic.
|
|
155
153
|
r.extendsRegistrar(CUSTOM_FIELDS_EXTENSION, {});
|
|
156
154
|
|
|
157
|
-
// Definition
|
|
155
|
+
// Definition CRUD handlers.
|
|
158
156
|
r.writeHandler(variant.defineTenantHandler);
|
|
159
157
|
r.writeHandler(defineSystemFieldHandler);
|
|
160
158
|
r.writeHandler(variant.updateTenantHandler);
|
|
161
159
|
r.writeHandler(variant.deleteTenantHandler);
|
|
162
160
|
r.writeHandler(deleteSystemFieldHandler);
|
|
163
161
|
|
|
164
|
-
// Value
|
|
162
|
+
// Value write handlers. They emit events on the host aggregate stream.
|
|
165
163
|
r.writeHandler(variant.setHandler);
|
|
166
164
|
r.writeHandler(variant.clearHandler);
|
|
167
165
|
|
|
168
|
-
//
|
|
169
|
-
//
|
|
170
|
-
//
|
|
166
|
+
// The list query is tenant-scoped. CustomFieldsFormSection dispatches this
|
|
167
|
+
// query name directly, so apps with their own role vocabulary must override
|
|
168
|
+
// the roles through fieldDefinitionListRoles.
|
|
171
169
|
r.queryHandler(
|
|
172
170
|
defineEntityListHandler("field-definition", fieldDefinitionEntity, {
|
|
173
171
|
access: { roles: variant.fieldDefinitionListRoles },
|
|
@@ -193,24 +191,24 @@ const defaultCustomFieldsFeature = defineFeature(CUSTOM_FIELDS_FEATURE_NAME, (r)
|
|
|
193
191
|
);
|
|
194
192
|
|
|
195
193
|
export type CustomFieldsFeatureOptions = {
|
|
196
|
-
/**
|
|
194
|
+
/** Quota for define-tenant-field. */
|
|
197
195
|
readonly fieldDefinitionLimitPerTenant?: number;
|
|
198
|
-
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
196
|
+
/** Roles for set-/clear-custom-field, used by the save paths in
|
|
197
|
+
* CustomFieldsFormSection. Default ["TenantAdmin","TenantMember"];
|
|
198
|
+
* apps with their own role vocabulary (for example ["Admin","Editor"])
|
|
199
|
+
* MUST set this, otherwise value saving is access_denied for every app user
|
|
200
|
+
* (role-naming drift). */
|
|
203
201
|
readonly valueWriteRoles?: readonly string[];
|
|
204
|
-
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
202
|
+
/** Roles for custom-fields:query:field-definition:list, used by the loading
|
|
203
|
+
* path in CustomFieldsFormSection. Default ["TenantAdmin"]. If
|
|
204
|
+
* valueWriteRoles is set but this is not, the value roles are inherited here
|
|
205
|
+
* (unioned with the default so admins retain list access); otherwise the
|
|
206
|
+
* FormSection cannot load for value writers (access_denied) while the save
|
|
207
|
+
* path remains open (an asymmetric break). */
|
|
210
208
|
readonly fieldDefinitionListRoles?: readonly string[];
|
|
211
209
|
/** Access roles for the definition-CRUD triad (`define-tenant-field`,
|
|
212
|
-
* `update-tenant-field`, `delete-tenant-field`) — hard-wired to ["TenantAdmin"]
|
|
213
|
-
*
|
|
210
|
+
* `update-tenant-field`, `delete-tenant-field`) — hard-wired to ["TenantAdmin"].
|
|
211
|
+
* Apps with their own role vocabulary (e.g. ["Admin","Editor"])
|
|
214
212
|
* MUST set this, else field-definition management is access_denied for every
|
|
215
213
|
* app-user without a "TenantAdmin" role. Only covers the tenant-scope triad —
|
|
216
214
|
* define-/delete-system-field stay hard-wired to ["SystemAdmin"], since
|
|
@@ -19,13 +19,13 @@ export type ClearCustomFieldPayload = z.infer<typeof clearCustomFieldPayloadSche
|
|
|
19
19
|
const CLEAR_CUSTOM_FIELD_REASON =
|
|
20
20
|
"reads custom field definitions with an explicit tenant_id = caller tenant via raw SQL with read retry";
|
|
21
21
|
|
|
22
|
-
// clear-custom-field —
|
|
23
|
-
//
|
|
24
|
-
// jsonb
|
|
22
|
+
// clear-custom-field — removes a custom-field value from a host entity.
|
|
23
|
+
// Emits the customField.cleared event; MSP removes the key from the
|
|
24
|
+
// jsonb column (key removal, not setting it to null).
|
|
25
25
|
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
26
|
+
// Per-field fieldAccess.write gate: the caller must hold one of the defined
|
|
27
|
+
// roles when fieldDefinition.serializedField.fieldAccess.write is set.
|
|
28
|
+
// Handler-level RBAC (TenantAdmin/Member) still applies as well.
|
|
29
29
|
export const clearCustomFieldHandler: WriteHandlerDef = {
|
|
30
30
|
name: "clear-custom-field",
|
|
31
31
|
schema: clearCustomFieldPayloadSchema,
|
|
@@ -73,8 +73,9 @@ export const clearCustomFieldHandler: WriteHandlerDef = {
|
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
76
|
+
/** Companion to createSetCustomFieldHandler: set and clear use the same roles;
|
|
77
|
+
* allowing a value to be set without allowing it to be cleared would leave
|
|
78
|
+
* access control incomplete. */
|
|
78
79
|
export function createClearCustomFieldHandler(
|
|
79
80
|
roles: readonly string[] = DEFAULT_VALUE_WRITE_ROLES,
|
|
80
81
|
): WriteHandlerDef {
|