@cosmicdrift/kumiko-bundled-features 0.386.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/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,9 +1,9 @@
|
|
|
1
1
|
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { createEntity, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
// Audit
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// Audit trail for rejected download attempts.
|
|
4
|
+
// Writes one row per 4xx response on the download-by-{token,job} path, allowing the DPO
|
|
5
|
+
// to detect brute-force probing and anomalies such as many invalid attempts from one IP.
|
|
6
|
+
// Successful downloads are recorded in download-token.lastUsedAt instead.
|
|
7
7
|
export const downloadAttemptEntity = createEntity({
|
|
8
8
|
table: "read_download_attempts",
|
|
9
9
|
idType: "uuid",
|
|
@@ -23,11 +23,11 @@ export const downloadAttemptEntity = createEntity({
|
|
|
23
23
|
personal: false,
|
|
24
24
|
reason: "technical_reference",
|
|
25
25
|
}),
|
|
26
|
-
// Token
|
|
26
|
+
// Token hash for the token path, or NULL for the job path or an unknown token.
|
|
27
27
|
tokenHash: createTextField({ maxLength: 64, personal: false, reason: "technical_reference" }),
|
|
28
|
-
// Job
|
|
28
|
+
// Job ID when the attempt identified one; NULL for an unknown token.
|
|
29
29
|
jobId: createTextField({ personal: false, reason: "technical_reference" }),
|
|
30
|
-
// User
|
|
30
|
+
// User ID for the authenticated job path; NULL for anonymous token-path requests.
|
|
31
31
|
attemptedByUserId: createTextField({ personal: false, reason: "pseudonymous_fk" }),
|
|
32
32
|
// The anonymous token path has no owner, so those rows fall back to the tenant key;
|
|
33
33
|
// find "exact" on ip because list-download-attempts filters by IP.
|
|
@@ -43,10 +43,10 @@ export const downloadAttemptEntity = createEntity({
|
|
|
43
43
|
}),
|
|
44
44
|
attemptedAt: createTimestampField({ required: true }),
|
|
45
45
|
},
|
|
46
|
-
// 90d hardDelete: unbounded growth
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
//
|
|
46
|
+
// 90d hardDelete: unbounded growth would create a disk bomb targeting the system
|
|
47
|
+
// that detects brute-force activity. Brute-force patterns are short-lived (hours to days),
|
|
48
|
+
// while a 90d window covers forensic reviews and quarterly DPO audits.
|
|
49
|
+
// The tenant can extend retention through an override for HR compliance.
|
|
50
50
|
retention: { keepFor: "90d", strategy: "hardDelete", reference: "attemptedAt" },
|
|
51
51
|
});
|
|
52
52
|
export const downloadAttemptsTable = buildEntityTable("downloadAttempt", downloadAttemptEntity);
|
|
@@ -1,40 +1,39 @@
|
|
|
1
1
|
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { createBigIntField, createEntity, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
// Export-Download-Token
|
|
3
|
+
// Export-Download-Token.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// 1. Worker
|
|
7
|
-
//
|
|
8
|
-
// 2. crud.create(downloadTokenEntity, ...)
|
|
9
|
-
// `exportDownloadToken.created`-Event in
|
|
10
|
-
//
|
|
11
|
-
// direct
|
|
12
|
-
// 3. Plain
|
|
13
|
-
//
|
|
14
|
-
// 4.
|
|
15
|
-
//
|
|
5
|
+
// Security token for the download endpoint. Pattern:
|
|
6
|
+
// 1. Worker generates a plain token (32 random bytes, base64url) +
|
|
7
|
+
// hash (SHA256 hex) when flipping to done.
|
|
8
|
+
// 2. crud.create(downloadTokenEntity, ...) emits
|
|
9
|
+
// `exportDownloadToken.created`-Event in the event store. The DB row
|
|
10
|
+
// is written synchronously via the projection (Marten pattern, NOT
|
|
11
|
+
// direct INSERT).
|
|
12
|
+
// 3. Plain token remains in worker memory + is passed via
|
|
13
|
+
// RunExportJobsResult to the notification flow. NEVER plain in DB.
|
|
14
|
+
// 4. The download endpoint hashes the incoming token + looks up the
|
|
15
|
+
// hash entry. Constant-time comparison against timing attacks.
|
|
16
16
|
//
|
|
17
|
-
// **Multi-use within TTL
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
17
|
+
// **Multi-use within TTL**: Token is not "consumed" on download.
|
|
18
|
+
// Multiple downloads until expiresAt are allowed — better UX for connection
|
|
19
|
+
// interruptions, no forced re-export. Pattern matches Google Takeout (7d)
|
|
20
|
+
// + Facebook Data Download (4d).
|
|
21
21
|
//
|
|
22
|
-
// **TTL = job.expiresAt** (denormalized,
|
|
23
|
-
// Storage
|
|
24
|
-
// expiresAt + exportStorageCleanupGraceHours.
|
|
25
|
-
// (
|
|
26
|
-
// != null
|
|
22
|
+
// **TTL = job.expiresAt** (denormalized, same value as the job row).
|
|
23
|
+
// Storage cleanup nulls downloadStorageKey after
|
|
24
|
+
// expiresAt + exportStorageCleanupGraceHours. The token row remains
|
|
25
|
+
// (audit trail) — the download endpoint checks job.downloadStorageKey
|
|
26
|
+
// != null before streaming + returns 410 Gone when storage is cleared.
|
|
27
27
|
//
|
|
28
|
-
// **idType: "uuid"**
|
|
29
|
-
//
|
|
28
|
+
// **idType: "uuid"** matches ExportJob — token IDs cross process
|
|
29
|
+
// boundaries (audit events for the DPO, possible re-issue paths).
|
|
30
30
|
export const exportDownloadTokenEntity = createEntity({
|
|
31
31
|
table: "read_export_download_tokens",
|
|
32
32
|
idType: "uuid",
|
|
33
33
|
fields: {
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
// Job gehoeren.
|
|
34
|
+
// Foreign key to export jobs. UNIQUE (see indexes) enforces one token per
|
|
35
|
+
// job. A separate token row keeps token-specific audit fields
|
|
36
|
+
// (`lastUsedAt`/IP/UA) separate from the job.
|
|
38
37
|
jobId: createTextField({
|
|
39
38
|
required: true,
|
|
40
39
|
personal: false,
|
|
@@ -48,22 +47,21 @@ export const exportDownloadTokenEntity = createEntity({
|
|
|
48
47
|
personal: false,
|
|
49
48
|
reason: "technical_reference",
|
|
50
49
|
}),
|
|
51
|
-
//
|
|
50
|
+
// The time the token was issued, when the job was marked done.
|
|
52
51
|
issuedAt: createTimestampField({
|
|
53
52
|
required: true,
|
|
54
53
|
}),
|
|
55
|
-
//
|
|
56
|
-
//
|
|
54
|
+
// The token expires at the same time as `job.expiresAt`; the worker sets both
|
|
55
|
+
// values when marking the job done.
|
|
57
56
|
expiresAt: createTimestampField({
|
|
58
57
|
required: true,
|
|
59
58
|
}),
|
|
60
|
-
// Audit
|
|
61
|
-
//
|
|
62
|
-
//
|
|
59
|
+
// Audit timestamp for the most recent download. NULL means the token has
|
|
60
|
+
// never been downloaded; the endpoint updates it after each successful
|
|
61
|
+
// stream.
|
|
63
62
|
lastUsedAt: createTimestampField({}),
|
|
64
|
-
// Audit
|
|
65
|
-
//
|
|
66
|
-
// (z.B. broken Sync-Tool).
|
|
63
|
+
// Audit count of downloads. `bigInt` accommodates pathological re-download
|
|
64
|
+
// loops, such as those caused by a broken sync tool.
|
|
67
65
|
useCount: createBigIntField({}),
|
|
68
66
|
// Audit: source IP of the last download. Helps the DPO investigate
|
|
69
67
|
// unusual activity ("token was used from 5 different IPs"). Plain
|
|
@@ -83,11 +81,9 @@ export const exportDownloadTokenEntity = createEntity({
|
|
|
83
81
|
reason: "is_business_data",
|
|
84
82
|
}),
|
|
85
83
|
},
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
// in place via update (fw#832) — sonst kollidiert der Projection-
|
|
90
|
-
// Rebuild an genau diesem Index.
|
|
84
|
+
// UNIQUE on `jobId` provides an idempotency backstop: rerunning a completed
|
|
85
|
+
// job must not create a second token aggregate. Re-runs update the existing
|
|
86
|
+
// token in place; otherwise projection rebuilds would collide on this index.
|
|
91
87
|
indexes: [
|
|
92
88
|
{
|
|
93
89
|
unique: true,
|
|
@@ -6,10 +6,10 @@ export declare const EXPORT_JOB_STATUS: {
|
|
|
6
6
|
};
|
|
7
7
|
export type ExportJobStatus = (typeof EXPORT_JOB_STATUS)[keyof typeof EXPORT_JOB_STATUS];
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `expectUniqueViolation
|
|
9
|
+
* Database constraint name for the partial UNIQUE index (one active job per
|
|
10
|
+
* user). This is the single source of truth: request-export.write catches
|
|
11
|
+
* 23505 with this name as race protection, and tests pin it as the
|
|
12
|
+
* `expectUniqueViolation` argument. Renaming it propagates automatically.
|
|
13
13
|
*/
|
|
14
14
|
export declare const ACTIVE_JOB_CONSTRAINT = "read_export_jobs_one_active_per_user";
|
|
15
15
|
export declare const exportJobEntity: import("@cosmicdrift/kumiko-types/fields").EntityDefinition<{
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { buildEntityTable, sql } from "@cosmicdrift/kumiko-framework/db";
|
|
2
2
|
import { createBigIntField, createEntity, createLongTextField, createSelectField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
-
// Export-
|
|
3
|
+
// Export-job lifecycle.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// pickt auf → "running" → erfolgreich "done" + downloadStorageKey gesetzt
|
|
5
|
+
// User triggers `request-export` → ExportJob (status="pending"). The worker
|
|
6
|
+
// picks it up → "running" → on success, "done" + downloadStorageKey set
|
|
8
7
|
// + expiresAt = completedAt + compliance-profile.userRights.exportDownloadTtl
|
|
9
|
-
// (per
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// (configurable per tenant via override, default 7 days). On throw or stale
|
|
9
|
+
// timeout → "failed" with errorMessage. Stale timeout and storage-cleanup
|
|
10
|
+
// grace are also read from the compliance profile.
|
|
12
11
|
//
|
|
13
|
-
// Status
|
|
14
|
-
//
|
|
15
|
-
//
|
|
12
|
+
// Status values are constants—the single source of truth for the worker,
|
|
13
|
+
// application code (`request-export` handler), UI polling banner, and test
|
|
14
|
+
// drift guard.
|
|
16
15
|
export const EXPORT_JOB_STATUS = {
|
|
17
16
|
Pending: "pending",
|
|
18
17
|
Running: "running",
|
|
@@ -20,10 +19,10 @@ export const EXPORT_JOB_STATUS = {
|
|
|
20
19
|
Failed: "failed",
|
|
21
20
|
};
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `expectUniqueViolation
|
|
22
|
+
* Database constraint name for the partial UNIQUE index (one active job per
|
|
23
|
+
* user). This is the single source of truth: request-export.write catches
|
|
24
|
+
* 23505 with this name as race protection, and tests pin it as the
|
|
25
|
+
* `expectUniqueViolation` argument. Renaming it propagates automatically.
|
|
27
26
|
*/
|
|
28
27
|
export const ACTIVE_JOB_CONSTRAINT = "read_export_jobs_one_active_per_user";
|
|
29
28
|
const EXPORT_JOB_STATUS_OPTIONS = [
|
|
@@ -35,46 +34,45 @@ const EXPORT_JOB_STATUS_OPTIONS = [
|
|
|
35
34
|
// **Tenant-agnostic** like userTable — one job per userId across all
|
|
36
35
|
// memberships; the worker iterates cross-tenant via ctx.db.unsafeRaw (same pattern as runForgetCleanup).
|
|
37
36
|
//
|
|
38
|
-
// **Idempotency:** Partial
|
|
39
|
-
// `status IN ('pending', 'running')`.
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
// (Audit-Historie).
|
|
37
|
+
// **Idempotency:** Partial UNIQUE index on `(userId)` WHERE
|
|
38
|
+
// `status IN ('pending', 'running')`. A user with a pending job cannot start
|
|
39
|
+
// a second parallel job—the insert fails with a constraint violation, which
|
|
40
|
+
// the request-export handler catches and uses to return the existing pending
|
|
41
|
+
// job (insert-or-return). This closes the race window. Done/failed jobs can
|
|
42
|
+
// be retained indefinitely per user for audit history.
|
|
45
43
|
//
|
|
46
|
-
// **idType: "uuid"** —
|
|
47
|
-
//
|
|
48
|
-
//
|
|
44
|
+
// **idType: "uuid"** — job IDs cross process boundaries (BullMQ payloads,
|
|
45
|
+
// job-run logger, and audit events for the DPO). Serial IDs are only reliable
|
|
46
|
+
// within one process; UUIDs remain stable across processes.
|
|
49
47
|
export const exportJobEntity = createEntity({
|
|
50
48
|
table: "read_export_jobs",
|
|
51
49
|
idType: "uuid",
|
|
52
50
|
description: "One user's GDPR Art. 20 data-export request and its lifecycle: who asked, from which tenant, the pending/running/done/failed status, the timestamps, the download storage key and expiry, and any error the export worker hit.",
|
|
53
51
|
fields: {
|
|
54
|
-
// Tenant-
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
// (
|
|
58
|
-
//
|
|
52
|
+
// Tenant-agnostic: set when writing because the framework requires a
|
|
53
|
+
// tenant_id column, but ignored at the domain level.
|
|
54
|
+
// No maxLength — follows userTable.id and tenantMembershipsTable.userId
|
|
55
|
+
// (both have no maxLength). The userId shape is platform-wide; here it is
|
|
56
|
+
// only used for storage.
|
|
59
57
|
userId: createTextField({
|
|
60
58
|
required: true,
|
|
61
59
|
searchable: true,
|
|
62
60
|
personal: false,
|
|
63
61
|
reason: "pseudonymous_fk",
|
|
64
62
|
}),
|
|
65
|
-
// **requestedFromTenantId** —
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
63
|
+
// **requestedFromTenantId** — the tenant from which the user submitted the
|
|
64
|
+
// request. This persisted audit path tells the worker which compliance
|
|
65
|
+
// profile applies to the job TTL, stale timeout, and cleanup. This keeps
|
|
66
|
+
// one effective profile per request instead of changing with every
|
|
67
|
+
// cross-tenant click. The tenant is taken from the first click (option a).
|
|
68
|
+
// The column is not simply named "tenantId" to avoid confusion with the
|
|
69
|
+
// framework-generated tenant_id column.
|
|
72
70
|
//
|
|
73
|
-
// **
|
|
74
|
-
//
|
|
75
|
-
// "compliance-profiles:query:for-tenant", {})`),
|
|
76
|
-
// `executor.tenantId
|
|
77
|
-
//
|
|
71
|
+
// **Worker note:** Profile resolution must use `requestedFromTenantId`
|
|
72
|
+
// (`queryAs(systemUserOf(requestedFromTenantId),
|
|
73
|
+
// "compliance-profiles:query:for-tenant", {})`), not
|
|
74
|
+
// `executor.tenantId`; otherwise a job picked up from another tenant
|
|
75
|
+
// context would use the wrong profile.
|
|
78
76
|
requestedFromTenantId: createTextField({
|
|
79
77
|
required: true,
|
|
80
78
|
personal: false,
|
|
@@ -85,36 +83,36 @@ export const exportJobEntity = createEntity({
|
|
|
85
83
|
default: EXPORT_JOB_STATUS.Pending,
|
|
86
84
|
options: EXPORT_JOB_STATUS_OPTIONS,
|
|
87
85
|
}),
|
|
88
|
-
//
|
|
89
|
-
//
|
|
86
|
+
// When the user requested the job. Required because no job row exists
|
|
87
|
+
// without a request.
|
|
90
88
|
requestedAt: createTimestampField({
|
|
91
89
|
required: true,
|
|
92
90
|
sortable: true,
|
|
93
91
|
}),
|
|
94
|
-
//
|
|
95
|
-
//
|
|
92
|
+
// When the worker began processing the job. NULL while `pending`.
|
|
93
|
+
// Stale detection uses this together with
|
|
96
94
|
// compliance-profile.userRights.exportStaleTimeoutMinutes.
|
|
97
95
|
startedAt: createTimestampField({}),
|
|
98
|
-
//
|
|
99
|
-
//
|
|
96
|
+
// When the worker completed the job, successfully or with failure. NULL
|
|
97
|
+
// while `running`.
|
|
100
98
|
completedAt: createTimestampField({}),
|
|
101
|
-
// Storage
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
// signed
|
|
99
|
+
// Storage key of the completed ZIP file. NULL until `done`.
|
|
100
|
+
// The worker sets this and writes the ZIP bytes via
|
|
101
|
+
// storage-provider.write(key).
|
|
102
|
+
// This is not a signed URL—the download endpoint generates the signed URL
|
|
103
|
+
// on demand through the storage provider.
|
|
105
104
|
downloadStorageKey: createTextField({
|
|
106
105
|
maxLength: 500,
|
|
107
106
|
personal: false,
|
|
108
107
|
reason: "technical_reference",
|
|
109
108
|
}),
|
|
110
|
-
//
|
|
109
|
+
// When the download is no longer available. The worker sets
|
|
111
110
|
// `completedAt + compliance-profile.userRights.exportDownloadTtl`
|
|
112
|
-
//
|
|
111
|
+
// when switching to `done`. NULL for pending, running, and failed jobs.
|
|
113
112
|
//
|
|
114
|
-
// Storage
|
|
115
|
-
// `expiresAt + compliance-profile.userRights.exportStorageCleanupGraceHours
|
|
116
|
-
//
|
|
117
|
-
// verbleiben.
|
|
113
|
+
// Storage cleanup requirement: after
|
|
114
|
+
// `expiresAt + compliance-profile.userRights.exportStorageCleanupGraceHours`,
|
|
115
|
+
// a separate pass deletes expired ZIPs so they do not remain on S3.
|
|
118
116
|
expiresAt: createTimestampField({}),
|
|
119
117
|
// Failed-state diagnostics. longText because hook errors with stack
|
|
120
118
|
// traces can run several KB. `reason: "is_business_data"` because
|
|
@@ -123,19 +121,19 @@ export const exportJobEntity = createEntity({
|
|
|
123
121
|
personal: false,
|
|
124
122
|
reason: "is_business_data",
|
|
125
123
|
}),
|
|
126
|
-
// Audit
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
// silent
|
|
124
|
+
// Audit information for operators: the export size. This supports capacity
|
|
125
|
+
// planning and detects pathological cases (a streaming ZIP containing 5 GB
|
|
126
|
+
// of files writes several billion bytes, so integer overflow would cause
|
|
127
|
+
// silent audit drift).
|
|
130
128
|
//
|
|
131
|
-
// bigInt
|
|
132
|
-
//
|
|
129
|
+
// bigInt provides a JS-`number` round trip via mode:"number", safe up to
|
|
130
|
+
// 2^53 ≈ 9 PB and suitable for JSON-based status polling.
|
|
133
131
|
bytesWritten: createBigIntField({}),
|
|
134
132
|
},
|
|
135
|
-
// Partial
|
|
136
|
-
//
|
|
137
|
-
//
|
|
138
|
-
//
|
|
133
|
+
// Partial UNIQUE index: only one active job per user; done/failed history
|
|
134
|
+
// is unlimited. request-export.write uses an application-side pre-check as
|
|
135
|
+
// the primary path and catches this constraint's 23505 as race protection
|
|
136
|
+
// for the <1ms window between fetchOne and crud.create.
|
|
139
137
|
indexes: [
|
|
140
138
|
{
|
|
141
139
|
unique: true,
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Generates a new download token. The plain token is sent to the user by email;
|
|
3
|
+
* the hash is stored in the token database row.
|
|
4
4
|
*
|
|
5
|
-
* Token
|
|
6
|
-
*
|
|
5
|
+
* Token format: 32 random bytes → base64url-encoded (~43 chars). URL-safe for
|
|
6
|
+
* Magic-Link use (no +/= characters that would need to be URL-encoded).
|
|
7
7
|
*/
|
|
8
8
|
export declare function generateDownloadToken(): Promise<{
|
|
9
9
|
readonly plain: string;
|
|
10
10
|
readonly hash: string;
|
|
11
11
|
}>;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* compare-helper).
|
|
13
|
+
* Hashes a plain token into its database representation. In the verification path,
|
|
14
|
+
* the download endpoint hashes the incoming token and looks up the hash in the
|
|
15
|
+
* database. A constant-time string comparison prevents timing attacks; the caller
|
|
16
|
+
* performs it via `crypto.subtle` or a secure comparison helper.
|
|
18
17
|
*/
|
|
19
18
|
export declare function hashDownloadToken(plain: string): Promise<string>;
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Generates a cryptographically secure token to authorize the export ZIP download.
|
|
2
|
+
// Follows the Magic-Link/Bearer-Token pattern with a hash stored in the database:
|
|
2
3
|
//
|
|
3
|
-
//
|
|
4
|
-
// Export-ZIP-Downloads. Pattern matched Magic-Link/Bearer-Token mit DB-
|
|
5
|
-
// gespeichertem Hash:
|
|
6
|
-
//
|
|
7
|
-
// 1. Worker generiert plain-Token (32 byte random base64url) + Hash
|
|
4
|
+
// 1. The worker generates a plain token (32 random bytes, base64url) and its hash
|
|
8
5
|
// (SHA256 hex).
|
|
9
|
-
// 2.
|
|
10
|
-
// 3.
|
|
11
|
-
// 4.
|
|
12
|
-
//
|
|
6
|
+
// 2. The database stores ONLY the hash. The plain token remains in worker memory.
|
|
7
|
+
// 3. The notification step sends the plain token to the user by email.
|
|
8
|
+
// 4. The download endpoint hashes the incoming token and compares it with the
|
|
9
|
+
// database hash using a constant-time comparison to prevent timing attacks.
|
|
13
10
|
//
|
|
14
|
-
// **Multi-use within TTL
|
|
15
|
-
//
|
|
16
|
-
//
|
|
11
|
+
// **Multi-use within TTL:** The token is NOT "consumed" on download, so the user
|
|
12
|
+
// can download repeatedly until expiresAt. This matches Google-Takeout (7d) and
|
|
13
|
+
// Facebook-Data-Download (4d).
|
|
17
14
|
//
|
|
18
15
|
// **Universal Web-Crypto API:** crypto.getRandomValues + crypto.subtle.digest
|
|
19
|
-
//
|
|
20
|
-
//
|
|
16
|
+
// runs identically in Bun, Node 19+, and browsers, avoiding platform-specific
|
|
17
|
+
// imports.
|
|
21
18
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* Generates a new download token. The plain token is sent to the user by email;
|
|
20
|
+
* the hash is stored in the token database row.
|
|
24
21
|
*
|
|
25
|
-
* Token
|
|
26
|
-
*
|
|
22
|
+
* Token format: 32 random bytes → base64url-encoded (~43 chars). URL-safe for
|
|
23
|
+
* Magic-Link use (no +/= characters that would need to be URL-encoded).
|
|
27
24
|
*/
|
|
28
25
|
export async function generateDownloadToken() {
|
|
29
26
|
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
@@ -32,11 +29,10 @@ export async function generateDownloadToken() {
|
|
|
32
29
|
return { plain, hash };
|
|
33
30
|
}
|
|
34
31
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* compare-helper).
|
|
32
|
+
* Hashes a plain token into its database representation. In the verification path,
|
|
33
|
+
* the download endpoint hashes the incoming token and looks up the hash in the
|
|
34
|
+
* database. A constant-time string comparison prevents timing attacks; the caller
|
|
35
|
+
* performs it via `crypto.subtle` or a secure comparison helper.
|
|
40
36
|
*/
|
|
41
37
|
export async function hashDownloadToken(plain) {
|
|
42
38
|
const encoded = new TextEncoder().encode(plain);
|
|
@@ -44,7 +40,7 @@ export async function hashDownloadToken(plain) {
|
|
|
44
40
|
return uint8ArrayToHex(new Uint8Array(digest));
|
|
45
41
|
}
|
|
46
42
|
function uint8ArrayToBase64Url(bytes) {
|
|
47
|
-
// btoa
|
|
43
|
+
// btoa expects a binary string. atob/btoa are universal in Bun, Node, and browsers.
|
|
48
44
|
let binary = "";
|
|
49
45
|
for (let i = 0; i < bytes.length; i++) {
|
|
50
46
|
binary += String.fromCharCode(bytes[i]); // @cast-boundary dynamic-key
|
|
@@ -2,12 +2,12 @@ import { type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
|
2
2
|
import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
|
|
3
3
|
import { type PublicDeletionRoutes } from "./public-deletion-gate.tsx";
|
|
4
4
|
export type UserDataRightsClientOptions = {
|
|
5
|
-
/**
|
|
5
|
+
/** Overrides merged into the default bundles (de/en). */
|
|
6
6
|
readonly translations?: TranslationsByLocale;
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* privacy-center
|
|
10
|
-
*
|
|
7
|
+
/** When set, registers the anonymous (login-free) deletion screens as a
|
|
8
|
+
* gate on the specified paths. If omitted, only the authenticated
|
|
9
|
+
* privacy-center screen is available. Register this client BEFORE the auth
|
|
10
|
+
* client; otherwise, anonymous visitors are redirected to the login screen. */
|
|
11
11
|
readonly publicDeletion?: PublicDeletionRoutes;
|
|
12
12
|
};
|
|
13
13
|
export declare function userDataRightsClient(options?: UserDataRightsClientOptions): ClientFeatureDefinition;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// createKumikoApp({ clientFeatures: [userDataRightsClient()] }); the screen
|
|
7
7
|
// has no own r.nav, the app places it via r.nav.
|
|
8
8
|
//
|
|
9
|
-
//
|
|
9
|
+
// The former `privacyCenter: { showDeletion }` option is gone — a
|
|
10
10
|
// declarative screen is now registered server-side once for all apps, so a
|
|
11
11
|
// client prop can no longer toggle its sections/actions per app. Its
|
|
12
12
|
// replacement is the server-side
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// ConfirmAccountDeletionScreen —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// user-data-rights:write:confirm-deletion-by-token
|
|
2
|
+
// ConfirmAccountDeletionScreen — anonymous Apex screen, step 2. Reads the
|
|
3
|
+
// token from the URL fragment (`#token=…`, never sent to the server, so it does
|
|
4
|
+
// not appear in proxy/access logs) and dispatches
|
|
5
|
+
// user-data-rights:write:confirm-deletion-by-token on confirmation to start the
|
|
6
|
+
// grace period.
|
|
6
7
|
//
|
|
7
|
-
//
|
|
8
|
+
// The app mounts this screen at the deletionVerifyUrl route (for example,
|
|
8
9
|
// /delete-account/confirm) via createPublicSurface.
|
|
9
10
|
import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
10
11
|
import { useState } from "react";
|
|
@@ -13,7 +13,7 @@ export const PRIVACY_CENTER_SCREEN_ID = "privacy-center";
|
|
|
13
13
|
// compliance-profiles' COMPLIANCE_PROFILE_CATALOG_EXTENSION_NAME.
|
|
14
14
|
export const EXPORT_SECTION_EXTENSION_NAME = "UserDataRightsExportSection";
|
|
15
15
|
// enumOption keyPrefix for the privacy-center screen's `status` field
|
|
16
|
-
//
|
|
16
|
+
// pattern — resolves the raw user-lifecycle enum value
|
|
17
17
|
// (active/restricted/deletionRequested/deleted) to a translated label
|
|
18
18
|
// instead of showing the raw string.
|
|
19
19
|
export const STATUS_OPTION_KEY_PREFIX = "userDataRights.privacyCenter.field.status.option.";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// Public exports
|
|
2
|
-
//
|
|
3
|
-
// `@cosmicdrift/kumiko-bundled-features/user-data-rights/web`.
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// Public exports for the browser side of the user-data-rights feature —
|
|
2
|
+
// the anonymous Apex deletion screens. Consumed via the subpath export
|
|
3
|
+
// `@cosmicdrift/kumiko-bundled-features/user-data-rights/web`. The server
|
|
4
|
+
// side (defineFeature, Handler) lives under `.../user-data-rights` and has
|
|
5
|
+
// no React/DOM dependencies.
|
|
6
6
|
export { userDataRightsClient } from "./client-plugin.js";
|
|
7
7
|
export { ConfirmAccountDeletionScreen } from "./confirm-deletion-screen.js";
|
|
8
8
|
export { defaultTranslations } from "./default-translations.js";
|