@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
|
@@ -17,8 +17,7 @@ import type { CustomFieldClearedPayload, CustomFieldSetPayload } from "./events.
|
|
|
17
17
|
import { createCustomFieldsFeature } from "./feature.ts";
|
|
18
18
|
import { CUSTOM_FIELDS_EXTENSION, FIELD_DEFINITION_AGGREGATE_TYPE } from "./web/constants.ts";
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
// hinzu. Consumer:
|
|
20
|
+
// Adds a `customFields jsonb` column to an entity definition.
|
|
22
21
|
//
|
|
23
22
|
// const propertyEntity = createEntity({
|
|
24
23
|
// fields: {
|
|
@@ -27,57 +26,58 @@ import { CUSTOM_FIELDS_EXTENSION, FIELD_DEFINITION_AGGREGATE_TYPE } from "./web/
|
|
|
27
26
|
// },
|
|
28
27
|
// });
|
|
29
28
|
//
|
|
30
|
-
//
|
|
31
|
-
// NOT NULL
|
|
29
|
+
// `customFields` follows the same contract as regular fields: default `{}` and
|
|
30
|
+
// NOT NULL, like embedded columns.
|
|
32
31
|
// @wrapper-known semantic-alias
|
|
33
32
|
export function customFieldsField(): JsonbFieldDef {
|
|
34
33
|
return createJsonbField();
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// search-payload
|
|
36
|
+
// Complete integration of the custom-fields bundle for a specific host
|
|
37
|
+
// entity. One call site per consumer registers all wiring aspects:
|
|
38
|
+
// extension tracking, the value-projection MSP, rebuild replay via
|
|
39
|
+
// extendEntityProjection, the postQuery hook for API flattening, and the
|
|
40
|
+
// search-payload extension for indexable customFields.
|
|
42
41
|
//
|
|
43
42
|
// Consumer-side:
|
|
44
43
|
//
|
|
45
44
|
// defineFeature("property-mgmt", (r) => {
|
|
46
|
-
// r.entity({ name: "property", ...propertyEntity }); //
|
|
45
|
+
// r.entity({ name: "property", ...propertyEntity }); // must have customFieldsField()
|
|
47
46
|
// r.requires({ features: [CUSTOM_FIELDS_FEATURE_NAME] });
|
|
48
47
|
// wireCustomFieldsFor(r, "property", propertyTable);
|
|
49
48
|
// });
|
|
50
49
|
//
|
|
51
|
-
//
|
|
52
|
-
// `buildEntityTable(name, entity)
|
|
53
|
-
//
|
|
50
|
+
// The `entityTable` parameter is the Drizzle table instance (typically the
|
|
51
|
+
// output of `buildEntityTable(name, entity)`). Closing over `entityTable`
|
|
52
|
+
// avoids a runtime table lookup through the registry in the MSP apply
|
|
53
|
+
// function.
|
|
54
54
|
//
|
|
55
|
-
// **
|
|
55
|
+
// **What is registered**:
|
|
56
56
|
//
|
|
57
|
-
// 1. r.useExtension("customFields", entityName) — opt-in marker
|
|
58
|
-
//
|
|
57
|
+
// 1. r.useExtension("customFields", entityName) — opt-in marker enabling
|
|
58
|
+
// boot validation and usage tracking through the registry.
|
|
59
59
|
//
|
|
60
60
|
// 2. r.multiStreamProjection — consumes customField.set/.cleared events
|
|
61
|
-
//
|
|
62
|
-
//
|
|
61
|
+
// emitted by the customer's set-custom-field / clear-custom-field write
|
|
62
|
+
// handlers. Updates entityTable.customFields jsonb through
|
|
63
63
|
// jsonb_set / jsonb-key-removal.
|
|
64
64
|
//
|
|
65
|
-
// 3. r.extendEntityProjection —
|
|
66
|
-
// implicit projection
|
|
67
|
-
// customField
|
|
68
|
-
//
|
|
65
|
+
// 3. r.extendEntityProjection — adds the same apply handlers to the host
|
|
66
|
+
// entity's implicit projection so rebuildProjection replays the
|
|
67
|
+
// customField events. Without this, customFields would reset to `{}` on
|
|
68
|
+
// every entity rebuild (for example, after a schema migration).
|
|
69
69
|
//
|
|
70
|
-
// 4. r.entityHook("postQuery", entity, flatten-fn) —
|
|
71
|
-
//
|
|
72
|
-
//
|
|
70
|
+
// 4. r.entityHook("postQuery", entity, flatten-fn) — on every read of
|
|
71
|
+
// this entity, expands `row.customFields` jsonb at the root level so
|
|
72
|
+
// the API response looks like it contains regular fields.
|
|
73
73
|
//
|
|
74
|
-
// 5. r.searchPayloadExtension(entity, contributor) —
|
|
75
|
-
// customFields
|
|
76
|
-
//
|
|
74
|
+
// 5. r.searchPayloadExtension(entity, contributor) — contributes
|
|
75
|
+
// searchable customFields keys as flat fields in the Meilisearch index
|
|
76
|
+
// document.
|
|
77
77
|
//
|
|
78
|
-
// 6. fieldDefinition.deleted
|
|
79
|
-
//
|
|
80
|
-
//
|
|
78
|
+
// 6. fieldDefinition.deleted event handler in the same MSP — removes
|
|
79
|
+
// orphaned values from all entity rows when a fieldDefinition is deleted
|
|
80
|
+
// (one key removal per fieldKey).
|
|
81
81
|
export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
82
82
|
r: TReg,
|
|
83
83
|
entityName: string,
|
|
@@ -87,24 +87,24 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
87
87
|
r.useExtension(CUSTOM_FIELDS_EXTENSION, entityName);
|
|
88
88
|
|
|
89
89
|
// Qualified event-type-names — sourced from typed EventDef.name handles
|
|
90
|
-
// (compile-time literal-typed, no Template-Literal-Drift
|
|
91
|
-
// collapse
|
|
90
|
+
// (compile-time literal-typed, no Template-Literal-Drift from the toKebab-
|
|
91
|
+
// collapse bug that exposed it).
|
|
92
92
|
const setEventType = createCustomFieldsFeature().exports.setEvent.name;
|
|
93
93
|
const clearedEventType = createCustomFieldsFeature().exports.clearedEvent.name;
|
|
94
94
|
const fieldDefDeletedType = createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name;
|
|
95
95
|
|
|
96
|
-
//
|
|
97
|
-
// entity-projection
|
|
98
|
-
//
|
|
99
|
-
//
|
|
96
|
+
// Shared apply bodies: the MSP supplies them live through an async cursor,
|
|
97
|
+
// while the entity-projection extension replays them in rebuildProjection.
|
|
98
|
+
// Both use the same idempotent SQL helpers. The two-parameter signature is
|
|
99
|
+
// the common subset of MultiStreamApplyFn and SingleStreamApplyFn.
|
|
100
100
|
const applyCustomFieldSet = async (event: StoredEvent, tx: DbRunner): Promise<void> => {
|
|
101
|
-
// skip:
|
|
102
|
-
//
|
|
103
|
-
//
|
|
101
|
+
// skip: fires for every aggregate type that emits customField.set, but only
|
|
102
|
+
// events for the wired host entity should be processed. Other consumers
|
|
103
|
+
// have their own wiring for their entities.
|
|
104
104
|
if (event.aggregateType !== entityName) return;
|
|
105
105
|
const payload = event.payload as CustomFieldSetPayload; // @cast-boundary engine-payload
|
|
106
106
|
|
|
107
|
-
// skip: a value-less customField.set is an anomaly
|
|
107
|
+
// skip: a value-less customField.set is an anomaly (every set
|
|
108
108
|
// carries its value; the sensitive self-projection path was removed) —
|
|
109
109
|
// warn and leave the row untouched instead of binding undefined.
|
|
110
110
|
if (payload.value === undefined) {
|
|
@@ -116,9 +116,9 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
// jsonb_set:
|
|
120
|
-
//
|
|
121
|
-
// jsonb
|
|
119
|
+
// jsonb_set: assigns value to the key. If the key does not yet exist, it is
|
|
120
|
+
// created (`create_missing=true` is the default). value must be supplied
|
|
121
|
+
// as a jsonb literal.
|
|
122
122
|
const tableName = extractTableName(entityTable, "custom-fields/wire-for-entity");
|
|
123
123
|
await setCustomFieldValue(
|
|
124
124
|
tx,
|
|
@@ -131,28 +131,27 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
const applyCustomFieldCleared = async (event: StoredEvent, tx: DbRunner): Promise<void> => {
|
|
134
|
-
// skip:
|
|
135
|
-
// verarbeiten.
|
|
134
|
+
// skip: fires for all aggregate types; process only our host entity.
|
|
136
135
|
if (event.aggregateType !== entityName) return;
|
|
137
136
|
const payload = event.payload as CustomFieldClearedPayload; // @cast-boundary engine-payload
|
|
138
137
|
|
|
139
|
-
// jsonb minus operator (`-`)
|
|
138
|
+
// The jsonb minus operator (`-`) removes a key from a jsonb object.
|
|
140
139
|
const tableName = extractTableName(entityTable, "custom-fields/wire-for-entity");
|
|
141
140
|
await clearCustomFieldKey(tx, tableName, payload.fieldKey, event.aggregateId, event.tenantId);
|
|
142
141
|
};
|
|
143
142
|
|
|
144
143
|
const applyFieldDefinitionDeleted = async (event: StoredEvent, tx: DbRunner): Promise<void> => {
|
|
145
|
-
// fieldDefinition.deleted fires
|
|
146
|
-
//
|
|
147
|
-
//
|
|
144
|
+
// fieldDefinition.deleted fires once per field-definition deletion, not once
|
|
145
|
+
// per entity. Remove the key from all rows of the host entity if the
|
|
146
|
+
// deleted field definition belonged to this entity.
|
|
148
147
|
const payload = event.payload as {
|
|
149
148
|
entityName: string;
|
|
150
149
|
fieldKey: string;
|
|
151
150
|
tenantId?: TenantId;
|
|
152
151
|
}; // @cast-boundary engine-payload
|
|
153
|
-
// skip: fieldDefinition.deleted
|
|
154
|
-
//
|
|
155
|
-
//
|
|
152
|
+
// skip: fieldDefinition.deleted fires for field definitions across all
|
|
153
|
+
// entities; clean rows only when the deleted definition belonged to this
|
|
154
|
+
// host entity.
|
|
156
155
|
if (payload.entityName !== entityName) return;
|
|
157
156
|
|
|
158
157
|
const tableName = extractTableName(entityTable, "custom-fields/wire-for-entity");
|
|
@@ -179,13 +178,12 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
179
178
|
},
|
|
180
179
|
});
|
|
181
180
|
|
|
182
|
-
// Rebuild
|
|
183
|
-
//
|
|
184
|
-
//
|
|
185
|
-
//
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
// kommt deshalb als extra source dazu.
|
|
181
|
+
// Rebuild wiring: without it, rebuildProjection replays only entity
|
|
182
|
+
// lifecycle events and resets each customFields jsonb value to its default
|
|
183
|
+
// `{}`. The values exist only in customField.set/.cleared events. set/
|
|
184
|
+
// cleared events use the HOST entity stream (aggregateType = entityName,
|
|
185
|
+
// already covered by the source); fieldDefinition.deleted belongs to the
|
|
186
|
+
// "field-definition" stream and is therefore added as an extra source.
|
|
189
187
|
r.extendEntityProjection(entityName, {
|
|
190
188
|
sources: [FIELD_DEFINITION_AGGREGATE_TYPE],
|
|
191
189
|
apply: {
|
|
@@ -195,8 +193,8 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
195
193
|
},
|
|
196
194
|
});
|
|
197
195
|
|
|
198
|
-
// postQuery
|
|
199
|
-
//
|
|
196
|
+
// postQuery hook: expands row.customFields jsonb at the API response's root
|
|
197
|
+
// level so it is indistinguishable from regular fields.
|
|
200
198
|
r.hook({
|
|
201
199
|
type: "postQuery",
|
|
202
200
|
target: { allOf: entityName },
|
|
@@ -214,11 +212,11 @@ export function wireCustomFieldsFor<TReg extends FeatureRegistrar<string>>(
|
|
|
214
212
|
}),
|
|
215
213
|
});
|
|
216
214
|
|
|
217
|
-
// Search-
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
215
|
+
// Search-payload extension: flattens customFields keys into the index
|
|
216
|
+
// document. Unlike the postQuery hook, which merges ALL keys, the search
|
|
217
|
+
// contributor should include only fields defined with searchable=true. The
|
|
218
|
+
// current version conservatively contributes everything; a later change
|
|
219
|
+
// will filter by the fieldDefinition.searchable flag.
|
|
222
220
|
r.searchPayloadExtension(entityName, ({ state }) => {
|
|
223
221
|
const customFields = state["customFields"];
|
|
224
222
|
if (customFields && typeof customFields === "object" && !Array.isArray(customFields)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// User-data-rights wiring for custom-fields.
|
|
2
2
|
|
|
3
3
|
import { type DbRunner, extractTableName } from "@cosmicdrift/kumiko-framework/db";
|
|
4
4
|
import type { UserDataExportSnippet, UserDataHookCtx } from "@cosmicdrift/kumiko-framework/engine";
|
|
@@ -28,7 +28,7 @@ function asCustomFieldsHostRow(value: unknown): CustomFieldsHostRow | null {
|
|
|
28
28
|
return { id, customFields: Object.fromEntries(Object.entries(cf)) };
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// selectCustomFieldsHostRows runs raw SQL against a dynamic host
|
|
32
32
|
// table name (opts.entityTable varies per call site), so it can't go through
|
|
33
33
|
// TenantDb's typed method API (table param must be a known SchemaTable). The
|
|
34
34
|
// SQL text itself still filters `tenant_id = ctx.tenantId`, so this stays a
|
|
@@ -64,7 +64,7 @@ async function exportCustomFields(
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
// Export-only wiring: custom fields hold supplemental business data, not PII
|
|
67
|
-
//
|
|
67
|
+
// — there is nothing to redact on user-forget, only Art. 20 export.
|
|
68
68
|
export function wireCustomFieldsUserDataRightsFor<TReg extends FeatureRegistrar<string>>(
|
|
69
69
|
r: TReg,
|
|
70
70
|
opts: WireCustomFieldsUserDataRightsOptions,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// `feedback_bulk_patterns` — Drift-Risiko bei Schema-Aenderungen).
|
|
1
|
+
// Shared override parser for policy-for-Query and the resolve-for-tenant helper. It was
|
|
2
|
+
// duplicated 1:1 in both files, so schema changes could make the copies drift.
|
|
4
3
|
|
|
5
4
|
import { retentionOverrideSchema } from "../override-schema.ts";
|
|
6
5
|
import type { RetentionOverride } from "../resolver.ts";
|
|
@@ -36,25 +36,18 @@ export {
|
|
|
36
36
|
tenantRetentionOverrideTable,
|
|
37
37
|
} from "./schema/tenant-retention-override.ts";
|
|
38
38
|
|
|
39
|
-
// data-retention —
|
|
39
|
+
// data-retention — automated retention and deletion per entity.
|
|
40
40
|
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// - Retention-Presets (dsgvo-basic, dsgvo-hgb, swiss-dsg, default)
|
|
44
|
-
// - tenantRetentionOverride-Entity für per-Tenant Edge-Cases
|
|
41
|
+
// Retention is resolved through three layers: entity default → tenant preset →
|
|
42
|
+
// tenant override stored in `tenantRetentionOverride`.
|
|
45
43
|
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
44
|
+
// The retention-cleanup cron performs batched hard deletes and soft deletes per
|
|
45
|
+
// tenant. The tenant preset can be derived from the compliance profile, while
|
|
46
|
+
// anonymization is deferred and uses an idempotency marker; see
|
|
47
|
+
// `run-retention-cleanup.ts`.
|
|
50
48
|
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// Cross-Feature-Hinweis: Plan-Roadmap docs/plans/datenschutz/
|
|
55
|
-
// core-data-retention.md — Forget-Flow konsultiert blockDelete via
|
|
56
|
-
// retention.policyFor → anonymize statt hardDelete bei Aufbewahrungs-
|
|
57
|
-
// pflicht. Das Wiring kommt in Sprint 2.U5.
|
|
49
|
+
// The forget flow consults `retention.policyFor` and anonymizes records instead
|
|
50
|
+
// of hard-deleting them while a mandatory retention period applies.
|
|
58
51
|
export function createDataRetentionFeature(): FeatureDefinition {
|
|
59
52
|
return defineFeature("data-retention", (r) => {
|
|
60
53
|
r.describe(
|
|
@@ -67,11 +60,11 @@ export function createDataRetentionFeature(): FeatureDefinition {
|
|
|
67
60
|
});
|
|
68
61
|
r.entity({ name: "tenant-retention-override", ...tenantRetentionOverrideEntity });
|
|
69
62
|
|
|
70
|
-
//
|
|
63
|
+
// Cross-feature API for the forget flow and cleanup job
|
|
71
64
|
r.exposesApi("retention.policyFor");
|
|
72
65
|
r.queryHandler(policyForQuery);
|
|
73
66
|
|
|
74
|
-
//
|
|
67
|
+
// Autonomous retention cleanup. perTenant fan-out (one run per
|
|
75
68
|
// active tenant, like soft-delete-cleanup): runRetentionCleanup's raw
|
|
76
69
|
// query helpers need the unfiltered runner, so the handler declares
|
|
77
70
|
// escapeHatch and reaches for ctx.db.unsafeRaw(). Without this cron,
|
|
@@ -3,18 +3,18 @@ import * as z from "zod";
|
|
|
3
3
|
import { resolveRetentionPolicyForTenant } from "../resolve-for-tenant.ts";
|
|
4
4
|
import type { EffectiveRetentionPolicy } from "../resolver.ts";
|
|
5
5
|
|
|
6
|
-
// retention:query:policy-for — Cross-
|
|
6
|
+
// retention:query:policy-for — Cross-feature API for the forget flow.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// The forget flow calls this for each entity to determine whether it should
|
|
9
|
+
// use "delete", "anonymize", or "blockDelete-bis-Frist". The cleanup job uses
|
|
10
|
+
// it for the same purpose.
|
|
11
11
|
//
|
|
12
12
|
// Delegates to resolveRetentionPolicyForTenant so forget, the cleanup cron and
|
|
13
13
|
// this query can never disagree about the tenant preset. Letting the resolver
|
|
14
14
|
// load the preset itself costs one read per call, fine for a single lookup.
|
|
15
15
|
//
|
|
16
|
-
// access: openToAll —
|
|
17
|
-
//
|
|
16
|
+
// access: openToAll — other features in the same tenant may retrieve this.
|
|
17
|
+
// The result contains no PII, only policy metadata.
|
|
18
18
|
export const policyForQuery = defineQueryHandler({
|
|
19
19
|
name: "policy-for",
|
|
20
20
|
schema: z.object({
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
// keepFor
|
|
1
|
+
// keepFor format parser: "30d" / "10y" / "6m" / "1w" / "24h" → cutoff instant.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// Not millisecond-precise — GDPR retention requirements use day/month
|
|
4
|
+
// granularity. "6m" = 6×30d, "10y" = 10×365d. The cleanup job runs daily,
|
|
5
|
+
// so a difference of a few days at the cutoff is acceptable.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
7
|
+
// The boot validator already checked the format against /^\d+[hdwmy]$/
|
|
8
|
+
// — validate defensively again here for migration edge cases.
|
|
9
9
|
//
|
|
10
|
-
// Temporal
|
|
11
|
-
// `getTemporal()`
|
|
10
|
+
// Temporal is provided via globalThis (the polyfill is installed during framework boot).
|
|
11
|
+
// `getTemporal()` from framework/time provides typed access.
|
|
12
12
|
|
|
13
13
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
14
14
|
|
|
@@ -29,17 +29,17 @@ export class InvalidKeepForError extends Error {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
// Re-export
|
|
33
|
-
//
|
|
32
|
+
// Re-export Temporal.Instant as a type alias so callers do not have to obtain
|
|
33
|
+
// the type from globalThis themselves.
|
|
34
34
|
export type Instant = InstanceType<ReturnType<typeof getTemporal>["Instant"]>;
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* Computes the cutoff instant — rows with reference < cutoff are expired
|
|
38
|
+
* and removed by the cleanup job.
|
|
39
39
|
*
|
|
40
|
-
* @param spec keepFor
|
|
41
|
-
* @param now
|
|
42
|
-
*
|
|
40
|
+
* @param spec keepFor string such as "30d", "10y", "6m", "1w", "24h"
|
|
41
|
+
* @param now Current point in time (injection parameter for time-travel tests;
|
|
42
|
+
* not global Temporal.Now)
|
|
43
43
|
*/
|
|
44
44
|
export function computeCutoff(spec: string, now: Instant): Instant {
|
|
45
45
|
const match = KEEP_FOR_PATTERN.exec(spec);
|
|
@@ -61,8 +61,8 @@ export function computeCutoff(spec: string, now: Instant): Instant {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
64
|
+
* Determines whether referenceTimestamp is older than the keepFor cutoff at now.
|
|
65
|
+
* The cleanup job uses this for each row.
|
|
66
66
|
*/
|
|
67
67
|
export function isPastCutoff(args: {
|
|
68
68
|
readonly referenceTimestamp: Instant;
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
// Zod
|
|
1
|
+
// Strict Zod schema for RetentionOverride.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// Symmetric with compliance-profiles override-schema.ts.
|
|
4
|
+
// Every user-configurable JSON override uses strict Zod validation
|
|
5
|
+
// with enum validation.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
// - Top-
|
|
9
|
-
// - Strategy
|
|
10
|
-
// - keepFor
|
|
7
|
+
// Protects against:
|
|
8
|
+
// - Top-level typos ("keepfor" instead of "keepFor") — strict() rejects them
|
|
9
|
+
// - Strategy enum drift ("delete" instead of "hardDelete") — z.enum rejects it
|
|
10
|
+
// - keepFor format drift ("30days" instead of "30d") — regex rejects it
|
|
11
11
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// gueltig sein.
|
|
12
|
+
// A tenant override may omit all three properties (the resolver falls back
|
|
13
|
+
// to the preset/entity default), but every property that is set must be valid.
|
|
15
14
|
|
|
16
15
|
import * as z from "zod";
|
|
17
16
|
|
|
@@ -20,10 +19,9 @@ const KEEP_FOR_PATTERN = /^\d+[hdwmy]$/;
|
|
|
20
19
|
const retentionStrategySchema = z.enum(["hardDelete", "softDelete", "anonymize", "blockDelete"]);
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* undefined behavior weiterzumachen.
|
|
22
|
+
* Strict Zod schema for RetentionOverride, used by the set-override handler
|
|
23
|
+
* and the cleanup job's DB loader. The loader logs invalid JSON from the
|
|
24
|
+
* config column and skips it instead of continuing with undefined behavior.
|
|
27
25
|
*/
|
|
28
26
|
export const retentionOverrideSchema = z
|
|
29
27
|
.object({
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
// Retention
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Retention presets — predefined bundles of per-entity retention
|
|
2
|
+
// configurations for each compliance regime. The tenant admin selects ONE
|
|
3
|
+
// (analogous to compliance profiles); the entity default and tenant override
|
|
4
|
+
// are layered above it as layers 1 and 3 (see resolver.ts).
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// rest folgt on-demand wenn Customer fragt.
|
|
9
|
-
//
|
|
10
|
-
// Presets sind pure Daten — keine Logik. Erweitern = Constant erweitern,
|
|
11
|
-
// kein Code-Eingriff.
|
|
6
|
+
// The presets are pure data with no logic. Extending them means extending the
|
|
7
|
+
// constant; no code changes are required.
|
|
12
8
|
|
|
13
9
|
import type { RetentionDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
14
10
|
|
|
@@ -23,25 +19,25 @@ export type RetentionPreset = Readonly<Record<string, RetentionDef>>;
|
|
|
23
19
|
export type RetentionPresetKey = "default" | "dsgvo-basic" | "dsgvo-hgb" | "swiss-dsg";
|
|
24
20
|
|
|
25
21
|
/**
|
|
26
|
-
*
|
|
27
|
-
* pipeda-default, ca-quebec-l25)
|
|
22
|
+
* Available presets. Additional options (hipaa, ccpa, aggressive-gdpr,
|
|
23
|
+
* pipeda-default, ca-quebec-l25) can be added on demand.
|
|
28
24
|
*/
|
|
29
25
|
export const RETENTION_PRESETS: Readonly<Record<RetentionPresetKey, RetentionPreset>> = {
|
|
30
|
-
// Default —
|
|
31
|
-
//
|
|
32
|
-
//
|
|
26
|
+
// Default — no automatic action; intended only for Dev/Staging.
|
|
27
|
+
// A production tenant that leaves `default` selected causes the cleanup job
|
|
28
|
+
// to write the audit entry "skipped: no preset selected".
|
|
33
29
|
default: {},
|
|
34
30
|
|
|
35
|
-
// DSGVO Basic —
|
|
31
|
+
// DSGVO Basic — data minimization without accounting retention obligations.
|
|
36
32
|
"dsgvo-basic": {
|
|
37
33
|
"audit-log": { keepFor: "1y", strategy: "hardDelete", reference: "createdAt" },
|
|
38
34
|
session: { keepFor: "30d", strategy: "hardDelete", reference: "lastSeenAt" },
|
|
39
35
|
"http-log": { keepFor: "90d", strategy: "hardDelete", reference: "createdAt" },
|
|
40
36
|
},
|
|
41
37
|
|
|
42
|
-
// DSGVO + HGB —
|
|
43
|
-
//
|
|
44
|
-
//
|
|
38
|
+
// DSGVO + HGB — German statutory retention obligations take precedence.
|
|
39
|
+
// Orders are anonymized (PII removed while business data remains); invoices
|
|
40
|
+
// and bookings are blockDelete for up to 10 years, then anonymized.
|
|
45
41
|
"dsgvo-hgb": {
|
|
46
42
|
"audit-log": { keepFor: "1y", strategy: "hardDelete", reference: "createdAt" },
|
|
47
43
|
session: { keepFor: "30d", strategy: "hardDelete", reference: "lastSeenAt" },
|
|
@@ -52,7 +48,7 @@ export const RETENTION_PRESETS: Readonly<Record<RetentionPresetKey, RetentionPre
|
|
|
52
48
|
order: { keepFor: "6y", strategy: "anonymize", reference: "completedAt" },
|
|
53
49
|
},
|
|
54
50
|
|
|
55
|
-
//
|
|
51
|
+
// Swiss DSG — similar to DSGVO, with retention under OR Art. 958f.
|
|
56
52
|
"swiss-dsg": {
|
|
57
53
|
"audit-log": { keepFor: "1y", strategy: "hardDelete", reference: "createdAt" },
|
|
58
54
|
session: { keepFor: "30d", strategy: "hardDelete", reference: "lastSeenAt" },
|
|
@@ -61,9 +57,8 @@ export const RETENTION_PRESETS: Readonly<Record<RetentionPresetKey, RetentionPre
|
|
|
61
57
|
} satisfies Readonly<Record<RetentionPresetKey, RetentionPreset>>;
|
|
62
58
|
|
|
63
59
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* echtes Preset.
|
|
60
|
+
* Presets available in the onboarding banner. `default` is a migration edge
|
|
61
|
+
* case and is not displayed; production tenants must choose an actual preset.
|
|
67
62
|
*/
|
|
68
63
|
export const SELECTABLE_RETENTION_PRESETS: readonly RetentionPresetKey[] = [
|
|
69
64
|
"dsgvo-basic",
|
|
@@ -13,7 +13,7 @@ import { type EffectiveRetentionPolicy, resolveRetentionPolicy } from "./resolve
|
|
|
13
13
|
import { tenantRetentionOverrideTable } from "./schema/tenant-retention-override.ts";
|
|
14
14
|
|
|
15
15
|
export interface ResolveForTenantArgs {
|
|
16
|
-
//
|
|
16
|
+
// A EXT_USER_DATA hook's ctx.db is a TenantDb (method-form);
|
|
17
17
|
// the cleanup cron's own db is still a raw DbRunner. Both are valid here —
|
|
18
18
|
// this lookup is a plain tenant-scoped read either way.
|
|
19
19
|
readonly db: DbRunner | TenantDb;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Derives a tenant's Layer-2 retention preset from its compliance profile.
|
|
2
|
+
// The retention-cleanup cron calls this once per fan-out tenant.
|
|
3
3
|
//
|
|
4
|
-
// **Soft
|
|
5
|
-
// compliance-profiles
|
|
6
|
-
//
|
|
7
|
-
// (Layer 1)
|
|
8
|
-
//
|
|
4
|
+
// **Soft dependency:** data-retention remains mountable standalone. A preset is
|
|
5
|
+
// derived only when compliance-profiles is mounted as well (its entity is
|
|
6
|
+
// registered); otherwise this returns null, leaving only entity defaults
|
|
7
|
+
// (Layer 1) and per-entity tenant overrides (Layer 3). No r.requires is used,
|
|
8
|
+
// so an app can use data-retention without compliance-profiles.
|
|
9
9
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// The mapping is intentional: compliance profiles (regions) and retention
|
|
11
|
+
// presets are both built around the same three regimes (EU/CH/DE-HGB).
|
|
12
|
+
// swiss-dsg even has the same name. minimal-no-region maps to "default"
|
|
13
|
+
// (a no-op preset).
|
|
13
14
|
|
|
14
15
|
import type { ComplianceProfileKey } from "@cosmicdrift/kumiko-framework/compliance";
|
|
15
16
|
import type { DbRunner, TenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -17,8 +18,8 @@ import type { Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
|
17
18
|
import { resolveProfileForTenant } from "../compliance-profiles/index.ts";
|
|
18
19
|
import type { RetentionPresetKey } from "./presets.ts";
|
|
19
20
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
21
|
+
// Entity name from compliance-profiles/feature.ts — check that the feature is
|
|
22
|
+
// mounted before reading its table; otherwise fetchOne throws.
|
|
22
23
|
const COMPLIANCE_PROFILE_ENTITY = "tenant-compliance-profile";
|
|
23
24
|
|
|
24
25
|
const PROFILE_TO_PRESET: Readonly<Record<ComplianceProfileKey, RetentionPresetKey>> = {
|
|
@@ -43,12 +44,12 @@ export async function resolveTenantRetentionPreset(
|
|
|
43
44
|
if (!args.registry.getEntity(COMPLIANCE_PROFILE_ENTITY)) {
|
|
44
45
|
return null;
|
|
45
46
|
}
|
|
46
|
-
// resolveProfileForTenant
|
|
47
|
-
// by tenantId
|
|
48
|
-
//
|
|
47
|
+
// resolveProfileForTenant reads the tenant's 1:1 profile row from the boot DB,
|
|
48
|
+
// filtered by tenantId, and falls back to minimal-no-region when the tenant
|
|
49
|
+
// has not selected a profile yet.
|
|
49
50
|
const effective = await resolveProfileForTenant({ db: args.db, tenantId: args.tenantId });
|
|
50
51
|
return PROFILE_TO_PRESET[effective.profile.key] ?? null;
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
//
|
|
54
|
+
// Exported for the unit test that checks completeness against ComplianceProfileKey.
|
|
54
55
|
export { PROFILE_TO_PRESET };
|