@cosmicdrift/kumiko-bundled-features 0.385.0 → 0.387.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.js +0 -2
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-renderer/headless";
|
|
3
3
|
// Export section (Art. 20) — the one part of user-data-rights' privacy-center
|
|
4
|
-
// screen that stays custom
|
|
4
|
+
// screen that stays custom. Registered as an EditExtensionSection
|
|
5
5
|
// component (see web/client-plugin.tsx); the projectionDetail screen
|
|
6
6
|
// (feature.ts) supplies the surrounding Section chrome (title, testId), so
|
|
7
7
|
// this component renders only its own body content.
|
|
@@ -15,18 +15,19 @@ import { postWithDownload } from "@cosmicdrift/kumiko-renderer/web";
|
|
|
15
15
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
16
16
|
import { useEffect, useState } from "react";
|
|
17
17
|
import { EXPORT_JOB_STATUS, UserDataRightsHandlers, UserDataRightsQueries, } from "./constants.js";
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// The export job runs asynchronously (worker-Lane-Cron, ~1 Min). While it is
|
|
19
|
+
// pending/running, the screen polls its status so the download appears without
|
|
20
|
+
// a manual reload.
|
|
21
21
|
const EXPORT_POLL_MS = 4000;
|
|
22
|
-
// Dispatcher
|
|
23
|
-
//
|
|
22
|
+
// Dispatcher failures include i18nKey only when the handler sets one; read it
|
|
23
|
+
// at the boundary with a generic fallback.
|
|
24
24
|
function failureKey(error) {
|
|
25
25
|
const key = propertyOf(error, "i18nKey");
|
|
26
26
|
return typeof key === "string" ? key : "userDataRights.privacyCenter.errors.generic";
|
|
27
27
|
}
|
|
28
|
-
//
|
|
29
|
-
//
|
|
28
|
+
// Only the date portion of the raw ISO instant is relevant; use a string slice
|
|
29
|
+
// instead of the Date API (no-date-api-Guard) for universal support. Empty/null
|
|
30
|
+
// values become "—".
|
|
30
31
|
export function formatDate(iso) {
|
|
31
32
|
if (!iso)
|
|
32
33
|
return EMPTY_VALUE_PLACEHOLDER;
|
|
@@ -65,10 +66,10 @@ export function ExportSection() {
|
|
|
65
66
|
setStatus({ kind: "idle" });
|
|
66
67
|
void statusQuery.refetch?.();
|
|
67
68
|
};
|
|
68
|
-
// Download
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// attachment →
|
|
69
|
+
// Download runs through the dispatcher (which supplies X-CSRF-Token) instead of
|
|
70
|
+
// an <a>-navigation: download-by-job returns a signed URL, which
|
|
71
|
+
// postWithDownload navigates the browser to (content-disposition:
|
|
72
|
+
// attachment → triggers a download).
|
|
72
73
|
const downloadExport = async (jobId) => {
|
|
73
74
|
const err = await postWithDownload(dispatcher, UserDataRightsQueries.downloadByJob, { jobId });
|
|
74
75
|
if (err)
|
|
@@ -82,7 +83,7 @@ export function ExportSection() {
|
|
|
82
83
|
const failed = job?.status === EXPORT_JOB_STATUS.Failed;
|
|
83
84
|
// While the job is running: poll until Done/Failed, then auto-stop.
|
|
84
85
|
const refetch = statusQuery.refetch;
|
|
85
|
-
// kumiko-lint-ignore no-raw-hooks
|
|
86
|
+
// kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
|
|
86
87
|
useEffect(() => {
|
|
87
88
|
if (!inProgress || !refetch)
|
|
88
89
|
return;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from "react";
|
|
2
2
|
export type PublicDeletionRoutes = {
|
|
3
|
-
/** Login-
|
|
3
|
+
/** Login-free route for the email request screen (e.g. "/account/delete"). */
|
|
4
4
|
readonly requestPath: string;
|
|
5
|
-
/** Login-
|
|
5
|
+
/** Login-free route for token confirmation; path of deletionVerifyUrl. */
|
|
6
6
|
readonly confirmPath: string;
|
|
7
|
-
/**
|
|
8
|
-
* defaultShell). Apps
|
|
7
|
+
/** Shell around the screen card. Default: full-screen centered (like the auth-
|
|
8
|
+
* defaultShell). Apps can provide their own shell (e.g. a marketing header). */
|
|
9
9
|
readonly shell?: (screen: ReactNode) => ReactNode;
|
|
10
10
|
};
|
|
11
11
|
export declare function makePublicDeletionGate(routes: PublicDeletionRoutes): ComponentType<{
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// RequestAccountDeletionScreen —
|
|
3
|
-
// → user-data-rights:write:request-deletion-by-email. Enumeration-safe:
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// RequestAccountDeletionScreen — anonymous Apex screen, step 1: email form
|
|
3
|
+
// → user-data-rights:write:request-deletion-by-email. Enumeration-safe: always
|
|
4
|
+
// shows a "If an account exists, the email is on its way" confirmation, even
|
|
5
|
+
// when the server has determined internally that the email does not exist.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
// createPublicSurface;
|
|
7
|
+
// The app mounts this screen at an Apex route (e.g. /delete-account) via
|
|
8
|
+
// createPublicSurface; the page shell provides the surrounding chrome.
|
|
9
9
|
import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
const REQUEST_BY_EMAIL = "user-data-rights:write:request-deletion-by-email";
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* - Reserved-Names: "." / ".." / "..." → "file"
|
|
3
|
+
* Sanitizes a user-provided fileName for use as a ZIP-internal-path suffix.
|
|
4
|
+
* - Path traversal: "../../etc/passwd" → "file.etc_passwd"
|
|
5
|
+
* - Null bytes: "report\x00.pdf" → "report_.pdf"
|
|
6
|
+
* - Path separators: "sub/dir/file.txt" → "sub_dir_file.txt"
|
|
7
|
+
* - Reserved names: "." / ".." / "..." → "file"
|
|
9
8
|
* - Empty input: "" / null / undef → "unnamed"
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* - Excessive length: long strings are truncated to
|
|
10
|
+
* MAX_SANITIZED_BASENAME_LENGTH
|
|
11
|
+
* (the extension is preserved when present)
|
|
12
|
+
* - Unicode: non-ASCII characters → underscores. Leading stripping
|
|
13
|
+
* can also cause all-Unicode names to become "file".
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* The output is guaranteed to be non-empty, contain no path separators, obey
|
|
16
|
+
* the maximum length, and contain no `..` sequence.
|
|
17
17
|
*/
|
|
18
18
|
export declare function sanitizeZipFilename(raw: string): string;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Computes the ZIP-internal path for a fileRef. Layout:
|
|
21
21
|
* files/<tenantId>/<fileRefId>-<sanitized-fileName>
|
|
22
22
|
*
|
|
23
|
-
* tenantId
|
|
24
|
-
* sanitizeZipFilename.
|
|
23
|
+
* tenantId and fileRefId have UUID shapes and are safe; fileName is passed
|
|
24
|
+
* through sanitizeZipFilename. Path traversal is guaranteed to be excluded.
|
|
25
25
|
*/
|
|
26
26
|
export declare function buildFileRefZipPath(args: {
|
|
27
27
|
readonly tenantId: TenantId;
|
|
@@ -1,65 +1,66 @@
|
|
|
1
|
-
// Shared helper
|
|
1
|
+
// Shared helper for computing ZIP paths from fileRefs.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// 1. bundle.json:
|
|
5
|
-
//
|
|
6
|
-
// 2. ZIP
|
|
3
|
+
// The bundle has two views of the same fileRefs:
|
|
4
|
+
// 1. bundle.json: A flat list with `zipPath` for each fileRef. Reader
|
|
5
|
+
// tools can use this to link JSON to files/-paths.
|
|
6
|
+
// 2. ZIP entries: Bytes are stored under exactly these `zipPath` keys.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// run-export-jobs's bundleToZipEntries
|
|
11
|
-
// Keys.
|
|
8
|
+
// To keep both views synchronized, path computation lives EXACTLY ONCE here.
|
|
9
|
+
// run-user-export fills zipPath in the fileRef item, and
|
|
10
|
+
// run-export-jobs's bundleToZipEntries uses the same paths as entry keys.
|
|
12
11
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* (PKWARE
|
|
16
|
-
*
|
|
12
|
+
* Maximum length of the sanitized fileName without its extension. Realistic
|
|
13
|
+
* filenames are <50; 100 is a safe limit for ZIP compatibility
|
|
14
|
+
* (the PKWARE spec has no hard limit, but many readers struggle with
|
|
15
|
+
* extremely long names).
|
|
17
16
|
*/
|
|
18
17
|
const MAX_SANITIZED_BASENAME_LENGTH = 100;
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* relative
|
|
19
|
+
* Allowed filename chars: alphanumerics, dot, dash, underscore. Everything
|
|
20
|
+
* else is replaced with an underscore. This excludes path separators (`/`,
|
|
21
|
+
* `\`) and null bytes in particular; relative traversal (`..`) is handled
|
|
22
|
+
* by the basename and leading-dot rules below.
|
|
23
23
|
*/
|
|
24
24
|
const FILENAME_SAFE_CHARS = /[^a-zA-Z0-9._-]/g;
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* -
|
|
29
|
-
* -
|
|
30
|
-
* -
|
|
31
|
-
* - Reserved-Names: "." / ".." / "..." → "file"
|
|
26
|
+
* Sanitizes a user-provided fileName for use as a ZIP-internal-path suffix.
|
|
27
|
+
* - Path traversal: "../../etc/passwd" → "file.etc_passwd"
|
|
28
|
+
* - Null bytes: "report\x00.pdf" → "report_.pdf"
|
|
29
|
+
* - Path separators: "sub/dir/file.txt" → "sub_dir_file.txt"
|
|
30
|
+
* - Reserved names: "." / ".." / "..." → "file"
|
|
32
31
|
* - Empty input: "" / null / undef → "unnamed"
|
|
33
|
-
* -
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
32
|
+
* - Excessive length: long strings are truncated to
|
|
33
|
+
* MAX_SANITIZED_BASENAME_LENGTH
|
|
34
|
+
* (the extension is preserved when present)
|
|
35
|
+
* - Unicode: non-ASCII characters → underscores. Leading stripping
|
|
36
|
+
* can also cause all-Unicode names to become "file".
|
|
37
37
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
38
|
+
* The output is guaranteed to be non-empty, contain no path separators, obey
|
|
39
|
+
* the maximum length, and contain no `..` sequence.
|
|
40
40
|
*/
|
|
41
41
|
export function sanitizeZipFilename(raw) {
|
|
42
42
|
if (raw === undefined || raw === null || raw === "")
|
|
43
43
|
return "unnamed";
|
|
44
|
-
//
|
|
44
|
+
// Extract the extension (the last ".X" where X contains no ".").
|
|
45
45
|
const lastDot = raw.lastIndexOf(".");
|
|
46
46
|
const hasExt = lastDot > 0 && lastDot < raw.length - 1;
|
|
47
47
|
const baseName = hasExt ? raw.slice(0, lastDot) : raw;
|
|
48
48
|
const extension = hasExt ? raw.slice(lastDot + 1) : "";
|
|
49
49
|
const safeBase = collapseUnsafe(baseName).slice(0, MAX_SANITIZED_BASENAME_LENGTH);
|
|
50
50
|
const safeExt = collapseUnsafe(extension).slice(0, 20);
|
|
51
|
-
// Empty
|
|
51
|
+
// Empty or all-underscore input → "file" as a reproducible fallback.
|
|
52
52
|
const finalBase = safeBase.length === 0 ? "file" : safeBase;
|
|
53
53
|
return safeExt.length > 0 ? `${finalBase}.${safeExt}` : finalBase;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
* 1. Replace
|
|
58
|
-
* 2. Collapse `..` (
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
56
|
+
* Three-step sanitization:
|
|
57
|
+
* 1. Replace everything except [a-zA-Z0-9._-] with "_".
|
|
58
|
+
* 2. Collapse `..` (or more) to "_"—this prevents `..` from surviving
|
|
59
|
+
* sanitization (for example, when the input contains only dots and
|
|
60
|
+
* slashes).
|
|
61
|
+
* 3. Strip leading [._-]+—this prevents hidden-file patterns, empty
|
|
62
|
+
* basenames, and leading segments that would consist entirely of
|
|
63
|
+
* underscores after the first two steps.
|
|
63
64
|
*/
|
|
64
65
|
function collapseUnsafe(s) {
|
|
65
66
|
let out = s.replace(FILENAME_SAFE_CHARS, "_");
|
|
@@ -68,11 +69,11 @@ function collapseUnsafe(s) {
|
|
|
68
69
|
return out;
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
|
-
*
|
|
72
|
+
* Computes the ZIP-internal path for a fileRef. Layout:
|
|
72
73
|
* files/<tenantId>/<fileRefId>-<sanitized-fileName>
|
|
73
74
|
*
|
|
74
|
-
* tenantId
|
|
75
|
-
* sanitizeZipFilename.
|
|
75
|
+
* tenantId and fileRefId have UUID shapes and are safe; fileName is passed
|
|
76
|
+
* through sanitizeZipFilename. Path traversal is guaranteed to be excluded.
|
|
76
77
|
*/
|
|
77
78
|
export function buildFileRefZipPath(args) {
|
|
78
79
|
const safeName = sanitizeZipFilename(args.fileName);
|
|
@@ -10,23 +10,23 @@ import { notificationPreferenceDeleteHook, notificationPreferenceExportHook, } f
|
|
|
10
10
|
import { tenantInvitationDeleteHook, tenantInvitationExportHook, } from "./hooks/tenant-invitation.userdata-hook.js";
|
|
11
11
|
import { userDeleteHook, userExportHook } from "./hooks/user.userdata-hook.js";
|
|
12
12
|
import { userSessionDeleteHook, userSessionExportHook, } from "./hooks/user-session.userdata-hook.js";
|
|
13
|
-
// user-data-rights-defaults — Default
|
|
14
|
-
// `user`
|
|
13
|
+
// user-data-rights-defaults — Default hooks for the core entities
|
|
14
|
+
// `user` and `fileRef`.
|
|
15
15
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
16
|
+
// Architectural decision: user-data-rights itself cannot call
|
|
17
|
+
// r.requires({ features: ["user", "files"] }) + r.useExtension(EXT_USER_DATA, ...)
|
|
18
|
+
// because it provides EXT_USER_DATA itself (the boot validator rejects
|
|
19
|
+
// self-extension). The solution is a third, optionally mountable feature
|
|
20
|
+
// that requires both sources and makes the useExtension calls.
|
|
21
21
|
//
|
|
22
|
-
// App
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
22
|
+
// App authors can omit this feature if they want to register custom hooks
|
|
23
|
+
// instead (for example, "anonymize should hard-delete the user row" — an
|
|
24
|
+
// app-specific compliance decision). The default implementation covers 95%
|
|
25
|
+
// of apps.
|
|
26
26
|
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
27
|
+
// This follows the file-foundation + file-provider-s3 pattern (separate
|
|
28
|
+
// plugin features): user/files do not define their own hooks because that
|
|
29
|
+
// would create circular requires.
|
|
30
30
|
// Binary storage for the fileRef delete-hook is resolved at run time from the
|
|
31
31
|
// mounted file-foundation via ctx.buildStorageProvider (injected by the forget
|
|
32
32
|
// orchestrator) — no provider is captured here, so a single app-wide store and
|
|
@@ -78,7 +78,7 @@ export function createUserDataRightsDefaultsFeature() {
|
|
|
78
78
|
export: configValueExportHook,
|
|
79
79
|
delete: configValueDeleteHook,
|
|
80
80
|
});
|
|
81
|
-
// Events-only aggregates
|
|
81
|
+
// Events-only aggregates: export reads the projected rows, the
|
|
82
82
|
// delete hooks are deliberate no-ops — erasure happens via crypto-
|
|
83
83
|
// shredding (forget erases the user's DEK; recipientAddress / job
|
|
84
84
|
// payload become unreadable in events AND rows).
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { appendEventInTenantDb, getStreamVersionInTenantDb, } from "@cosmicdrift/kumiko-framework/event-store";
|
|
2
2
|
import { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, deliveryAttemptsTable, } from "../../delivery/index.js";
|
|
3
3
|
import { featureMounted } from "./feature-mounted.js";
|
|
4
|
-
// userData-Hooks for delivery's attempt log
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// the export runner's central decrypt sweep resolves to plaintext (or
|
|
8
|
-
// [[erased]] after a forget).
|
|
4
|
+
// userData-Hooks for delivery's attempt log. deliveryAttempt is an events-only aggregate — the
|
|
5
|
+
// export reads the projected rows; recipientAddress may be ciphertext (kumiko-pii:), which the
|
|
6
|
+
// export runner's central decrypt sweep resolves to plaintext (or [[erased]] after a forget).
|
|
9
7
|
export const deliveryAttemptExportHook = async (ctx) => {
|
|
10
8
|
if (!featureMounted(ctx, "delivery"))
|
|
11
9
|
return null;
|
|
@@ -10,66 +10,62 @@ const ERROR_CONTEXT = "user-data-rights-defaults:fileRef";
|
|
|
10
10
|
// writes are wiped/resurrected on rebuild — the Art.17 hole this fixes. Bounded:
|
|
11
11
|
// per-user forget flows are rare, so per-row events are acceptable.
|
|
12
12
|
const crud = createEventStoreExecutor(fileRefsTable, fileRefEntity, { entityName: "fileRef" });
|
|
13
|
-
//
|
|
13
|
+
// User-data hook for the fileRef entity.
|
|
14
14
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
15
|
+
// The export hook returns metadata for all of the user's FileRefs, with the
|
|
16
|
+
// subject resolved through insertedById. Storage-provider binary streams are
|
|
17
|
+
// not included directly; signed download URLs package them into the ZIP
|
|
18
|
+
// separately.
|
|
19
19
|
//
|
|
20
|
-
//
|
|
20
|
+
// The delete hook removes the fileRef row and binary:
|
|
21
21
|
// "delete": storageProvider.delete() per file + row hard-delete — but
|
|
22
22
|
// ONLY for rows whose field is marked as PII of the person
|
|
23
|
-
// (isPersonalFileRow
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
// "anonymize": insertedById=null
|
|
29
|
-
// point at it; person-link removed)
|
|
23
|
+
// (isPersonalFileRow). All other rows (business/tenant data,
|
|
24
|
+
// no resolvable field, no annotation) go through
|
|
25
|
+
// severPersonLink instead, even when the entity strategy is
|
|
26
|
+
// "delete" — the uploader axis (insertedById) is not the
|
|
27
|
+
// subject axis.
|
|
28
|
+
// "anonymize": insertedById=null; row and binary survive (FK refs can still
|
|
29
|
+
// point at it; person-link removed). This applies to ALL rows
|
|
30
30
|
// when a retention override on fileRef (anonymize or
|
|
31
31
|
// blockDelete, e.g. a statutory retention duty) sets the
|
|
32
32
|
// strategy, regardless of the field.
|
|
33
33
|
//
|
|
34
|
-
// **Provider
|
|
35
|
-
// `ctx.buildStorageProvider(ctx.tenantId)
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
34
|
+
// **Provider resolution:** the provider is obtained at runtime from
|
|
35
|
+
// `ctx.buildStorageProvider(ctx.tenantId)`. The forget orchestrator builds it
|
|
36
|
+
// from the mounted file-foundation, using the SAME store as upload and export
|
|
37
|
+
// (delete-target == upload-target by construction). No provider is captured at
|
|
38
|
+
// mount time.
|
|
39
39
|
//
|
|
40
|
-
// **
|
|
41
|
-
// 1. Resolution
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
// Rollback" der Sprint-2-Atomicity bleibt gewahrt: nur DIESE Sub-Tx rollt
|
|
54
|
-
// zurueck. Der anonymize-Pfad behaelt Row+binary, hat nichts zu schlucken.
|
|
40
|
+
// **Two error classes are handled differently:**
|
|
41
|
+
// 1. Resolution fails (no provider configured / configResolver missing) →
|
|
42
|
+
// NOT fail-closed: warn per invocation and perform a row-only delete. A
|
|
43
|
+
// misconfigured store must not permanently block the Art. 17 deletion;
|
|
44
|
+
// the boot guard exposes the misconfiguration, and binaries are removed
|
|
45
|
+
// once a provider exists.
|
|
46
|
+
// 2. Binary DELETE fails even though a provider exists → FAIL-CLOSED: the
|
|
47
|
+
// hook throws after the loop, the per-user sub-transaction rolls back,
|
|
48
|
+
// the user remains DeletionRequested, and the next run retries (delete is
|
|
49
|
+
// idempotent → converges). Swallowing the error and deleting the row would
|
|
50
|
+
// mark erasure as "done" while leaving the bytes behind. Only this
|
|
51
|
+
// sub-transaction rolls back; there is no global rollback. The anonymize
|
|
52
|
+
// path retains the row and binary, so it has no error to swallow.
|
|
55
53
|
//
|
|
56
|
-
// Caveat: hard-delete via deleteMany
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// bounded; ein executor.purge-API folgt mit dem trashed-files-GC.
|
|
54
|
+
// Caveat: hard-delete via deleteMany emits no fileRef.deleted event, so
|
|
55
|
+
// storage-tracking does not decrement. If the files being deleted were not
|
|
56
|
+
// soft-deleted first, `tenant_storage_usage` remains inflated. Forget flows are
|
|
57
|
+
// rare and bounded; an executor.purge API will follow with trashed-files GC.
|
|
61
58
|
export const fileRefExportHook = async (ctx) => {
|
|
62
|
-
// isDeleted:false — soft-deleted (trashed)
|
|
63
|
-
//
|
|
59
|
+
// isDeleted:false — soft-deleted (trashed) files are excluded from the
|
|
60
|
+
// export bundle. The forget hook below still processes them.
|
|
64
61
|
const rawRows = await ctx.db.selectMany(fileRefsTable, {
|
|
65
62
|
tenantId: ctx.tenantId,
|
|
66
63
|
insertedById: ctx.userId,
|
|
67
64
|
isDeleted: false,
|
|
68
65
|
});
|
|
69
|
-
// @cast-boundary db-row: drizzle
|
|
70
|
-
// (framework-customType).
|
|
71
|
-
// .toString()
|
|
72
|
-
// Date.
|
|
66
|
+
// @cast-boundary db-row: drizzle returns insertedAt as an Instant
|
|
67
|
+
// (framework-customType). JSON export requires a string —
|
|
68
|
+
// .toString() works for both Temporal.Instant and Date.
|
|
73
69
|
const rows = rawRows.map((r) => {
|
|
74
70
|
const row = r; // @cast-boundary recursive-walk
|
|
75
71
|
return {
|
|
@@ -92,9 +88,8 @@ export const fileRefExportHook = async (ctx) => {
|
|
|
92
88
|
size: r.size,
|
|
93
89
|
insertedAt: r.insertedAt,
|
|
94
90
|
})),
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
// UserDataExportSnippet.fileRefs).
|
|
91
|
+
// The fileRefs list is passed to the storage provider, which generates
|
|
92
|
+
// signed URLs and adds the files to the ZIP.
|
|
98
93
|
fileRefs: rows.map((r) => ({
|
|
99
94
|
fileRefId: r.id,
|
|
100
95
|
storageKey: r.storageKey,
|
|
@@ -119,7 +114,7 @@ async function resolveProvider(ctx) {
|
|
|
119
114
|
return undefined;
|
|
120
115
|
}
|
|
121
116
|
}
|
|
122
|
-
// Per-row Art.17 decision
|
|
117
|
+
// Per-row Art.17 decision: whether THIS file's field
|
|
123
118
|
// carries personal data of the forgotten person, or is business/tenant data
|
|
124
119
|
// that merely loses its uploader-attribution. insertedById names who
|
|
125
120
|
// UPLOADED the file, not whose data it is — a dealer's vehicle photo
|
|
@@ -138,8 +133,7 @@ function isPersonalPiiField(field) {
|
|
|
138
133
|
("userOwned" in field && field.userOwned !== undefined) ||
|
|
139
134
|
("recordOwned" in field && field.recordOwned === true));
|
|
140
135
|
}
|
|
141
|
-
// Three cases the field-lookup itself can't resolve
|
|
142
|
-
// the non-resolvable cases):
|
|
136
|
+
// Three cases the field-lookup itself can't resolve:
|
|
143
137
|
// 1. Unattached upload (entityType/fieldName both null) → hard-delete: a
|
|
144
138
|
// file with no entity binding belongs to nobody but its uploader.
|
|
145
139
|
// 2. Field exists but carries no PII annotation → anonymize (the
|
|
@@ -211,7 +205,7 @@ export const fileRefDeleteHook = async (ctx, strategy) => {
|
|
|
211
205
|
return;
|
|
212
206
|
}
|
|
213
207
|
// strategy="delete" decides PER ROW based on the field, not uniformly
|
|
214
|
-
//
|
|
208
|
+
// only rows whose field is marked as PII of the person (or
|
|
215
209
|
// unattached, see isPersonalFileRow) take the hard path. Everything else
|
|
216
210
|
// only loses the uploader link.
|
|
217
211
|
const personalRows = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jobRunsTable } from "../../jobs/index.js";
|
|
2
2
|
import { featureMounted } from "./feature-mounted.js";
|
|
3
|
-
// userData-Hooks for the jobs run log
|
|
3
|
+
// userData-Hooks for the jobs run log.
|
|
4
4
|
// Job runs live on the SYSTEM tenant regardless of who triggered them, so
|
|
5
5
|
// the export filters by triggeredById only — Art. 15 covers everything the
|
|
6
6
|
// user caused, across tenants. payload may be ciphertext (kumiko-pii:); the
|
|
@@ -27,6 +27,6 @@ export const jobRunExportHook = async (ctx) => {
|
|
|
27
27
|
export const jobRunDeleteHook = async () => {
|
|
28
28
|
// Deliberate no-op: erasure runs via crypto-shredding — the forget pipeline
|
|
29
29
|
// erases the triggering user's DEK, which makes the payload unreadable in
|
|
30
|
-
// BOTH the append-only events and the projected rows
|
|
30
|
+
// BOTH the append-only events and the projected rows. triggeredById
|
|
31
31
|
// itself is a pseudonymous fk (plaintext by design, like config.userId).
|
|
32
32
|
};
|
|
@@ -9,7 +9,7 @@ import { featureMounted } from "./feature-mounted.js";
|
|
|
9
9
|
// the forget verb.
|
|
10
10
|
//
|
|
11
11
|
// The delivery ATTEMPTS log is covered separately: export via
|
|
12
|
-
// delivery-attempt.userdata-hook.ts, erasure via crypto-shredding
|
|
12
|
+
// delivery-attempt.userdata-hook.ts, erasure via crypto-shredding.
|
|
13
13
|
const crud = createEventStoreExecutor(notificationPreferencesTable, notificationPreferenceEntity, {
|
|
14
14
|
entityName: "notification-preference",
|
|
15
15
|
});
|
|
@@ -3,9 +3,9 @@ import { featureMounted } from "./feature-mounted.js";
|
|
|
3
3
|
// userData-Hooks for the sessions feature's user-session rows (ip, userAgent).
|
|
4
4
|
//
|
|
5
5
|
// user-session is an unmanaged direct-write store (no event stream, excluded
|
|
6
|
-
// from projection rebuilds
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// from projection rebuilds, see sessions/feature.ts), so a direct DELETE is
|
|
7
|
+
// legal here and survives rebuilds; the executor path the ES entities use does
|
|
8
|
+
// not apply.
|
|
9
9
|
//
|
|
10
10
|
// Both forget strategies hard-delete: a session row without its user is
|
|
11
11
|
// worthless (revocation audit trail loses its subject), and ip/userAgent are
|