@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,6 +1,6 @@
|
|
|
1
1
|
// Generic tier-resolver factory. Extracted from the near-identical
|
|
2
|
-
// tier-resolver.ts app copies in show-pony and publicstatus
|
|
3
|
-
//
|
|
2
|
+
// tier-resolver.ts app copies in show-pony and publicstatus — the only
|
|
3
|
+
// per-app variables were the TierName union and its caps/defaults, so
|
|
4
4
|
// both are now factory parameters.
|
|
5
5
|
import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
6
6
|
import { tierAssignmentEntity } from "./entity.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// Trial
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// Row
|
|
1
|
+
// Trial phase: a new tenant receives the features of a higher tier for a grace
|
|
2
|
+
// period starting at its creation date (`inserted_at` of the tier-assignment Row —
|
|
3
|
+
// stable across rebuilds because it comes from the Create Event), regardless of
|
|
4
|
+
// the stored tier. It is derived solely from time: no stored flag, no scheduler,
|
|
5
|
+
// and automatic expiration. The app defines the policy (which tier, how long);
|
|
6
|
+
// the tier-engine applies it in the resolver.
|
|
7
|
+
// Pure millisecond arithmetic on epochMilliseconds, which both sides—the
|
|
8
|
+
// projection Row and Now—provide. No Date and no time zone.
|
|
9
9
|
export function isTrialActive(startedAtEpochMs, nowEpochMs, durationHours) {
|
|
10
10
|
return nowEpochMs < startedAtEpochMs + durationHours * 3_600_000;
|
|
11
11
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Public exports
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `@cosmicdrift/kumiko-bundled-features/tier-engine`
|
|
1
|
+
// Public exports for the browser side of the tier-engine feature. Import via
|
|
2
|
+
// `@cosmicdrift/kumiko-bundled-features/tier-engine/web` — the server side
|
|
3
|
+
// (createTierEngineFeature) is under
|
|
4
|
+
// `@cosmicdrift/kumiko-bundled-features/tier-engine` and has no React deps.
|
|
5
5
|
export { tierEngineClient } from "./client-plugin.js";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//
|
|
1
|
+
// One-time migration tooling for older user event streams.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// Making `user` a systemStream entity means every executor op addresses the
|
|
4
4
|
// stream on SYSTEM_TENANT_ID. Streams created before that live on whichever
|
|
5
|
-
// tenant created them ("scattered"), so
|
|
6
|
-
// against the empty SYSTEM stream. The raw UPDATE
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// tenant created them ("scattered"), so newer writes version-conflict
|
|
6
|
+
// against the empty SYSTEM stream. The raw UPDATE breaks as soon as an
|
|
7
|
+
// aggregate has BOTH a legacy stream and newer SYSTEM events
|
|
8
|
+
// (split stream — e.g. a skipOptimisticLock
|
|
9
9
|
// lifecycle write appended v1 on SYSTEM while v1..n live on the old
|
|
10
10
|
// tenant): retenanting then trips events_aggregate_version_uq.
|
|
11
11
|
//
|
|
@@ -54,12 +54,12 @@ async function migrateAggregate(db, aggregateId) {
|
|
|
54
54
|
WHERE "aggregate_type" = 'user' AND "aggregate_id" = $1::uuid
|
|
55
55
|
ORDER BY "id" ASC
|
|
56
56
|
FOR UPDATE`, [aggregateId]);
|
|
57
|
-
//
|
|
57
|
+
// Negative interim versions — real versions are always >= 1, so
|
|
58
58
|
// nothing can collide with events_aggregate_version_uq mid-migration.
|
|
59
59
|
for (const [i, ev] of events.entries()) {
|
|
60
60
|
await raw.unsafe(`UPDATE "kumiko_events" SET "tenant_id" = $1::uuid, "version" = $2 WHERE "id" = $3`, [SYSTEM_TENANT_ID, -(i + 1), ev.id]);
|
|
61
61
|
}
|
|
62
|
-
//
|
|
62
|
+
// Final contiguous 1..n.
|
|
63
63
|
for (const [i, ev] of events.entries()) {
|
|
64
64
|
await raw.unsafe(`UPDATE "kumiko_events" SET "version" = $1 WHERE "id" = $2`, [i + 1, ev.id]);
|
|
65
65
|
}
|
|
@@ -11,14 +11,14 @@ import { UserErrors } from "../web/constants.js";
|
|
|
11
11
|
const crud = createEventStoreExecutor(userTable, userEntity, { entityName: "user" });
|
|
12
12
|
// Only the Auth features (running as SYSTEM) or a SystemAdmin may create users.
|
|
13
13
|
//
|
|
14
|
-
// Email uniqueness has two layers
|
|
14
|
+
// Email uniqueness has two layers:
|
|
15
15
|
// 1. A pre-flight fetchOne — fast-fails with a friendly error on the
|
|
16
16
|
// common case, but is race-prone on its own: two concurrent requests
|
|
17
17
|
// can both see "no duplicate" and both proceed to crud.create.
|
|
18
18
|
// 2. The real guard is the unique index over email's blind-index column
|
|
19
19
|
// (schema/user.ts). A losing concurrent create hits that constraint
|
|
20
|
-
// and crud.create returns a UniqueViolationError (framework's
|
|
21
|
-
//
|
|
20
|
+
// and crud.create returns a UniqueViolationError (framework's pg-23505
|
|
21
|
+
// mapping) instead of throwing — remapped below to the same
|
|
22
22
|
// emailAlreadyExists shape the pre-flight path returns, so callers see
|
|
23
23
|
// one consistent error regardless of which layer caught the race.
|
|
24
24
|
export const createWrite = defineWriteHandler({
|
|
@@ -89,7 +89,7 @@ export const createWrite = defineWriteHandler({
|
|
|
89
89
|
// schema/user.ts's `read_users_email_unique` (+ its generated `_bidx`
|
|
90
90
|
// pendant) is the actual race-safety net behind the pre-flight check
|
|
91
91
|
// above — a losing concurrent create surfaces here as a generic
|
|
92
|
-
// UniqueViolationError (framework
|
|
92
|
+
// UniqueViolationError (framework pg-23505 mapping). Only the email
|
|
93
93
|
// constraint gets remapped; any other unique_violation on this entity
|
|
94
94
|
// passes through unchanged.
|
|
95
95
|
function isRecord(value) {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* User
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* gleiches Pattern wie ROLES.SystemAdmin).
|
|
2
|
+
* User lifecycle status. This is the single source of truth used by the
|
|
3
|
+
* auth middleware, forget job, and restriction handler instead of duplicated
|
|
4
|
+
* magic strings, following the same pattern as ROLES.SystemAdmin.
|
|
6
5
|
*/
|
|
7
6
|
export declare const USER_STATUS: {
|
|
8
7
|
readonly Active: "active";
|
|
@@ -12,17 +11,18 @@ export declare const USER_STATUS: {
|
|
|
12
11
|
};
|
|
13
12
|
export type UserStatus = (typeof USER_STATUS)[keyof typeof USER_STATUS];
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* Display strings anonymized by userDeleteHook. Constants keep i18n mapping
|
|
15
|
+
* possible and prevent drift. The default is German; app authors can
|
|
16
|
+
* translate it through the i18n system if desired.
|
|
18
17
|
*/
|
|
19
18
|
export declare const USER_DELETED_DISPLAY_NAME = "[Geloescht]";
|
|
20
19
|
export declare const USER_ANONYMIZED_DISPLAY_NAME = "[Anonymisiert]";
|
|
21
20
|
/**
|
|
22
|
-
* Email
|
|
23
|
-
* —
|
|
24
|
-
*
|
|
25
|
-
* `.invalid
|
|
21
|
+
* Email pseudonyms used after forgetting. `<prefix>-<userId>@anonymized.invalid`
|
|
22
|
+
* — the userId suffix is permitted as a pseudo-audit marker for operator
|
|
23
|
+
* tracing; the user ID itself is a UUID, not PII.
|
|
24
|
+
* The `.invalid` TLD is reserved by RFC2606, so the address can never be
|
|
25
|
+
* delivered.
|
|
26
26
|
*/
|
|
27
27
|
export declare const USER_DELETED_EMAIL_PREFIX = "deleted";
|
|
28
28
|
export declare const USER_ANONYMIZED_EMAIL_PREFIX = "anonymized";
|
package/dist/user/schema/user.js
CHANGED
|
@@ -2,10 +2,9 @@ import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
|
|
|
2
2
|
import { access, createBooleanField, createDerivedField, createEntity, createMultiSelectField, createSelectField, createTextField, createTimestampField, createTzField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
3
|
import { GLOBAL_ROLE_OPTIONS } from "../web/constants.js";
|
|
4
4
|
/**
|
|
5
|
-
* User
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* gleiches Pattern wie ROLES.SystemAdmin).
|
|
5
|
+
* User lifecycle status. This is the single source of truth used by the
|
|
6
|
+
* auth middleware, forget job, and restriction handler instead of duplicated
|
|
7
|
+
* magic strings, following the same pattern as ROLES.SystemAdmin.
|
|
9
8
|
*/
|
|
10
9
|
export const USER_STATUS = {
|
|
11
10
|
Active: "active",
|
|
@@ -14,24 +13,25 @@ export const USER_STATUS = {
|
|
|
14
13
|
Deleted: "deleted",
|
|
15
14
|
};
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* Display strings anonymized by userDeleteHook. Constants keep i18n mapping
|
|
17
|
+
* possible and prevent drift. The default is German; app authors can
|
|
18
|
+
* translate it through the i18n system if desired.
|
|
20
19
|
*/
|
|
21
20
|
export const USER_DELETED_DISPLAY_NAME = "[Geloescht]";
|
|
22
21
|
export const USER_ANONYMIZED_DISPLAY_NAME = "[Anonymisiert]";
|
|
23
22
|
/**
|
|
24
|
-
* Email
|
|
25
|
-
* —
|
|
26
|
-
*
|
|
27
|
-
* `.invalid
|
|
23
|
+
* Email pseudonyms used after forgetting. `<prefix>-<userId>@anonymized.invalid`
|
|
24
|
+
* — the userId suffix is permitted as a pseudo-audit marker for operator
|
|
25
|
+
* tracing; the user ID itself is a UUID, not PII.
|
|
26
|
+
* The `.invalid` TLD is reserved by RFC2606, so the address can never be
|
|
27
|
+
* delivered.
|
|
28
28
|
*/
|
|
29
29
|
export const USER_DELETED_EMAIL_PREFIX = "deleted";
|
|
30
30
|
export const USER_ANONYMIZED_EMAIL_PREFIX = "anonymized";
|
|
31
31
|
export const USER_ANONYMIZED_EMAIL_DOMAIN = "anonymized.invalid";
|
|
32
|
-
// Tuple form
|
|
33
|
-
// Object.values(USER_STATUS)
|
|
34
|
-
// type
|
|
32
|
+
// Tuple form for createSelectField (requires a non-empty readonly tuple).
|
|
33
|
+
// Object.values(USER_STATUS) would be string[]; the static tuple preserves
|
|
34
|
+
// type safety.
|
|
35
35
|
const USER_STATUS_OPTIONS = [
|
|
36
36
|
USER_STATUS.Active,
|
|
37
37
|
USER_STATUS.Restricted,
|
|
@@ -45,10 +45,10 @@ export const userEntity = createEntity({
|
|
|
45
45
|
table: "read_users",
|
|
46
46
|
softDelete: true,
|
|
47
47
|
// Tenant-independent identity aggregate — its event stream lives on
|
|
48
|
-
// SYSTEM_TENANT_ID instead of whichever tenant happened to create it
|
|
48
|
+
// SYSTEM_TENANT_ID instead of whichever tenant happened to create it.
|
|
49
49
|
systemStream: true,
|
|
50
50
|
// Every row lives on SYSTEM_TENANT_ID; writes with another tenantId are
|
|
51
|
-
// rejected
|
|
51
|
+
// rejected.
|
|
52
52
|
tenancy: "global",
|
|
53
53
|
fields: {
|
|
54
54
|
// Identity — anyone who can see the user can read the email, but only
|
|
@@ -81,17 +81,17 @@ export const userEntity = createEntity({
|
|
|
81
81
|
reason: "credential_hash_read_without_decrypt",
|
|
82
82
|
}),
|
|
83
83
|
// Profile — user-editable. Real name in most apps → PII. Searchable via
|
|
84
|
-
// the derived Meili index; events/projection stay ciphertext
|
|
84
|
+
// the derived Meili index; events/projection stay ciphertext.
|
|
85
85
|
displayName: createTextField({
|
|
86
86
|
required: true,
|
|
87
87
|
maxLength: 100,
|
|
88
88
|
personal: "self",
|
|
89
89
|
find: "fuzzy",
|
|
90
90
|
}),
|
|
91
|
-
// No default here — tenant-settings owns the app-wide locale default
|
|
91
|
+
// No default here — tenant-settings owns the app-wide locale default.
|
|
92
92
|
locale: createTextField({ maxLength: 10, personal: false, reason: "technical_reference" }),
|
|
93
93
|
// No default here — mirrors locale: ctx.tz falls back to tenant.timezone
|
|
94
|
-
// (then "UTC") when unset, see buildHandlerContext
|
|
94
|
+
// (then "UTC") when unset, see buildHandlerContext.
|
|
95
95
|
timezone: createTzField(),
|
|
96
96
|
// Which tenant should this user land in on next login. Set by the login
|
|
97
97
|
// handler (SYSTEM), read by the login flow + UI for deep-linking.
|
|
@@ -121,21 +121,22 @@ export const userEntity = createEntity({
|
|
|
121
121
|
default: [],
|
|
122
122
|
access: { write: access.privileged },
|
|
123
123
|
}),
|
|
124
|
-
//
|
|
125
|
-
// - "active":
|
|
126
|
-
// - "restricted": Art. 18
|
|
127
|
-
//
|
|
124
|
+
// User lifecycle status for user-data-rights.
|
|
125
|
+
// - "active": Normal state; all operations are allowed.
|
|
126
|
+
// - "restricted": Art. 18 restriction — login is blocked and every
|
|
127
|
+
// live session is rejected by sessionChecker
|
|
128
128
|
// ("blocked"). Recovery via lift-restriction
|
|
129
|
-
// (openToAll, session
|
|
130
|
-
// - "deletionRequested": delete-account
|
|
131
|
-
//
|
|
132
|
-
// (
|
|
133
|
-
//
|
|
134
|
-
// - "deleted": Forget executed
|
|
135
|
-
// softDelete. Login
|
|
129
|
+
// (openToAll, independent of the session).
|
|
130
|
+
// - "deletionRequested": delete-account was called and gracePeriodEnd set;
|
|
131
|
+
// login is blocked. Existing sessions remain LIVE
|
|
132
|
+
// (reversible), so the user can return to "active"
|
|
133
|
+
// via cancel-deletion.
|
|
134
|
+
// - "deleted": Forget was executed after the grace period; the row
|
|
135
|
+
// was anonymized via softDelete. Login is blocked and
|
|
136
|
+
// the session is "blocked".
|
|
136
137
|
//
|
|
137
|
-
//
|
|
138
|
-
// execute-forget
|
|
138
|
+
// Write access is privileged: only the request-deletion / restrict / lift /
|
|
139
|
+
// execute-forget handlers (all in SYSTEM context) may change the status.
|
|
139
140
|
status: createSelectField({
|
|
140
141
|
required: true,
|
|
141
142
|
default: USER_STATUS.Active,
|
|
@@ -143,21 +144,21 @@ export const userEntity = createEntity({
|
|
|
143
144
|
sortable: true,
|
|
144
145
|
access: { write: access.privileged },
|
|
145
146
|
}),
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
// (= now() + Compliance-Profile.userRights.gracePeriod),
|
|
151
|
-
// cancel-deletion
|
|
147
|
+
// When a pending forget may actually be executed.
|
|
148
|
+
// The user-data-rights cron job checks daily whether gracePeriodEnd < now()
|
|
149
|
+
// and then triggers the EXT_USER_DATA hooks. NULL means no forget is pending;
|
|
150
|
+
// delete-account sets it to
|
|
151
|
+
// (= now() + Compliance-Profile.userRights.gracePeriod), and
|
|
152
|
+
// cancel-deletion resets it.
|
|
152
153
|
gracePeriodEnd: createTimestampField({
|
|
153
154
|
access: { write: access.privileged },
|
|
154
155
|
}),
|
|
155
|
-
// Replay
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
159
|
-
// (
|
|
160
|
-
//
|
|
156
|
+
// Replay protection for the anonymous email-token deletion flow.
|
|
157
|
+
// request-deletion-by-email sets one UUID per email request, and
|
|
158
|
+
// cancel-deletion clears it. confirm-deletion-by-token incorporates this ID
|
|
159
|
+
// into the token's HMAC purpose, so a token replayed after cancellation
|
|
160
|
+
// (while still within its TTL) no longer verifies against the cleared or
|
|
161
|
+
// renewed ID. NULL means no email request is pending.
|
|
161
162
|
pendingDeletionRequestId: createTextField({
|
|
162
163
|
maxLength: 36,
|
|
163
164
|
access: { write: access.privileged },
|
package/dist/user/seeding.d.ts
CHANGED
|
@@ -4,28 +4,28 @@ import { type SeedTenantHooks } from "../tenant/seeding.ts";
|
|
|
4
4
|
export type SeedUserOptions = {
|
|
5
5
|
readonly email: string;
|
|
6
6
|
readonly displayName: string;
|
|
7
|
-
/** Optional
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
/** Optional pre-hashed password. For plain-password tests, prefer the
|
|
8
|
+
* convenience wrapper from
|
|
9
|
+
* `@cosmicdrift/kumiko-bundled-features/auth-email-password/seeding`,
|
|
10
|
+
* which performs argon2 hashing. */
|
|
11
11
|
readonly passwordHash?: string;
|
|
12
12
|
readonly locale?: string;
|
|
13
|
-
/** Global roles
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
/** Global roles—stored in users.roles as jsonb string[].
|
|
14
|
+
* The login handler merges them into the session roles alongside tenant-
|
|
15
|
+
* membership roles. Default: empty array. Typical example:
|
|
16
|
+
* `["SystemAdmin"]` for the platform operator. */
|
|
17
17
|
readonly roles?: readonly string[];
|
|
18
|
-
/** Initial
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
/** Initial state for emailVerified. Default: false. The required
|
|
19
|
+
* verification flow must explicitly set "true" when email ownership has
|
|
20
|
+
* already been proven—for example, in a Magic-Link signup where the user
|
|
21
|
+
* clicked the email link before the account was created. */
|
|
22
22
|
readonly emailVerified?: boolean;
|
|
23
23
|
readonly by?: SessionUser;
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
* Idempotent add-only
|
|
28
|
-
*
|
|
26
|
+
* Seeds a user. Returns the userId (existing or newly created).
|
|
27
|
+
* Idempotent and add-only via the `email` column: if a user with this
|
|
28
|
+
* email exists, its ID is returned without a new insert.
|
|
29
29
|
*/
|
|
30
30
|
export declare function seedUser(db: DbConnection, options: SeedUserOptions, hooks?: SeedTenantHooks): Promise<{
|
|
31
31
|
id: string;
|
package/dist/user/seeding.js
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
// Testing
|
|
2
|
-
//
|
|
3
|
-
// `UserHandlers.create`,
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// Testing helper for the user feature. `seedUser` creates a user directly
|
|
2
|
+
// through the event-store executor—the same path as the real
|
|
3
|
+
// `UserHandlers.create`, but without access checks or ConflictError on
|
|
4
|
+
// duplicates. It is idempotent and add-only via the `email` column: an
|
|
5
|
+
// existing user returns without emitting an event. There is no update path;
|
|
6
|
+
// profile changes go through the regular handler.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// Directly calling `db.insert(userTable)` would bypass the event store, so no
|
|
9
|
+
// `user.created` event would be emitted and no MSP consumers (audit,
|
|
10
|
+
// search-index) would see the seed. The executor path emits the event and
|
|
11
|
+
// writes the projection row in one transaction.
|
|
12
12
|
import { computeBlindIndex, configuredBlindIndexKey } from "@cosmicdrift/kumiko-framework/crypto";
|
|
13
13
|
import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
|
|
14
14
|
import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
|
|
15
|
-
// kumiko-lint-ignore cross-feature-import shares the postSave-hooks fixture contract with tenant/seeding
|
|
15
|
+
// kumiko-lint-ignore cross-feature-import shares the postSave-hooks fixture contract with tenant/seeding
|
|
16
16
|
import { fireEntityPostSave } from "../tenant/seeding.js";
|
|
17
17
|
import { userEntity, userTable } from "./schema/user.js";
|
|
18
18
|
const userExecutor = createEventStoreExecutor(userTable, userEntity, { entityName: "user" });
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
* Idempotent add-only
|
|
22
|
-
*
|
|
20
|
+
* Seeds a user. Returns the userId (existing or newly created).
|
|
21
|
+
* Idempotent and add-only via the `email` column: if a user with this
|
|
22
|
+
* email exists, its ID is returned without a new insert.
|
|
23
23
|
*/
|
|
24
24
|
export async function seedUser(db, options,
|
|
25
25
|
// Optional, append-only — same rationale as tenant/seeding's seedTenant
|
|
26
|
-
// hooks param
|
|
26
|
+
// hooks param: fires user's postSave hooks (e.g. a Welcome-
|
|
27
27
|
// notification hook keyed off `allOf: "user"`) for fixtures/self-signup
|
|
28
28
|
// that opt in. Omit to keep today's hook-less behavior.
|
|
29
29
|
hooks) {
|
|
30
30
|
const by = options.by ?? TestUsers.systemAdmin;
|
|
31
|
-
// executor.create
|
|
32
|
-
//
|
|
33
|
-
//
|
|
31
|
+
// executor.create expects a TenantDb (with an .insert() API). Although
|
|
32
|
+
// User is tenant-agnostic (it has no tenant_id column), the runtime
|
|
33
|
+
// interface requires this wrapper.
|
|
34
34
|
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
35
35
|
const existing = await fetchOne(db, userTable, { email: options.email, isDeleted: false });
|
|
36
|
-
// @cast-boundary db-row: users.id
|
|
37
|
-
//
|
|
36
|
+
// @cast-boundary db-row: users.id is a uuid column (string), and fetchOne
|
|
37
|
+
// returns the projection row as Record<string, unknown>.
|
|
38
38
|
if (existing) {
|
|
39
39
|
const id = existing["id"];
|
|
40
40
|
if (options.emailVerified === true) {
|
|
@@ -57,13 +57,13 @@ hooks) {
|
|
|
57
57
|
return { id: extractId(result.data, "seedUser") };
|
|
58
58
|
}
|
|
59
59
|
// A re-run seed onto a row created before emailVerified flipped to true must
|
|
60
|
-
// still set it
|
|
60
|
+
// still set it — via the executor, so it lands as a real `.updated` event.
|
|
61
61
|
export async function reconcileSeededUserEmailVerified(db, existingRow, by) {
|
|
62
62
|
// skip: already verified, nothing to reconcile
|
|
63
63
|
if (existingRow["emailVerified"] === true)
|
|
64
64
|
return;
|
|
65
|
-
// @cast-boundary db-row: users.id
|
|
66
|
-
//
|
|
65
|
+
// @cast-boundary db-row: users.id is a uuid column (string), and fetchOne
|
|
66
|
+
// returns the projection row as Record<string, unknown>.
|
|
67
67
|
const id = existingRow["id"];
|
|
68
68
|
const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
|
|
69
69
|
const result = await userExecutor.update({ id, version: existingRow["version"], changes: { emailVerified: true } }, by, tdb);
|
|
@@ -111,11 +111,11 @@ export async function rewriteSeededUserEmail(db, existingRow, email, by) {
|
|
|
111
111
|
throw new Error(`rewriteSeededUserEmail failed: ${result.error.code} — ${JSON.stringify(result.error.details ?? {})}`);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
114
|
+
// Extracts the `id` column from the executor.create result. The executor
|
|
115
|
+
// returns a Record<string, unknown> (the projection row), into which the DB
|
|
116
|
+
// writes the aggregate ID. We validate it at runtime instead of using a
|
|
117
|
+
// blind `as { id: string }` cast, so an API contract violation throws an
|
|
118
|
+
// explicit error rather than surfacing downstream as an undefined-value bug.
|
|
119
119
|
function extractId(data, who) {
|
|
120
120
|
if (typeof data === "object" && data !== null && "id" in data) {
|
|
121
121
|
const id = data.id; // @cast-boundary engine-bridge
|
package/dist/user/testing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// /testing re-
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// /testing re-exports /seeding. See ../tenant/testing.ts for the
|
|
2
|
+
// reason: helpers are shared between tests and Dev-Server bootstrap,
|
|
3
|
+
// and /seeding is the stable home.
|
|
4
4
|
export * from "./seeding.js";
|
|
@@ -8,11 +8,11 @@ export interface RecordDownloadUseArgs {
|
|
|
8
8
|
readonly tokenVersion: number;
|
|
9
9
|
readonly tokenUseCount: number;
|
|
10
10
|
/**
|
|
11
|
-
* Tenant
|
|
12
|
-
* tenant-
|
|
13
|
-
*
|
|
14
|
-
* job.requestedFromTenantId —
|
|
15
|
-
*
|
|
11
|
+
* Tenant for the system-mode TenantDb. ExportDownloadToken is
|
|
12
|
+
* tenant-agnostic (1:1 with the tenant-agnostic job), but the event-store
|
|
13
|
+
* stream lookup requires a tenant context. We use
|
|
14
|
+
* job.requestedFromTenantId — the same identity used when creating the
|
|
15
|
+
* token in the worker.
|
|
16
16
|
*/
|
|
17
17
|
readonly tenantId: TenantId;
|
|
18
18
|
readonly now: Instant;
|
|
@@ -20,9 +20,9 @@ export interface RecordDownloadUseArgs {
|
|
|
20
20
|
readonly userAgent: string | null;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
* Audit
|
|
24
|
-
* version
|
|
25
|
-
*
|
|
23
|
+
* Audit update: useCount, lastUsedAt, IP, and UA. Best-effort —
|
|
24
|
+
* version conflicts (parallel downloads) are swallowed, so the download
|
|
25
|
+
* still succeeds.
|
|
26
26
|
*/
|
|
27
27
|
export declare function recordDownloadUse(args: RecordDownloadUseArgs): Promise<void>;
|
|
28
28
|
export type DownloadAttemptResult = "notFound" | "expired" | "failed" | "signedUrlNotSupported";
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
// Audit
|
|
1
|
+
// Audit helper for the download endpoint.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// During a download (token path or job path), audit fields on the token row
|
|
4
|
+
// are updated:
|
|
5
5
|
// - useCount + 1
|
|
6
6
|
// - lastUsedAt = now
|
|
7
|
-
// - lastUsedFromIp = caller
|
|
8
|
-
// - lastUsedUserAgent = UA
|
|
7
|
+
// - lastUsedFromIp = caller IP (X-Forwarded-For or connection IP)
|
|
8
|
+
// - lastUsedUserAgent = UA header
|
|
9
9
|
//
|
|
10
|
-
// **Best-
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// (kein download-block bei race).
|
|
10
|
+
// **Best-effort update:** version conflicts (two downloads racing to update)
|
|
11
|
+
// are silently swallowed — the audit records the "last use", not "all uses".
|
|
12
|
+
// The second download still succeeds (a race does not block the download).
|
|
14
13
|
//
|
|
15
|
-
// **ES via tokenCrud.update:**
|
|
16
|
-
//
|
|
14
|
+
// **ES via tokenCrud.update:** no direct UPDATE, so the event-store and tenant
|
|
15
|
+
// consistency rules remain in effect.
|
|
17
16
|
import { createEventStoreExecutor, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
18
17
|
import { createSystemUser } from "@cosmicdrift/kumiko-framework/engine";
|
|
19
18
|
import { tokenCrud } from "./run-export-jobs.js";
|
|
@@ -22,9 +21,9 @@ const attemptCrud = createEventStoreExecutor(downloadAttemptsTable, downloadAtte
|
|
|
22
21
|
entityName: "download-attempt",
|
|
23
22
|
});
|
|
24
23
|
/**
|
|
25
|
-
* Audit
|
|
26
|
-
* version
|
|
27
|
-
*
|
|
24
|
+
* Audit update: useCount, lastUsedAt, IP, and UA. Best-effort —
|
|
25
|
+
* version conflicts (parallel downloads) are swallowed, so the download
|
|
26
|
+
* still succeeds.
|
|
28
27
|
*/
|
|
29
28
|
export async function recordDownloadUse(args) {
|
|
30
29
|
const { db, tokenId, tokenVersion, tokenUseCount, tenantId, now, ip, userAgent } = args;
|
|
@@ -42,14 +41,14 @@ export async function recordDownloadUse(args) {
|
|
|
42
41
|
},
|
|
43
42
|
}, executor, tdb)
|
|
44
43
|
.catch(() => {
|
|
45
|
-
// version
|
|
46
|
-
//
|
|
47
|
-
//
|
|
44
|
+
// A version conflict means a parallel download already incremented
|
|
45
|
+
// useCount. Keep the first download's audit entry (lastUsedAt, etc.);
|
|
46
|
+
// do not block the download.
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
|
-
// Best-effort INSERT
|
|
51
|
-
//
|
|
52
|
-
//
|
|
49
|
+
// Best-effort INSERT into read_download_attempts. Errors in the audit path
|
|
50
|
+
// must not kill the download endpoint: the user should receive their 404,
|
|
51
|
+
// not a 500; failures are silently swallowed.
|
|
53
52
|
export async function recordInvalidAttempt(args) {
|
|
54
53
|
const { db, tenantId, now } = args;
|
|
55
54
|
const executor = createSystemUser(tenantId);
|
|
@@ -7,7 +7,7 @@ import { entitiesOf } from "../shared/index.js";
|
|
|
7
7
|
// only; runtime no-ops (a delete hook that silently skips) are not detectable
|
|
8
8
|
// here — those are covered by the export/forget integration tests.
|
|
9
9
|
//
|
|
10
|
-
// Registered as an `r.bootCheck()` by this feature
|
|
10
|
+
// Registered as an `r.bootCheck()` by this feature — EXT_USER_DATA is
|
|
11
11
|
// owned by user-data-rights (r.extendsRegistrar(EXT_USER_DATA, {})), so any
|
|
12
12
|
// r.useExtension(EXT_USER_DATA, ...) usage across the app already requires
|
|
13
13
|
// user-data-rights to be mounted (boot-validator's extension-provider check
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// subject is the user, the anchor is the pending request id stored on the
|
|
3
3
|
// user row. Minting and verification both run through
|
|
4
4
|
// shared/row-bound-grant, so a token from a cancelled cycle (id nulled) or a
|
|
5
|
-
// superseded one (row holds a newer id) fails verification
|
|
5
|
+
// superseded one (row holds a newer id) fails verification.
|
|
6
6
|
//
|
|
7
7
|
// The purpose string and the anchoring are unchanged from the hand-rolled
|
|
8
8
|
// version this replaced, so tokens stay byte-compatible.
|