@cosmicdrift/kumiko-samples 0.386.0 → 0.388.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 +9 -2
- package/packages/bundled-features/src/agent-tools/changes.json +6 -0
- package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
- package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +9 -9
- package/packages/bundled-features/src/audit/changes.json +12 -0
- package/packages/bundled-features/src/audit/handlers/audit-events.ts +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/auth-mfa/feature-exports.ts +2 -2
- package/packages/bundled-features/src/auth-mfa/feature.ts +6 -0
- 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 +9 -4
- 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-code-or-recovery-field.tsx +68 -0
- package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +23 -13
- package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +23 -13
- package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +15 -6
- package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +71 -24
- package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
- package/packages/bundled-features/src/billing-foundation/changes.json +55 -0
- package/packages/bundled-features/src/billing-foundation/checkout-core.ts +32 -42
- package/packages/bundled-features/src/billing-foundation/consumer-protection/confirmation-mail.ts +8 -2
- package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +14 -3
- package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +3 -4
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +12 -6
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +35 -19
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +12 -8
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +14 -8
- package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +5 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/withdrawal-period.ts +8 -10
- package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
- package/packages/bundled-features/src/billing-foundation/events.ts +23 -21
- package/packages/bundled-features/src/billing-foundation/feature.ts +45 -44
- package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
- package/packages/bundled-features/src/billing-foundation/handlers/billing-plans.query.ts +71 -6
- package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +19 -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/plan-switch-preview.query.ts +65 -0
- package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +29 -22
- package/packages/bundled-features/src/billing-foundation/handlers/start-plan-checkout.write.ts +44 -8
- package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +72 -82
- package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +14 -1
- package/packages/bundled-features/src/billing-foundation/i18n.ts +22 -0
- package/packages/bundled-features/src/billing-foundation/index.ts +2 -0
- package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +62 -27
- package/packages/bundled-features/src/billing-foundation/plan-switch.ts +84 -0
- 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 +144 -66
- package/packages/bundled-features/src/billing-foundation/validate-options.ts +19 -0
- package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +123 -51
- package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +89 -42
- package/packages/bundled-features/src/billing-foundation/web/constants.ts +4 -0
- package/packages/bundled-features/src/billing-foundation/web/plan-price.ts +55 -0
- package/packages/bundled-features/src/billing-foundation/web/plan-switch-confirm-dialog.tsx +224 -0
- 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/cap-reservation.ts +5 -1
- package/packages/bundled-features/src/cap-counter/changes.json +18 -0
- package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
- package/packages/bundled-features/src/cap-counter/enforce-cap.ts +66 -68
- 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 +9 -2
- 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/changes.json +6 -0
- package/packages/bundled-features/src/channel-email/feature.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/changes.json +12 -0
- package/packages/bundled-features/src/config/handlers/cascade.query.ts +4 -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/handlers/values.query.ts +4 -2
- 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 +28 -9
- package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
- package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +23 -21
- 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/changes.json +30 -0
- package/packages/bundled-features/src/delivery/channel-context.ts +9 -3
- package/packages/bundled-features/src/delivery/db/queries/preferences.ts +2 -2
- package/packages/bundled-features/src/delivery/delivery-service.ts +35 -5
- 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/handlers/preferences.query.ts +20 -1
- package/packages/bundled-features/src/delivery/handlers/unsubscribe-page-chrome.query.ts +1 -1
- package/packages/bundled-features/src/delivery/tables.ts +9 -8
- package/packages/bundled-features/src/delivery/unsubscribe-link.ts +3 -1
- package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +1 -0
- package/packages/bundled-features/src/delivery/unsubscribe-page.ts +6 -0
- package/packages/bundled-features/src/delivery/unsubscribe.ts +40 -19
- 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-foundation/index.ts +1 -0
- package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -1
- package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
- package/packages/bundled-features/src/file-provider-s3/env-named-feature.ts +0 -2
- 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/README.md +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +3 -3
- package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
- package/packages/bundled-features/src/form-draft/decrypt-draft.ts +4 -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/host-routing/README.md +1 -1
- package/packages/bundled-features/src/host-routing/changes.json +6 -0
- package/packages/bundled-features/src/host-routing/dispatch.ts +16 -17
- package/packages/bundled-features/src/host-routing/options.ts +2 -1
- package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
- package/packages/bundled-features/src/inbound-mail-foundation/changes.json +18 -0
- 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 +27 -15
- package/packages/bundled-features/src/inbound-mail-foundation/i18n.ts +0 -1
- 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/screens.ts +0 -3
- package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
- package/packages/bundled-features/src/inbound-mail-foundation/types.ts +70 -70
- package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +101 -84
- 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/changes.json +13 -0
- 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 +20 -11
- 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/handlers/tenant-failures.query.ts +45 -40
- package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +63 -59
- package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
- package/packages/bundled-features/src/jobs/job-run-logger.ts +19 -19
- 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/README.md +1 -1
- 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/changes.json +6 -0
- package/packages/bundled-features/src/mail-foundation/feature.ts +31 -30
- 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 +9 -6
- 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/renderer-pdf/changes.json +6 -0
- package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +27 -10
- 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 +16 -11
- 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 +11 -1
- package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
- package/packages/bundled-features/src/shared/index.ts +1 -1
- package/packages/bundled-features/src/shared/mail-template-body.ts +10 -3
- 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/step-dispatcher/changes.json +6 -0
- package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -0
- package/packages/bundled-features/src/subscription-dodo/changes.json +14 -0
- package/packages/bundled-features/src/subscription-dodo/client.ts +45 -0
- package/packages/bundled-features/src/subscription-dodo/constants.ts +24 -0
- package/packages/bundled-features/src/subscription-dodo/feature.ts +207 -0
- package/packages/bundled-features/src/subscription-dodo/index.ts +16 -0
- package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +345 -0
- package/packages/bundled-features/src/subscription-dodo/runtime.ts +126 -0
- package/packages/bundled-features/src/subscription-dodo/verify-webhook.ts +262 -0
- 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/changes.json +12 -0
- package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
- package/packages/bundled-features/src/subscription-stripe/feature.ts +45 -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 +9 -8
- 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 +41 -14
- package/packages/bundled-features/src/template-resolver/changes.json +48 -0
- package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -0
- package/packages/bundled-features/src/template-resolver/feature.ts +2 -2
- package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +27 -5
- package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +3 -2
- package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +8 -7
- package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +19 -20
- package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +15 -5
- 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/tenant-override-counts.query.ts +9 -5
- package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +8 -6
- package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +44 -5
- 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/handlers/usage.query.ts +37 -26
- package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +7 -2
- package/packages/bundled-features/src/template-resolver/seeding.ts +36 -18
- package/packages/bundled-features/src/template-resolver/store-template-resource.ts +22 -4
- package/packages/bundled-features/src/template-resolver/table.ts +13 -14
- package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +0 -11
- package/packages/bundled-features/src/template-resolver/template-meta.ts +12 -4
- package/packages/bundled-features/src/template-resolver/template-preview.ts +11 -3
- package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
- package/packages/bundled-features/src/template-resolver/web/constants.ts +7 -5
- package/packages/bundled-features/src/template-resolver/web/index.ts +7 -0
- package/packages/bundled-features/src/template-resolver/web/mail-layout-constants.ts +8 -0
- package/packages/bundled-features/src/tenant/changes.json +6 -0
- package/packages/bundled-features/src/tenant/feature.ts +7 -7
- package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +10 -4
- 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 +8 -5
- 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/changes.json +6 -0
- package/packages/bundled-features/src/tenant-lifecycle/constants.ts +5 -0
- package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
- package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +7 -3
- 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/changes.json +6 -0
- 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 +12 -9
- 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/constants.ts +3 -3
- 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 +169 -280
- package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +87 -108
- 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/waitlist/changes.json +18 -0
- package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +2 -1
- package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +5 -5
- package/packages/bundled-features/src/waitlist/import.ts +5 -0
- package/packages/bundled-features/src/waitlist/legacy-migrate.ts +22 -3
- package/packages/bundled-features/src/waitlist/link-on-signup.ts +20 -10
- package/packages/bundled-features/src/waitlist/options.ts +3 -0
- 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
- package/samples/apps/styleguide/src/features/widgets/i18n.ts +11 -0
- package/samples/apps/styleguide/src/features/widgets/web/Widgets.tsx +24 -0
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-constants.ts +5 -0
- package/samples/apps/use-all-bundled/e2e-billing-gallery/gallery-features.ts +90 -15
- package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +16 -6
- package/samples/apps/use-all-bundled/feature-manifest.json +120 -3
- package/samples/apps/use-all-bundled/src/run-config.ts +9 -3
- package/samples/recipes/auth-mfa/README.md +5 -0
- package/samples/recipes/auth-mfa/package.json +5 -2
- package/samples/recipes/auth-mfa/src/web/confirmation-code-step.tsx +49 -0
- package/samples/recipes/auth-mfa/tsconfig.json +8 -0
- package/samples/recipes/env-composition/README.md +3 -1
- package/samples/recipes/env-composition/src/env.ts +2 -0
- package/samples/recipes/legal-pages/README.md +1 -1
- package/samples/recipes/rate-limiting/README.md +18 -0
- package/samples/recipes/rate-limiting/src/feature.ts +12 -0
- package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +0 -12
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { SUPPORTED_FIELD_TYPES } from "./web/constants.ts";
|
|
3
3
|
|
|
4
|
-
// Field-Type-Validator — pinnt valid type-Werte für fieldDefinition.
|
|
5
4
|
export const fieldTypeSchema = z.enum(SUPPORTED_FIELD_TYPES);
|
|
6
5
|
|
|
7
6
|
// Per-field access-control. When set, `set/clear-custom-field` handlers
|
|
@@ -9,8 +8,8 @@ export const fieldTypeSchema = z.enum(SUPPORTED_FIELD_TYPES);
|
|
|
9
8
|
// in addition to the handler-level RBAC. Absent or empty `write` means
|
|
10
9
|
// the handler-level RBAC is the only gate.
|
|
11
10
|
//
|
|
12
|
-
// `read` is reserved for the postQuery-flatten pipeline
|
|
13
|
-
// enforced
|
|
11
|
+
// `read` is reserved for the postQuery-flatten pipeline and is not
|
|
12
|
+
// currently enforced.
|
|
14
13
|
export const customFieldAccessSchema = z
|
|
15
14
|
.object({
|
|
16
15
|
read: z.array(z.string()).optional(),
|
|
@@ -19,11 +18,12 @@ export const customFieldAccessSchema = z
|
|
|
19
18
|
.optional();
|
|
20
19
|
export type CustomFieldAccess = z.infer<typeof customFieldAccessSchema>;
|
|
21
20
|
|
|
22
|
-
// Serialized-field
|
|
23
|
-
// In v1
|
|
24
|
-
//
|
|
21
|
+
// Serialized-field JSONB: the value stored in the `serializedField` column.
|
|
22
|
+
// In v1, it is not strictly typed per field type because the base-field
|
|
23
|
+
// builder schemas are not yet exposed. This schema only guarantees the
|
|
24
|
+
// overall structure.
|
|
25
25
|
//
|
|
26
|
-
// Schema
|
|
26
|
+
// Schema shape (example inputs for the different field types):
|
|
27
27
|
//
|
|
28
28
|
// text: { type: "text", required: true, maxLength: 50 }
|
|
29
29
|
// number: { type: "number", required: false, min: 0, max: 100 }
|
|
@@ -33,13 +33,13 @@ export type CustomFieldAccess = z.infer<typeof customFieldAccessSchema>;
|
|
|
33
33
|
// money: { type: "money", required: false, currency: "EUR" }
|
|
34
34
|
// embedded: { type: "embedded", required: false, schema: { ... } }
|
|
35
35
|
//
|
|
36
|
-
// `fieldAccess`
|
|
37
|
-
// Everything else
|
|
36
|
+
// `fieldAccess` is the structured key recognised by the handlers.
|
|
37
|
+
// Everything else remains loose pending per-type discriminated unions —
|
|
38
38
|
// EXCEPT `sensitive`, which is explicitly rejected below: custom fields
|
|
39
|
-
// carry supplemental business data only, PII support was removed
|
|
39
|
+
// carry supplemental business data only, and PII support was removed.
|
|
40
40
|
const serializedFieldBaseShape = {
|
|
41
41
|
fieldAccess: customFieldAccessSchema,
|
|
42
|
-
// `retention
|
|
42
|
+
// `retention`: per-field expiry. The retention-cron strips
|
|
43
43
|
// values whose host-row `modified_at` is older than `keepFor`. Strategy
|
|
44
44
|
// `delete` removes the key from the customFields jsonb; `anonymize`
|
|
45
45
|
// sets it to `null` (key stays, value gone — preserves the schema
|
|
@@ -69,10 +69,10 @@ const updateSerializedFieldSchema = z
|
|
|
69
69
|
.looseObject({ type: fieldTypeSchema.optional(), ...serializedFieldBaseShape })
|
|
70
70
|
.refine(...rejectSensitive);
|
|
71
71
|
|
|
72
|
-
// i18n
|
|
72
|
+
// i18n labels — `{ de: "...", en: "...", ... }`. At least one entry.
|
|
73
73
|
const labelSchema = z.record(z.string().min(2).max(8), z.string().min(1));
|
|
74
74
|
|
|
75
|
-
// Payload
|
|
75
|
+
// Payload for the `define-tenant-field` and `define-system-field` write handlers.
|
|
76
76
|
export const defineFieldPayloadSchema = z.object({
|
|
77
77
|
entityName: z.string().min(1).max(64),
|
|
78
78
|
fieldKey: z
|
|
@@ -100,7 +100,7 @@ export const updateFieldPayloadSchema = defineFieldPayloadSchema.extend({
|
|
|
100
100
|
});
|
|
101
101
|
export type UpdateFieldPayload = z.infer<typeof updateFieldPayloadSchema>;
|
|
102
102
|
|
|
103
|
-
// Payload
|
|
103
|
+
// Payload for `delete-tenant-field` / `delete-system-field`.
|
|
104
104
|
export const deleteFieldPayloadSchema = z.object({
|
|
105
105
|
entityName: z.string().min(1).max(64),
|
|
106
106
|
fieldKey: z.string().min(1).max(64),
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// und registriert die CustomFieldsFormSection unter dem Namen
|
|
4
|
-
// CUSTOM_FIELDS_FORM_EXTENSION_NAME im ExtensionSectionsProvider. Apps
|
|
5
|
-
// referenzieren den Namen im Screen-Schema:
|
|
1
|
+
// Registers the custom-fields form section under
|
|
2
|
+
// CUSTOM_FIELDS_FORM_EXTENSION_NAME so apps can reference it in their screen schema:
|
|
6
3
|
//
|
|
7
4
|
// layout: { sections: [
|
|
8
5
|
// { kind: "extension", title: "...", contributesToFormSubmit: true, component: {
|
|
@@ -56,8 +56,8 @@ export const CUSTOM_FIELDS_EXTENSION = "customFields";
|
|
|
56
56
|
// every app user.
|
|
57
57
|
export const DEFAULT_VALUE_WRITE_ROLES = ["TenantAdmin", "TenantMember"] as const;
|
|
58
58
|
export const DEFAULT_FIELD_DEFINITION_LIST_ROLES = ["TenantAdmin"] as const;
|
|
59
|
-
// Default-RBAC of the definition-CRUD triad (define-/update-/delete-tenant-field
|
|
60
|
-
//
|
|
59
|
+
// Default-RBAC of the definition-CRUD triad (define-/update-/delete-tenant-field).
|
|
60
|
+
// Apps with their own role vocabulary override via
|
|
61
61
|
// createCustomFieldsFeature({ fieldDefinitionWriteRoles }) — otherwise those three
|
|
62
62
|
// hard-wired handler QNs are access_denied for every app-user without a
|
|
63
63
|
// "TenantAdmin" role (same Role-Naming-Drift as DEFAULT_VALUE_WRITE_ROLES above).
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
// CustomFieldsFormSection — extension-section component
|
|
2
|
-
//
|
|
3
|
-
// host
|
|
4
|
-
// `custom-fields:write:set-custom-field`
|
|
1
|
+
// CustomFieldsFormSection — extension-section component for entityEdit-
|
|
2
|
+
// screens. Loads the tenant's fieldDefinition list, filters it to the
|
|
3
|
+
// host entity, renders a typed input per definition, and dispatches
|
|
4
|
+
// `custom-fields:write:set-custom-field` for each non-empty value on save.
|
|
5
5
|
//
|
|
6
6
|
// Mount via createKumikoApp({ clientFeatures: [customFieldsClient()] })
|
|
7
|
-
// —
|
|
8
|
-
//
|
|
9
|
-
// `component: { react: { __component: CUSTOM_FIELDS_FORM_EXTENSION_NAME } }
|
|
10
|
-
// referenziert.
|
|
7
|
+
// — the clientFeature factory registers this component under the name
|
|
8
|
+
// `CustomFieldsFormSection`, which the app references in the screen schema
|
|
9
|
+
// via `component: { react: { __component: CUSTOM_FIELDS_FORM_EXTENSION_NAME } }`.
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
12
|
type ExtensionSubmitResult,
|
|
@@ -40,10 +39,10 @@ export function CustomFieldsFormSection({
|
|
|
40
39
|
}: {
|
|
41
40
|
readonly entityName: string;
|
|
42
41
|
readonly entityId: string | null;
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
42
|
+
/** The entity's previously saved customField values, passed through from the
|
|
43
|
+
* detail row. Without them, the section would be write-only: the inputs
|
|
44
|
+
* would not show existing values while editing. `pending` tracks only
|
|
45
|
+
* changes, so the Save button remains disabled until the first edit. */
|
|
47
46
|
readonly initialValues?: Readonly<Record<string, unknown>>;
|
|
48
47
|
}): ReactNode {
|
|
49
48
|
const { Banner, Button, Field, Input, Text } = usePrimitives();
|
|
@@ -58,11 +57,11 @@ export function CustomFieldsFormSection({
|
|
|
58
57
|
const [saving, setSaving] = useState(false);
|
|
59
58
|
const [errorKey, setErrorKey] = useState<string | null>(null);
|
|
60
59
|
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// false. Dirty
|
|
64
|
-
//
|
|
65
|
-
//
|
|
60
|
+
// Computed before the early returns because useExtensionFormSubmit (a Hook)
|
|
61
|
+
// must run before them. matchingFields is [] while loading, so dirty remains
|
|
62
|
+
// false. Dirty means differing from the SAVED value (not from ""); otherwise
|
|
63
|
+
// clearing an existing value would be invisible and skipped instead of
|
|
64
|
+
// cleared.
|
|
66
65
|
const matchingFields = (query.data?.rows ?? [])
|
|
67
66
|
.filter((f) => f.entityName === entityName)
|
|
68
67
|
.slice()
|
|
@@ -75,9 +74,10 @@ export function CustomFieldsFormSection({
|
|
|
75
74
|
});
|
|
76
75
|
const dirty = changedFields.length > 0;
|
|
77
76
|
|
|
78
|
-
//
|
|
79
|
-
// (
|
|
80
|
-
//
|
|
77
|
+
// Writes all changed fields via set/clear. Used by the composed submit
|
|
78
|
+
// (the main form calls the handler after the entity write) and by the
|
|
79
|
+
// standalone button when the section is mounted without a surrounding
|
|
80
|
+
// composed form.
|
|
81
81
|
const flushChanges = async (targetEntityId: string): Promise<ExtensionSubmitResult> => {
|
|
82
82
|
for (const field of changedFields) {
|
|
83
83
|
const raw = pending[field.fieldKey] ?? "";
|
|
@@ -105,9 +105,9 @@ export function CustomFieldsFormSection({
|
|
|
105
105
|
return { isSuccess: true };
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
-
// composed =
|
|
109
|
-
//
|
|
110
|
-
//
|
|
108
|
+
// composed = inside an entityEdit form, so there is no separate Save button;
|
|
109
|
+
// the section writes along with the main save. Outside a composed form
|
|
110
|
+
// (composed === false), the standalone button remains available.
|
|
111
111
|
const composed = useExtensionFormSubmit({
|
|
112
112
|
dirty,
|
|
113
113
|
onSubmit: (ctx) => flushChanges(ctx.entityId),
|
|
@@ -236,9 +236,9 @@ function coerceValue(type: string, raw: string): unknown {
|
|
|
236
236
|
return raw;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
//
|
|
240
|
-
//
|
|
241
|
-
//
|
|
239
|
+
// Inverse of coerceValue: converts a stored jsonb value to the string form
|
|
240
|
+
// expected by the input. number/boolean/date/text are represented as their
|
|
241
|
+
// inputs expect; missing values become "".
|
|
242
242
|
function displayValue(type: string, value: unknown): string {
|
|
243
243
|
if (value === undefined || value === null) return "";
|
|
244
244
|
if (type === "boolean") return value === true ? "true" : "false";
|
|
@@ -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;
|