@cosmicdrift/kumiko-bundled-features 1.0.0 → 2.0.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/package.json +41 -7
- package/src/__tests__/access-invalidation-consumer.integration.test.ts +279 -0
- package/src/__tests__/access-invalidation-stream.integration.test.ts +217 -0
- package/src/admin-shell/__tests__/admin-shell-security.integration.test.ts +200 -0
- package/src/admin-shell/__tests__/admin-shell.boot.test.ts +147 -0
- package/src/admin-shell/__tests__/overview-allowlist.test.ts +43 -0
- package/src/admin-shell/__tests__/overview-screens.boot.test.ts +35 -0
- package/src/admin-shell/constants.ts +11 -0
- package/src/admin-shell/feature.ts +135 -0
- package/src/admin-shell/i18n.ts +36 -0
- package/src/admin-shell/index.ts +17 -0
- package/src/admin-shell/overview-allowlist.ts +37 -0
- package/src/admin-shell/web/client-plugin.tsx +26 -0
- package/src/admin-shell/web/i18n.ts +16 -0
- package/src/admin-shell/web/index.ts +2 -0
- package/src/admin-shell/web/overview-layout.tsx +69 -0
- package/src/admin-shell/web/overview-query.ts +15 -0
- package/src/admin-shell/web/platform-overview-screen.tsx +90 -0
- package/src/admin-shell/web/tenant-overview-screen.tsx +90 -0
- package/src/agent-tools/__tests__/tool-catalog.test.ts +179 -0
- package/src/agent-tools/__tests__/tool-dispatch.integration.test.ts +100 -0
- package/src/agent-tools/__tests__/tool-dispatch.test.ts +126 -0
- package/src/agent-tools/index.ts +9 -0
- package/src/agent-tools/tool-catalog.ts +130 -0
- package/src/agent-tools/tool-dispatch.ts +82 -0
- package/src/agent-tools/types.ts +38 -0
- package/src/audit/__tests__/audit-screens.boot.test.ts +51 -0
- package/src/audit/__tests__/audit-security.integration.test.ts +201 -0
- package/src/audit/__tests__/audit.integration.test.ts +50 -25
- package/src/audit/constants.ts +9 -2
- package/src/audit/feature.ts +33 -1
- package/src/audit/handlers/details.query.ts +47 -0
- package/src/audit/handlers/list.query.ts +3 -2
- package/src/audit/i18n.ts +31 -0
- package/src/audit/web/audit-log-detail-screen.tsx +131 -0
- package/src/audit/web/audit-log-screen.tsx +250 -0
- package/src/audit/web/client-plugin.tsx +22 -0
- package/src/audit/web/i18n.ts +12 -0
- package/src/audit/web/index.ts +5 -0
- package/src/auth-email-password/__tests__/account-lockout-no-redis.integration.test.ts +4 -4
- package/src/auth-email-password/__tests__/account-lockout.integration.test.ts +4 -4
- package/src/auth-email-password/__tests__/account-unlock.integration.test.ts +283 -0
- package/src/auth-email-password/__tests__/auth-claims.integration.test.ts +10 -11
- package/src/auth-email-password/__tests__/auth-user-row.test.ts +36 -0
- package/src/auth-email-password/__tests__/auth.integration.test.ts +33 -6
- package/src/auth-email-password/__tests__/email-verification.integration.test.ts +9 -6
- package/src/auth-email-password/__tests__/feature-options.test.ts +33 -0
- package/src/auth-email-password/__tests__/identity-v3-login.integration.test.ts +3 -3
- package/src/auth-email-password/__tests__/invite-flow-kms.integration.test.ts +283 -0
- package/src/auth-email-password/__tests__/invite-flow.integration.test.ts +35 -1
- package/src/auth-email-password/__tests__/login-mfa-setup-required.integration.test.ts +129 -0
- package/src/auth-email-password/__tests__/multi-roles.integration.test.ts +1 -1
- package/src/auth-email-password/__tests__/password-policy.test.ts +15 -0
- package/src/auth-email-password/__tests__/password-reset.integration.test.ts +19 -6
- package/src/auth-email-password/__tests__/public-routes-rate-limit.integration.test.ts +3 -3
- package/src/auth-email-password/__tests__/seed-admin.integration.test.ts +1 -1
- package/src/auth-email-password/__tests__/self-registration-toggle.integration.test.ts +264 -0
- package/src/auth-email-password/__tests__/session-callbacks.integration.test.ts +20 -4
- package/src/auth-email-password/__tests__/session-strict-mode.integration.test.ts +7 -14
- package/src/auth-email-password/__tests__/signup-flow.integration.test.ts +91 -0
- package/src/auth-email-password/constants.ts +25 -0
- package/src/auth-email-password/email-templates.ts +32 -0
- package/src/auth-email-password/errors.ts +9 -0
- package/src/auth-email-password/feature.ts +59 -11
- package/src/auth-email-password/handlers/change-password.write.ts +14 -13
- package/src/auth-email-password/handlers/confirm-account-unlock.write.ts +59 -0
- package/src/auth-email-password/handlers/confirm-token-flow.ts +34 -105
- package/src/auth-email-password/handlers/invite-accept-with-login.write.ts +12 -5
- package/src/auth-email-password/handlers/invite-accept.write.ts +9 -2
- package/src/auth-email-password/handlers/invite-create.write.ts +2 -2
- package/src/auth-email-password/handlers/invite-signup-complete.write.ts +12 -4
- package/src/auth-email-password/handlers/login.write.ts +86 -16
- package/src/auth-email-password/handlers/logout.write.ts +4 -2
- package/src/auth-email-password/handlers/request-account-unlock.write.ts +38 -0
- package/src/auth-email-password/handlers/reset-password.write.ts +3 -2
- package/src/auth-email-password/handlers/self-registration-status.query.ts +23 -0
- package/src/auth-email-password/handlers/signup-confirm.write.ts +19 -11
- package/src/auth-email-password/handlers/signup-request.write.ts +22 -0
- package/src/auth-email-password/handlers/token-request-handler.ts +4 -2
- package/src/auth-email-password/i18n.ts +52 -0
- package/src/auth-email-password/index.ts +13 -2
- package/src/auth-email-password/lockout-store.ts +10 -5
- package/src/auth-email-password/password-policy.ts +2108 -0
- package/src/auth-email-password/seeding.ts +55 -27
- package/src/auth-email-password/self-registration-toggle.ts +25 -0
- package/src/auth-email-password/signed-token.ts +1 -0
- package/src/auth-email-password/unlock-token.ts +28 -0
- package/src/auth-email-password/web/__tests__/auth-client.test.ts +542 -0
- package/src/auth-email-password/web/__tests__/auth-form-logic.test.ts +44 -0
- package/src/auth-email-password/web/__tests__/auth-gate.test.tsx +194 -6
- package/src/auth-email-password/web/__tests__/client-plugin.test.tsx +34 -0
- package/src/auth-email-password/web/__tests__/confirm-account-unlock-screen.test.tsx +64 -0
- package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +5 -1
- package/src/auth-email-password/web/__tests__/invite-accept-screen.test.tsx +129 -2
- package/src/auth-email-password/web/__tests__/login-screen.test.tsx +149 -5
- package/src/auth-email-password/web/__tests__/request-account-unlock-screen.test.tsx +137 -0
- package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +5 -1
- package/src/auth-email-password/web/__tests__/signup-complete-screen.test.tsx +134 -0
- package/src/auth-email-password/web/__tests__/signup-screen.test.tsx +93 -0
- package/src/auth-email-password/web/__tests__/test-utils.tsx +12 -2
- package/src/auth-email-password/web/__tests__/use-url-token.test.tsx +29 -0
- package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +5 -1
- package/src/auth-email-password/web/auth-client.ts +96 -18
- package/src/auth-email-password/web/auth-form-logic.ts +30 -0
- package/src/auth-email-password/web/auth-form-primitives.tsx +22 -20
- package/src/auth-email-password/web/auth-gate.tsx +140 -19
- package/src/auth-email-password/web/client-plugin.ts +24 -2
- package/src/auth-email-password/web/confirm-account-unlock-screen.tsx +95 -0
- package/src/auth-email-password/web/forgot-password-screen.tsx +6 -6
- package/src/auth-email-password/web/index.ts +16 -4
- package/src/auth-email-password/web/invite-accept-screen.tsx +5 -5
- package/src/auth-email-password/web/login-screen.tsx +78 -22
- package/src/auth-email-password/web/request-account-unlock-screen.tsx +112 -0
- package/src/auth-email-password/web/reset-password-screen.tsx +15 -18
- package/src/auth-email-password/web/session.tsx +11 -6
- package/src/auth-email-password/web/signup-complete-screen.tsx +13 -15
- package/src/auth-email-password/web/signup-screen.tsx +8 -10
- package/src/auth-email-password/web/use-shell-user.ts +5 -2
- package/src/auth-email-password/web/user-menu.tsx +3 -1
- package/src/auth-email-password/web/verify-email-screen.tsx +10 -14
- package/src/auth-foundation/__tests__/feature.test.ts +46 -0
- package/src/auth-foundation/__tests__/session-store.test.ts +77 -0
- package/src/auth-foundation/__tests__/tenant-providers.test.ts +160 -0
- package/src/auth-foundation/__tests__/token-verifier.test.ts +150 -0
- package/src/auth-foundation/boot-checks.ts +150 -0
- package/src/auth-foundation/feature.ts +157 -0
- package/src/auth-foundation/index.ts +37 -0
- package/src/auth-foundation/resolve-anonymous-access.ts +62 -0
- package/src/auth-foundation/types.ts +170 -0
- package/src/auth-mfa/__tests__/base32.test.ts +28 -0
- package/src/auth-mfa/__tests__/disable-and-regenerate.integration.test.ts +265 -0
- package/src/auth-mfa/__tests__/enable-confirm-preauth.integration.test.ts +321 -0
- package/src/auth-mfa/__tests__/enable-flow.integration.test.ts +322 -0
- package/src/auth-mfa/__tests__/enable-start-preauth.integration.test.ts +237 -0
- package/src/auth-mfa/__tests__/errors-i18n-parity.test.ts +39 -0
- package/src/auth-mfa/__tests__/mfa-preauth-setup-token.test.ts +113 -0
- package/src/auth-mfa/__tests__/no-redis.integration.test.ts +209 -0
- package/src/auth-mfa/__tests__/pii-subject-encryption.integration.test.ts +139 -0
- package/src/auth-mfa/__tests__/reencrypt-job.integration.test.ts +247 -0
- package/src/auth-mfa/__tests__/session-auto-revoke.integration.test.ts +169 -0
- package/src/auth-mfa/__tests__/totp.test.ts +131 -0
- package/src/auth-mfa/__tests__/verify.integration.test.ts +319 -0
- package/src/auth-mfa/base32.ts +51 -0
- package/src/auth-mfa/config.ts +26 -0
- package/src/auth-mfa/constants.ts +45 -0
- package/src/auth-mfa/db/queries.ts +45 -0
- package/src/auth-mfa/errors.ts +66 -0
- package/src/auth-mfa/feature.ts +170 -0
- package/src/auth-mfa/handlers/disable.write.ts +67 -0
- package/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +200 -0
- package/src/auth-mfa/handlers/enable-confirm.write.ts +106 -0
- package/src/auth-mfa/handlers/enable-start-preauth.write.ts +87 -0
- package/src/auth-mfa/handlers/enable-start.write.ts +66 -0
- package/src/auth-mfa/handlers/reencrypt.job.ts +234 -0
- package/src/auth-mfa/handlers/regenerate-recovery.write.ts +77 -0
- package/src/auth-mfa/handlers/status.query.ts +23 -0
- package/src/auth-mfa/handlers/verify.write.ts +179 -0
- package/src/auth-mfa/i18n.ts +12 -0
- package/src/auth-mfa/index.ts +19 -0
- package/src/auth-mfa/mfa-challenge-token.ts +90 -0
- package/src/auth-mfa/mfa-preauth-setup-token.ts +86 -0
- package/src/auth-mfa/mfa-setup-token.ts +96 -0
- package/src/auth-mfa/mfa-status-checker.ts +84 -0
- package/src/auth-mfa/mfa-verify-attempts.ts +90 -0
- package/src/auth-mfa/otpauth-uri.ts +21 -0
- package/src/auth-mfa/recovery-codes.ts +54 -0
- package/src/auth-mfa/schema/user-mfa.ts +60 -0
- package/src/auth-mfa/testing.ts +5 -0
- package/src/auth-mfa/totp.ts +67 -0
- package/src/auth-mfa/verify-factor.ts +58 -0
- package/src/auth-mfa/web/__tests__/mfa-client.test.ts +265 -0
- package/src/auth-mfa/web/__tests__/mfa-enable-screen.test.tsx +182 -0
- package/src/auth-mfa/web/__tests__/mfa-setup-preauth-screen.test.tsx +379 -0
- package/src/auth-mfa/web/__tests__/mfa-verify-screen.test.tsx +104 -0
- package/src/auth-mfa/web/client-plugin.ts +37 -0
- package/src/auth-mfa/web/i18n.ts +136 -0
- package/src/auth-mfa/web/index.ts +27 -0
- package/src/auth-mfa/web/mfa-client.ts +184 -0
- package/src/auth-mfa/web/mfa-disable-dialog.tsx +69 -0
- package/src/auth-mfa/web/mfa-enable-screen.tsx +228 -0
- package/src/auth-mfa/web/mfa-recovery-codes-reveal.tsx +53 -0
- package/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +68 -0
- package/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +267 -0
- package/src/auth-mfa/web/mfa-verify-screen.tsx +117 -0
- package/src/auth-mfa/web/qrcode-browser.d.ts +12 -0
- package/src/auth-mfa-user-data/__tests__/hooks.integration.test.ts +134 -0
- package/src/auth-mfa-user-data/hooks.ts +53 -0
- package/src/auth-mfa-user-data/index.ts +21 -0
- package/src/billing-foundation/__tests__/billing-foundation.integration.test.ts +206 -2
- package/src/billing-foundation/__tests__/subscription-provider-contract.ts +93 -0
- package/src/billing-foundation/entities.ts +28 -4
- package/src/billing-foundation/events.ts +6 -2
- package/src/billing-foundation/feature.ts +9 -1
- package/src/billing-foundation/get-subscription-for-tenant.ts +16 -5
- package/src/billing-foundation/handlers/create-portal-session.write.ts +17 -1
- package/src/billing-foundation/handlers/list-subscriptions.query.ts +15 -1
- package/src/billing-foundation/handlers/process-event.write.ts +39 -3
- package/src/billing-foundation/tenant-destroy-hook.ts +46 -0
- package/src/cap-counter/__tests__/cap-list.boot.test.ts +27 -0
- package/src/cap-counter/__tests__/cap-list.security.integration.test.ts +53 -0
- package/src/cap-counter/__tests__/entity-ddl.test.ts +15 -0
- package/src/cap-counter/__tests__/with-cap-enforcement.integration.test.ts +8 -5
- package/src/cap-counter/constants.ts +2 -0
- package/src/cap-counter/enforce-cap.ts +15 -18
- package/src/cap-counter/entity.ts +3 -3
- package/src/cap-counter/feature.ts +28 -1
- package/src/cap-counter/i18n.ts +12 -0
- package/src/cap-counter/with-cap-enforcement.ts +2 -2
- package/src/channel-email/__tests__/pii-guard.test.ts +56 -0
- package/src/channel-email/email-channel.ts +2 -1
- package/src/channel-email/index.ts +1 -0
- package/src/channel-email/pii-guard.ts +39 -0
- package/src/compliance-profiles/__tests__/profile-picker.boot.test.ts +28 -0
- package/src/compliance-profiles/__tests__/profile-picker.security.integration.test.ts +91 -0
- package/src/compliance-profiles/constants.ts +15 -0
- package/src/compliance-profiles/feature.ts +22 -1
- package/src/compliance-profiles/handlers/set-profile.write.ts +2 -2
- package/src/compliance-profiles/i18n.ts +6 -0
- package/src/compliance-profiles/index.ts +6 -0
- package/src/compliance-profiles/web/client-plugin.tsx +22 -0
- package/src/compliance-profiles/web/compliance-profile-screen.tsx +152 -0
- package/src/compliance-profiles/web/i18n.ts +25 -0
- package/src/compliance-profiles/web/index.ts +6 -0
- package/src/config/__tests__/app-overrides.test.ts +11 -0
- package/src/config/__tests__/backing-secrets.integration.test.ts +22 -0
- package/src/config/__tests__/cascade.integration.test.ts +35 -0
- package/src/config/__tests__/config.integration.test.ts +71 -10
- package/src/config/__tests__/deserialize-value.test.ts +5 -8
- package/src/config/__tests__/inherited-redaction.integration.test.ts +4 -3
- package/src/config/__tests__/pii-encrypted.integration.test.ts +179 -0
- package/src/config/__tests__/reencrypt-job-concurrent-write-race.integration.test.ts +234 -0
- package/src/config/__tests__/reencrypt-job-kek-rotation.integration.test.ts +243 -0
- package/src/config/__tests__/write-helpers.test.ts +23 -0
- package/src/config/db/queries/resolver.ts +3 -3
- package/src/config/feature.ts +15 -8
- package/src/config/handlers/cascade.query.ts +2 -1
- package/src/config/handlers/reencrypt.job.ts +209 -0
- package/src/config/handlers/set.write.ts +55 -3
- package/src/config/handlers/values.query.ts +2 -1
- package/src/config/i18n.ts +9 -0
- package/src/config/index.ts +5 -4
- package/src/config/resolver.ts +75 -61
- package/src/config/table.ts +1 -1
- package/src/config/write-helpers.ts +22 -0
- package/src/crypto-shredding/__tests__/forget-subject.integration.test.ts +148 -0
- package/src/crypto-shredding/constants.ts +5 -0
- package/src/crypto-shredding/feature.ts +18 -0
- package/src/crypto-shredding/handlers/forget-subject.write.ts +91 -0
- package/src/crypto-shredding/index.ts +11 -0
- package/src/custom-fields/__tests__/audit-integration.integration.test.ts +1 -1
- package/src/custom-fields/__tests__/custom-fields.integration.test.ts +92 -53
- package/src/custom-fields/__tests__/field-access.integration.test.ts +25 -0
- package/src/custom-fields/__tests__/parse-serialized-field.test.ts +11 -3
- package/src/custom-fields/__tests__/retention.integration.test.ts +40 -0
- package/src/custom-fields/__tests__/user-data-rights.integration.test.ts +26 -79
- package/src/custom-fields/constants.ts +1 -0
- package/src/custom-fields/db/queries/user-data-rights.ts +0 -20
- package/src/custom-fields/entity.ts +1 -1
- package/src/custom-fields/events.ts +4 -3
- package/src/custom-fields/feature.ts +8 -0
- package/src/custom-fields/handlers/delete-system-field.write.ts +2 -1
- package/src/custom-fields/handlers/delete-tenant-field.write.ts +2 -1
- package/src/custom-fields/handlers/set-custom-field.write.ts +3 -44
- package/src/custom-fields/handlers/update-tenant-field.write.ts +0 -17
- package/src/custom-fields/lib/field-access.ts +8 -1
- package/src/custom-fields/lib/parse-serialized-field.ts +12 -4
- package/src/custom-fields/lib/value-schema.ts +1 -1
- package/src/custom-fields/run-retention.ts +9 -1
- package/src/custom-fields/schemas.ts +9 -9
- package/src/custom-fields/wire-for-entity.ts +110 -78
- package/src/custom-fields/wire-user-data-rights.ts +5 -54
- package/src/data-retention/__tests__/parse-override.test.ts +14 -13
- package/src/data-retention/__tests__/retention-cleanup.integration.test.ts +145 -8
- package/src/data-retention/feature.ts +3 -3
- package/src/data-retention/run-retention-cleanup.ts +102 -19
- package/src/delivery/__tests__/delivery-pii-kms.integration.test.ts +171 -0
- package/src/delivery/__tests__/delivery-screens.boot.test.ts +27 -0
- package/src/delivery/__tests__/delivery-security.integration.test.ts +106 -0
- package/src/delivery/constants.ts +13 -51
- package/src/delivery/feature.ts +29 -5
- package/src/delivery/handlers/log.query.ts +28 -7
- package/src/delivery/i18n.ts +6 -0
- package/src/delivery/index.ts +6 -1
- package/src/delivery/public-names.ts +36 -0
- package/src/delivery/tables.ts +3 -3
- package/src/delivery/web/client-plugin.tsx +20 -0
- package/src/delivery/web/delivery-log-screen.tsx +103 -0
- package/src/delivery/web/i18n.ts +25 -0
- package/src/delivery/web/index.ts +3 -0
- package/src/document-ingest-foundation/__tests__/feature.integration.test.ts +147 -0
- package/src/document-ingest-foundation/__tests__/feature.test.ts +105 -0
- package/src/document-ingest-foundation/__tests__/pages.test.ts +37 -0
- package/src/document-ingest-foundation/entity.ts +43 -0
- package/src/document-ingest-foundation/events.ts +25 -0
- package/src/document-ingest-foundation/feature.ts +126 -0
- package/src/document-ingest-foundation/index.ts +12 -0
- package/src/document-ingest-foundation/pages.ts +34 -0
- package/src/feature-toggles/__tests__/compose-tier-resolver.test.ts +304 -0
- package/src/feature-toggles/__tests__/feature-toggles.integration.test.ts +7 -6
- package/src/feature-toggles/__tests__/toggle-admin.boot.test.ts +31 -0
- package/src/feature-toggles/__tests__/toggle-admin.security.integration.test.ts +69 -0
- package/src/feature-toggles/compose-tier-resolver.ts +134 -0
- package/src/feature-toggles/constants.ts +14 -0
- package/src/feature-toggles/feature.ts +23 -3
- package/src/feature-toggles/global-feature-state-table.ts +20 -1
- package/src/feature-toggles/handlers/list.query.ts +1 -1
- package/src/feature-toggles/handlers/registered.query.ts +1 -1
- package/src/feature-toggles/i18n.ts +6 -0
- package/src/feature-toggles/index.ts +8 -0
- package/src/feature-toggles/toggle-runtime.ts +14 -0
- package/src/feature-toggles/web/client-plugin.tsx +22 -0
- package/src/feature-toggles/web/i18n.ts +29 -0
- package/src/feature-toggles/web/index.ts +6 -0
- package/src/feature-toggles/web/toggle-admin-screen.tsx +136 -0
- package/src/file-foundation/__tests__/feature.test.ts +5 -5
- package/src/file-foundation/__tests__/file-foundation.integration.test.ts +4 -3
- package/src/file-foundation/feature.ts +10 -11
- package/src/files-provider-s3/__tests__/s3-provider.integration.test.ts +27 -2
- package/src/files-provider-s3/s3-provider.ts +12 -1
- package/src/folders/__tests__/folders.integration.test.ts +3 -0
- package/src/folders/web/__tests__/folder-manager.test.tsx +43 -2
- package/src/folders/web/__tests__/tree.test.ts +8 -0
- package/src/folders/web/folder-manager.tsx +2 -3
- package/src/folders/web/i18n.ts +0 -2
- package/src/folders/web/tree.ts +13 -2
- package/src/folders-user-data/__tests__/hooks.integration.test.ts +1 -0
- package/src/folders-user-data/index.ts +4 -4
- package/src/inbound-mail-foundation/__tests__/account-state.test.ts +30 -0
- package/src/inbound-mail-foundation/__tests__/connect-routes.integration.test.ts +307 -0
- package/src/inbound-mail-foundation/__tests__/feature.test.ts +169 -0
- package/src/inbound-mail-foundation/__tests__/inbound-mail-foundation.integration.test.ts +644 -0
- package/src/inbound-mail-foundation/__tests__/inbound-mail-provider-contract.ts +111 -0
- package/src/inbound-mail-foundation/__tests__/retention.integration.test.ts +237 -0
- package/src/inbound-mail-foundation/__tests__/watch-supervisor.integration.test.ts +433 -0
- package/src/inbound-mail-foundation/aggregate-id.ts +40 -0
- package/src/inbound-mail-foundation/connect-routes.ts +230 -0
- package/src/inbound-mail-foundation/constants.ts +80 -0
- package/src/inbound-mail-foundation/db/queries/inbound-projections.ts +38 -0
- package/src/inbound-mail-foundation/entities.ts +172 -0
- package/src/inbound-mail-foundation/events.ts +147 -0
- package/src/inbound-mail-foundation/feature.ts +243 -0
- package/src/inbound-mail-foundation/handlers/account-state.ts +23 -0
- package/src/inbound-mail-foundation/handlers/connect-account.write.ts +112 -0
- package/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +69 -0
- package/src/inbound-mail-foundation/handlers/ingest-message.write.ts +333 -0
- package/src/inbound-mail-foundation/handlers/list-accounts.query.ts +44 -0
- package/src/inbound-mail-foundation/handlers/list-messages.query.ts +58 -0
- package/src/inbound-mail-foundation/handlers/scope-visibility.ts +14 -0
- package/src/inbound-mail-foundation/handlers/update-account.write.ts +78 -0
- package/src/inbound-mail-foundation/index.ts +97 -0
- package/src/inbound-mail-foundation/oauth-state.ts +103 -0
- package/src/inbound-mail-foundation/projection.ts +152 -0
- package/src/inbound-mail-foundation/provider-factory.ts +53 -0
- package/src/inbound-mail-foundation/retention-sweep.ts +168 -0
- package/src/inbound-mail-foundation/tenant-destroy-hook.ts +93 -0
- package/src/inbound-mail-foundation/types.ts +250 -0
- package/src/inbound-mail-foundation/watch-supervisor.ts +482 -0
- package/src/inbound-provider-imap/__tests__/feature.test.ts +115 -0
- package/src/inbound-provider-imap/__tests__/imap-foundation.integration.test.ts +302 -0
- package/src/inbound-provider-imap/__tests__/imap-live.integration.test.ts +206 -0
- package/src/inbound-provider-imap/__tests__/plugin-mocked.test.ts +358 -0
- package/src/inbound-provider-imap/credential-document.ts +51 -0
- package/src/inbound-provider-imap/feature.ts +283 -0
- package/src/inbound-provider-imap/imap-client.ts +158 -0
- package/src/inbound-provider-imap/index.ts +17 -0
- package/src/inbound-provider-inmemory/__tests__/feature.test.ts +52 -0
- package/src/inbound-provider-inmemory/feature.ts +154 -0
- package/src/inbound-provider-inmemory/index.ts +12 -0
- package/src/jobs/__tests__/entity-ddl.test.ts +15 -0
- package/src/jobs/__tests__/job-instant.test.ts +15 -0
- package/src/jobs/__tests__/job-system-user.integration.test.ts +4 -8
- package/src/jobs/__tests__/jobs-events.integration.test.ts +37 -1
- package/src/jobs/__tests__/jobs-pii-kms.integration.test.ts +120 -0
- package/src/jobs/__tests__/jobs-screens.boot.test.ts +36 -0
- package/src/jobs/__tests__/jobs-security.integration.test.ts +108 -0
- package/src/jobs/__tests__/reindex-entity-job.integration.test.ts +169 -0
- package/src/jobs/constants.ts +8 -1
- package/src/jobs/feature.ts +52 -8
- package/src/jobs/handlers/detail.query.ts +6 -0
- package/src/jobs/handlers/list.query.ts +8 -1
- package/src/jobs/handlers/projection-rebuild.job.ts +14 -4
- package/src/jobs/handlers/reindex-entity.job.ts +49 -0
- package/src/jobs/i18n.ts +37 -0
- package/src/jobs/job-instant.ts +9 -0
- package/src/jobs/job-run-table.ts +4 -4
- package/src/jobs/web/client-plugin.tsx +22 -0
- package/src/jobs/web/i18n.ts +12 -0
- package/src/jobs/web/index.ts +4 -0
- package/src/jobs/web/job-run-detail-screen.tsx +180 -0
- package/src/jobs/web/job-runs-screen.tsx +146 -0
- package/src/ledger/__tests__/ledger.integration.test.ts +8 -3
- package/src/ledger/handlers/confirm-schedule-period.write.ts +17 -4
- package/src/ledger/recurring.ts +17 -8
- package/src/ledger/web/index.ts +3 -2
- package/src/legal-pages/__tests__/legal-pages.integration.test.ts +55 -0
- package/src/legal-pages/feature.ts +24 -31
- package/src/legal-pages/index.ts +1 -0
- package/src/mail-foundation/__tests__/feature.test.ts +5 -6
- package/src/mail-foundation/__tests__/mail-foundation.integration.test.ts +4 -3
- package/src/mail-foundation/__tests__/mail-transport-contract.ts +58 -0
- package/src/mail-foundation/feature.ts +26 -24
- package/src/mail-transport-inmemory/__tests__/feature.test.ts +23 -0
- package/src/mail-transport-smtp/__tests__/feature.test.ts +65 -0
- package/src/managed-pages/__tests__/branding-coerce.test.ts +2 -6
- package/src/managed-pages/__tests__/i18n-surface.boot.test.ts +30 -0
- package/src/managed-pages/__tests__/managed-pages.integration.test.ts +137 -0
- package/src/managed-pages/feature.ts +45 -47
- package/src/managed-pages/handlers/branding.query.ts +5 -1
- package/src/managed-pages/handlers/by-tenant-published.query.ts +52 -0
- package/src/managed-pages/i18n.ts +66 -0
- package/src/managed-pages/screens/page-screens.ts +5 -1
- package/src/managed-pages/web/client-plugin.tsx +22 -0
- package/src/managed-pages/web/i18n.ts +24 -0
- package/src/managed-pages/web/index.ts +3 -0
- package/src/page-render/__tests__/layout.test.ts +63 -0
- package/src/page-render/__tests__/markdown.test.ts +29 -0
- package/src/page-render/branding.ts +4 -3
- package/src/page-render/index.ts +1 -1
- package/src/page-render/layout.ts +18 -3
- package/src/page-render/markdown.ts +1 -9
- package/src/page-render/web.ts +13 -0
- package/src/personal-access-tokens/__tests__/feature.test.ts +42 -0
- package/src/personal-access-tokens/__tests__/pat.integration.test.ts +239 -0
- package/src/personal-access-tokens/__tests__/scopes.test.ts +42 -0
- package/src/personal-access-tokens/constants.ts +33 -0
- package/src/personal-access-tokens/feature.ts +105 -0
- package/src/personal-access-tokens/handlers/available-scopes.query.ts +21 -0
- package/src/personal-access-tokens/handlers/create.write.ts +47 -0
- package/src/personal-access-tokens/handlers/list.query.ts +50 -0
- package/src/personal-access-tokens/handlers/revoke.write.ts +37 -0
- package/src/personal-access-tokens/hash.ts +17 -0
- package/src/personal-access-tokens/i18n.ts +5 -0
- package/src/personal-access-tokens/index.ts +31 -0
- package/src/personal-access-tokens/resolver.ts +58 -0
- package/src/personal-access-tokens/roles.ts +29 -0
- package/src/personal-access-tokens/schema/api-token.ts +63 -0
- package/src/personal-access-tokens/scopes.ts +43 -0
- package/src/personal-access-tokens/web/client-plugin.tsx +29 -0
- package/src/personal-access-tokens/web/i18n.ts +69 -0
- package/src/personal-access-tokens/web/index.ts +7 -0
- package/src/personal-access-tokens/web/pat-tokens-screen.tsx +265 -0
- package/src/readiness/__tests__/readiness.integration.test.ts +4 -3
- package/src/renderer-simple/__tests__/resolve-variables.test.ts +37 -0
- package/src/renderer-simple/resolve-variables.ts +3 -1
- package/src/secrets/__tests__/rotate.integration.test.ts +115 -18
- package/src/secrets/handlers/rotate.job.ts +77 -98
- package/src/secrets/secrets-context.ts +7 -38
- package/src/secrets/table.ts +7 -8
- package/src/seo/__tests__/llms-txt.test.ts +38 -0
- package/src/seo/__tests__/robots-txt.test.ts +18 -0
- package/src/seo/__tests__/schema-builders.test.ts +57 -0
- package/src/seo/__tests__/seo.integration.test.ts +350 -0
- package/src/seo/__tests__/sitemap.test.ts +38 -0
- package/src/seo/constants.ts +60 -0
- package/src/seo/feature.ts +316 -0
- package/src/seo/handlers/seo-config.query.ts +35 -0
- package/src/seo/index.ts +19 -0
- package/src/seo/llms-txt.ts +33 -0
- package/src/seo/robots-txt.ts +13 -0
- package/src/seo/schema-builders.ts +57 -0
- package/src/seo/sitemap.ts +33 -0
- package/src/sessions/__tests__/auto-revoke-binding.test.ts +71 -0
- package/src/sessions/__tests__/cleanup.integration.test.ts +2 -1
- package/src/sessions/__tests__/password-auto-revoke.integration.test.ts +11 -7
- package/src/sessions/__tests__/rebuild-survival.integration.test.ts +18 -7
- package/src/sessions/__tests__/session-store-registration.test.ts +21 -0
- package/src/sessions/__tests__/sessions-screens.boot.test.ts +55 -0
- package/src/sessions/__tests__/sessions.integration.test.ts +272 -20
- package/src/sessions/__tests__/test-helpers.ts +16 -3
- package/src/sessions/constants.ts +5 -0
- package/src/sessions/db/queries/cleanup.ts +2 -2
- package/src/sessions/feature.ts +175 -26
- package/src/sessions/handlers/detail.query.ts +36 -0
- package/src/sessions/handlers/list.query.ts +14 -9
- package/src/sessions/handlers/mine.query.ts +13 -8
- package/src/sessions/handlers/revoke-all-for-user.write.ts +51 -12
- package/src/sessions/handlers/revoke-all-others.write.ts +19 -1
- package/src/sessions/handlers/revoke.write.ts +13 -0
- package/src/sessions/i18n.ts +23 -0
- package/src/sessions/index.ts +9 -2
- package/src/sessions/schema/user-session.ts +8 -2
- package/src/sessions/session-callbacks.ts +99 -14
- package/src/sessions/session-checker-fail-open.test.ts +77 -0
- package/src/sessions/session-revoked-event.ts +29 -0
- package/src/sessions/testing.ts +14 -1
- package/src/shared/__tests__/chunked-entity-migration.test.ts +145 -0
- package/src/shared/chunked-entity-migration.ts +89 -0
- package/src/shared/decrypt-stored-pii.ts +26 -0
- package/src/shared/encrypt-for-direct-write.ts +23 -0
- package/src/shared/entities-of.ts +17 -0
- package/src/shared/grace-period.test.ts +26 -0
- package/src/shared/grace-period.ts +20 -0
- package/src/{auth-email-password/__tests__ → shared}/identity-v3-hash.test.ts +2 -2
- package/src/shared/index.ts +16 -0
- package/src/shared/map-with-concurrency.test.ts +104 -0
- package/src/shared/map-with-concurrency.ts +38 -0
- package/src/shared/password-hashing.test.ts +35 -0
- package/src/{auth-email-password → shared}/password-hashing.ts +11 -0
- package/src/shared/system-query.ts +5 -0
- package/src/{auth-email-password → shared}/token-burn-store.ts +1 -1
- package/src/subscription-mollie/__tests__/feature.test.ts +97 -0
- package/src/subscription-mollie/__tests__/mollie-foundation.integration.test.ts +12 -1
- package/src/subscription-mollie/__tests__/verify-webhook.test.ts +21 -0
- package/src/subscription-mollie/verify-webhook.ts +1 -0
- package/src/subscription-stripe/__tests__/feature.test.ts +127 -1
- package/src/subscription-stripe/__tests__/runtime.test.ts +14 -24
- package/src/subscription-stripe/__tests__/stripe-foundation.integration.test.ts +15 -5
- package/src/subscription-stripe/__tests__/verify-webhook.test.ts +20 -0
- package/src/subscription-stripe/feature.ts +2 -0
- package/src/subscription-stripe/verify-webhook.ts +3 -2
- package/src/tags/__tests__/schemas.test.ts +34 -0
- package/src/tags/__tests__/tags.integration.test.ts +12 -1
- package/src/tags/entity.ts +6 -1
- package/src/tags/feature.ts +2 -0
- package/src/tags/i18n.ts +5 -0
- package/src/tags/schemas.ts +9 -2
- package/src/tags/web/__tests__/tag-manager.test.tsx +333 -0
- package/src/tags/web/__tests__/tag-section.test.tsx +47 -1
- package/src/tags/web/tag-manager.tsx +1 -1
- package/src/tags/web/tag-section.tsx +6 -3
- package/src/template-resolver/testing.ts +2 -1
- package/src/tenant/__tests__/members-query-kms.integration.test.ts +98 -0
- package/src/tenant/__tests__/members-screens.boot.test.ts +51 -0
- package/src/tenant/__tests__/multi-tenant.integration.test.ts +1 -1
- package/src/tenant/__tests__/tenant-security.integration.test.ts +310 -0
- package/src/tenant/__tests__/tenant.integration.test.ts +8 -4
- package/src/tenant/constants.ts +5 -0
- package/src/tenant/feature.ts +19 -0
- package/src/tenant/handlers/active-tenant-ids.query.ts +8 -2
- package/src/tenant/handlers/cancel-invitation.write.ts +2 -2
- package/src/tenant/handlers/invitations.query.ts +21 -4
- package/src/tenant/handlers/members.query.ts +41 -6
- package/src/tenant/i18n.ts +28 -0
- package/src/tenant/index.ts +7 -2
- package/src/tenant/invitation-table.ts +3 -2
- package/src/tenant/schema/tenant.ts +27 -2
- package/src/tenant/screens.ts +3 -2
- package/src/tenant/seeding.ts +136 -3
- package/src/tenant/web/client-plugin.tsx +20 -0
- package/src/tenant/web/i18n.ts +43 -0
- package/src/tenant/web/index.ts +4 -0
- package/src/tenant/web/members-screen.tsx +270 -0
- package/src/tenant-lifecycle/__tests__/stages.test.ts +22 -0
- package/src/tenant-lifecycle/__tests__/tenant-lifecycle.integration.test.ts +471 -0
- package/src/tenant-lifecycle/boot-checks.ts +45 -0
- package/src/tenant-lifecycle/constants.ts +56 -0
- package/src/tenant-lifecycle/events.ts +46 -0
- package/src/tenant-lifecycle/feature.ts +112 -0
- package/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +79 -0
- package/src/tenant-lifecycle/handlers/request-destruction.write.ts +83 -0
- package/src/tenant-lifecycle/index.ts +7 -0
- package/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +16 -0
- package/src/tenant-lifecycle/lifecycle-gate.ts +65 -0
- package/src/tenant-lifecycle/run-tenant-destroy.ts +368 -0
- package/src/tenant-lifecycle/stages.ts +206 -0
- package/src/tenant-settings/__tests__/tenant-settings.integration.test.ts +115 -0
- package/src/tenant-settings/config.ts +44 -0
- package/src/tenant-settings/constants.ts +16 -0
- package/src/tenant-settings/feature.ts +49 -0
- package/src/tenant-settings/index.ts +8 -0
- package/src/tenant-settings/tenant-defaults.ts +67 -0
- package/src/text-content/web/__tests__/editor-read-only.test.tsx +33 -6
- package/src/text-content/web/__tests__/group-blocks.test.ts +28 -3
- package/src/text-content/web/client-plugin.tsx +126 -104
- package/src/tier-engine/__tests__/auto-default-tier.integration.test.ts +1 -1
- package/src/tier-engine/__tests__/resolver.integration.test.ts +1 -1
- package/src/tier-engine/__tests__/tier-engine.integration.test.ts +7 -4
- package/src/tier-engine/__tests__/trial-config-validation.test.ts +30 -0
- package/src/tier-engine/feature.ts +13 -6
- package/src/tier-engine/i18n.ts +8 -0
- package/src/tier-engine/web/tier-admin-screen.tsx +26 -19
- package/src/user/__tests__/stream-tenant-backfill.integration.test.ts +186 -0
- package/src/user/__tests__/user.integration.test.ts +26 -0
- package/src/user/constants.ts +1 -0
- package/src/user/db/queries/stream-tenant-backfill.ts +112 -0
- package/src/user/feature.ts +3 -0
- package/src/user/handlers/find-for-auth.query.ts +8 -6
- package/src/user/i18n.ts +20 -0
- package/src/user/index.ts +4 -0
- package/src/user/schema/user.ts +6 -2
- package/src/user/screens.ts +3 -15
- package/src/user/seeding.ts +8 -0
- package/src/user-data-rights/COMPLIANCE.md +21 -1
- package/src/user-data-rights/__tests__/anonymous-deletion-kms.integration.test.ts +145 -0
- package/src/user-data-rights/__tests__/anonymous-deletion.integration.test.ts +3 -0
- package/src/user-data-rights/__tests__/audit-log.integration.test.ts +67 -0
- package/src/user-data-rights/__tests__/boot-checks.test.ts +170 -0
- package/src/user-data-rights/__tests__/cross-data-matrix.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/download-by-token-resolver-trust.integration.test.ts +169 -0
- package/src/user-data-rights/__tests__/download.integration.test.ts +101 -33
- package/src/user-data-rights/__tests__/email-templates.test.ts +15 -0
- package/src/user-data-rights/__tests__/export-encrypted-fields.integration.test.ts +154 -0
- package/src/user-data-rights/__tests__/export-job-idempotency.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/export-job-list-cross-tenant.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/file-binary-forget-cleanup.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/file-binary-forget-failure.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/file-retention.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/file-storage-unification.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/forget-cleanup-hook-ordering.integration.test.ts +41 -62
- package/src/user-data-rights/__tests__/forget-hook-registry.integration.test.ts +110 -0
- package/src/user-data-rights/__tests__/inspector-screens.boot.test.ts +14 -0
- package/src/user-data-rights/__tests__/mail-default-bridge.integration.test.ts +19 -2
- package/src/user-data-rights/__tests__/read-users-rebuild-survives-lifecycle.integration.test.ts +25 -14
- package/src/user-data-rights/__tests__/request-cancel-deletion.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/request-deletion-callback.integration.test.ts +4 -1
- package/src/user-data-rights/__tests__/request-export.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/restriction-flow.integration.test.ts +172 -19
- package/src/user-data-rights/__tests__/run-export-jobs-cron-context.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/run-export-jobs.integration.test.ts +257 -26
- package/src/user-data-rights/__tests__/run-forget-cleanup.integration.test.ts +339 -5
- package/src/user-data-rights/__tests__/run-user-export.integration.test.ts +77 -1
- package/src/user-data-rights/__tests__/tenant-model-erasure.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/user-data-rights.integration.test.ts +9 -1
- package/src/user-data-rights/boot-checks.ts +70 -0
- package/src/user-data-rights/db/queries/__tests__/forget-cleanup.integration.test.ts +69 -0
- package/src/user-data-rights/db/queries/forget-cleanup.ts +9 -2
- package/src/user-data-rights/email-templates.ts +6 -6
- package/src/user-data-rights/feature.ts +162 -43
- package/src/user-data-rights/handlers/cancel-deletion.write.ts +8 -11
- package/src/user-data-rights/handlers/deletion-grace-period.ts +4 -1
- package/src/user-data-rights/handlers/download-by-job.query.ts +26 -18
- package/src/user-data-rights/handlers/download-by-token.query.ts +23 -15
- package/src/user-data-rights/handlers/lift-restriction.write.ts +44 -19
- package/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -0
- package/src/user-data-rights/handlers/my-audit-log.query.ts +1 -0
- package/src/user-data-rights/handlers/request-deletion-by-email.write.ts +3 -1
- package/src/user-data-rights/handlers/restrict-account.write.ts +58 -7
- package/src/user-data-rights/handlers/run-forget-cleanup.write.ts +2 -0
- package/src/user-data-rights/i18n.ts +35 -32
- package/src/user-data-rights/lib/is-admin-actor.ts +19 -0
- package/src/user-data-rights/lib/storage-provider-resolver.ts +6 -5
- package/src/user-data-rights/lib/update-user-lifecycle.ts +8 -24
- package/src/user-data-rights/run-export-jobs.ts +55 -19
- package/src/user-data-rights/run-forget-cleanup.ts +112 -7
- package/src/user-data-rights/run-user-export.ts +70 -4
- package/src/user-data-rights/schema/download-token.ts +5 -3
- package/src/user-data-rights/schema/export-job.ts +2 -0
- package/src/user-data-rights/screens.ts +2 -1
- package/src/user-data-rights/web/__tests__/privacy-center-screen.test.tsx +1 -0
- package/src/user-data-rights/web/__tests__/public-deletion-gate.test.tsx +7 -1
- package/src/user-data-rights/web/client-plugin.tsx +6 -1
- package/src/user-data-rights/web/i18n.ts +30 -10
- package/src/user-data-rights/web/privacy-center-screen.tsx +5 -3
- package/src/user-data-rights-defaults/__tests__/bundled-entities.userdata-hooks.integration.test.ts +455 -0
- package/src/user-data-rights-defaults/__tests__/feature-mounted.test.ts +24 -0
- package/src/user-data-rights-defaults/__tests__/user-data-rights-defaults.integration.test.ts +33 -9
- package/src/user-data-rights-defaults/feature.ts +78 -1
- package/src/user-data-rights-defaults/hooks/api-token.userdata-hook.ts +37 -0
- package/src/user-data-rights-defaults/hooks/config-value.userdata-hook.ts +51 -0
- package/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +37 -0
- package/src/user-data-rights-defaults/hooks/feature-mounted.ts +10 -0
- package/src/user-data-rights-defaults/hooks/in-app-message.userdata-hook.ts +38 -0
- package/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +35 -0
- package/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +54 -0
- package/src/user-data-rights-defaults/hooks/tenant-invitation.userdata-hook.ts +112 -0
- package/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +42 -0
- package/src/user-data-rights-defaults/index.ts +26 -0
- package/src/user-profile/__tests__/change-email.integration.test.ts +7 -1
- package/src/user-profile/__tests__/profile-screen.test.tsx +5 -0
- package/src/user-profile/feature.ts +4 -1
- package/src/user-profile/handlers/change-email.write.ts +15 -10
- package/src/user-profile/web/profile-screen.tsx +15 -3
- package/src/auth-email-password/stream-tenant.ts +0 -31
- package/src/feature-toggles/db/queries/toggle-state.ts +0 -25
- package/src/legal-pages/security-headers.ts +0 -1
- package/src/sessions/schema/index.ts +0 -5
- package/src/tenant/schema/index.ts +0 -5
- package/src/user/schema/index.ts +0 -5
- /package/src/{auth-email-password → shared}/identity-v3-hash.ts +0 -0
|
@@ -12,11 +12,12 @@
|
|
|
12
12
|
// downloadStorageKey wird genullt + storage-key geloescht
|
|
13
13
|
// 6. Idempotency: 2× run → kein Re-Processing von done/failed-Jobs
|
|
14
14
|
|
|
15
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
15
|
+
import { afterAll, beforeAll, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
16
16
|
import { spawn } from "node:child_process";
|
|
17
17
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
18
18
|
import { tmpdir } from "node:os";
|
|
19
19
|
import { join } from "node:path";
|
|
20
|
+
import { authFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
|
|
20
21
|
import { asRawClient, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
21
22
|
import { createEventsTable, eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
22
23
|
import {
|
|
@@ -38,7 +39,7 @@ import {
|
|
|
38
39
|
tenantComplianceProfileTable,
|
|
39
40
|
} from "../../compliance-profiles";
|
|
40
41
|
import { createDataRetentionFeature } from "../../data-retention";
|
|
41
|
-
import { createSessionsFeature } from "../../sessions";
|
|
42
|
+
import { createSessionsFeature, userSessionEntity } from "../../sessions";
|
|
42
43
|
import { tenantMembershipsTable } from "../../tenant";
|
|
43
44
|
import { createUserFeature, USER_STATUS, userEntity, userTable } from "../../user";
|
|
44
45
|
import { createUserDataRightsFeature } from "../feature";
|
|
@@ -59,6 +60,7 @@ beforeAll(async () => {
|
|
|
59
60
|
createUserFeature(),
|
|
60
61
|
createDataRetentionFeature(),
|
|
61
62
|
createComplianceProfilesFeature(),
|
|
63
|
+
authFoundationFeature,
|
|
62
64
|
createSessionsFeature(),
|
|
63
65
|
|
|
64
66
|
createUserDataRightsFeature(),
|
|
@@ -68,6 +70,7 @@ beforeAll(async () => {
|
|
|
68
70
|
await unsafeCreateEntityTable(stack.db, exportDownloadTokenEntity);
|
|
69
71
|
await unsafeCreateEntityTable(stack.db, tenantComplianceProfileEntity);
|
|
70
72
|
await unsafeCreateEntityTable(stack.db, userEntity);
|
|
73
|
+
await unsafeCreateEntityTable(stack.db, userSessionEntity);
|
|
71
74
|
await createEventsTable(stack.db);
|
|
72
75
|
// tenant-membership-table fuer runUserExport's Cross-Tenant-Iteration.
|
|
73
76
|
// Pattern matched user-data-rights-defaults integration-test.
|
|
@@ -144,6 +147,21 @@ async function seedPendingJob(opts: { user?: typeof aliceUser } = {}): Promise<s
|
|
|
144
147
|
return result.jobId;
|
|
145
148
|
}
|
|
146
149
|
|
|
150
|
+
// Force a UNIQUE-violation on read_export_download_tokens.job_id (test-fixture,
|
|
151
|
+
// direct-INSERT is a test-only exemption) — the worker's tokenCrud.create then
|
|
152
|
+
// fails with constraintName "read_export_download_tokens_one_per_job",
|
|
153
|
+
// deterministically flipping the job to failed for the tests below.
|
|
154
|
+
async function seedConflictingDownloadToken(jobId: string): Promise<void> {
|
|
155
|
+
await asRawClient(stack.db).unsafe(
|
|
156
|
+
`
|
|
157
|
+
INSERT INTO read_export_download_tokens
|
|
158
|
+
(id, tenant_id, job_id, token_hash, issued_at, expires_at, version, inserted_at, modified_at)
|
|
159
|
+
VALUES (gen_random_uuid(), $1, $2, $3, now(), now() + interval '7 days', 1, now(), now())
|
|
160
|
+
`,
|
|
161
|
+
[tenantA, jobId, "existing-hash"],
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
describe("runExportJobs :: happy path", () => {
|
|
148
166
|
test("pending Job → Worker pickt → done mit downloadStorageKey + bytesWritten", async () => {
|
|
149
167
|
const jobId = await seedPendingJob();
|
|
@@ -384,6 +402,47 @@ describe("runExportJobs :: storage-cleanup", () => {
|
|
|
384
402
|
expect(result.cleanedJobIds).not.toContain(jobId);
|
|
385
403
|
expect(await provider.exists(storageKey)).toBe(true);
|
|
386
404
|
});
|
|
405
|
+
|
|
406
|
+
test("storage-delete Throw → Job bleibt uncleaned (retry naechster Pass)", async () => {
|
|
407
|
+
const jobId = await seedPendingJob();
|
|
408
|
+
const T = getTemporal();
|
|
409
|
+
const longAgo = T.Instant.fromEpochMilliseconds(Date.now() - 365 * 24 * 60 * 60 * 1000);
|
|
410
|
+
const storageKey = `${tenantA}/exports/${jobId}.zip`;
|
|
411
|
+
const provider = await buildProvider(tenantA);
|
|
412
|
+
await provider.write(storageKey, new Uint8Array([7, 8, 9]));
|
|
413
|
+
|
|
414
|
+
await updateRows(
|
|
415
|
+
stack.db,
|
|
416
|
+
exportJobsTable,
|
|
417
|
+
{
|
|
418
|
+
status: EXPORT_JOB_STATUS.Done,
|
|
419
|
+
startedAt: longAgo,
|
|
420
|
+
completedAt: longAgo,
|
|
421
|
+
downloadStorageKey: storageKey,
|
|
422
|
+
expiresAt: longAgo,
|
|
423
|
+
},
|
|
424
|
+
{ id: jobId },
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
const result = await runExportJobs({
|
|
428
|
+
db: stack.db,
|
|
429
|
+
registry: stack.registry,
|
|
430
|
+
buildStorageProvider: async () => ({
|
|
431
|
+
...provider,
|
|
432
|
+
delete: async () => {
|
|
433
|
+
throw new Error("synthetic storage delete failure");
|
|
434
|
+
},
|
|
435
|
+
}),
|
|
436
|
+
now: NOW(),
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
expect(result.cleanedJobIds).not.toContain(jobId);
|
|
440
|
+
expect(await provider.exists(storageKey)).toBe(true);
|
|
441
|
+
const [row] = (await selectMany(stack.db, exportJobsTable, { id: jobId })) as Array<{
|
|
442
|
+
downloadStorageKey: string | null;
|
|
443
|
+
}>;
|
|
444
|
+
expect(row?.downloadStorageKey).toBe(storageKey);
|
|
445
|
+
});
|
|
387
446
|
});
|
|
388
447
|
|
|
389
448
|
describe("runExportJobs :: idempotency", () => {
|
|
@@ -573,6 +632,67 @@ describe("runExportJobs :: Atom 4a download-tokens", () => {
|
|
|
573
632
|
expect(tokenRows).toHaveLength(1);
|
|
574
633
|
});
|
|
575
634
|
|
|
635
|
+
test("Re-Run (fw#832): Job zurueck auf pending → Token in place rotiert, kein 2. created-Event", async () => {
|
|
636
|
+
const jobId = await seedPendingJob();
|
|
637
|
+
const first = await runExportJobs({
|
|
638
|
+
db: stack.db,
|
|
639
|
+
registry: stack.registry,
|
|
640
|
+
buildStorageProvider: buildProvider,
|
|
641
|
+
now: NOW(),
|
|
642
|
+
});
|
|
643
|
+
const firstPlain = first.tokenByJobId.get(jobId);
|
|
644
|
+
expect(firstPlain).toBeDefined();
|
|
645
|
+
|
|
646
|
+
const [tokenBefore] = (await selectMany(stack.db, exportDownloadTokensTable, {
|
|
647
|
+
jobId,
|
|
648
|
+
})) as Array<{ id: string }>;
|
|
649
|
+
|
|
650
|
+
// Operator-Recovery (Email-Fail, plain verloren): NUR den Job auf
|
|
651
|
+
// pending flippen — die Token-Row bleibt liegen. Vor fw#832 created
|
|
652
|
+
// der Worker dann ein ZWEITES Aggregat fuers gleiche jobId und der
|
|
653
|
+
// Projection-Rebuild kollidierte dauerhaft am one_per_job-Index.
|
|
654
|
+
await updateRows(
|
|
655
|
+
stack.db,
|
|
656
|
+
exportJobsTable,
|
|
657
|
+
{ status: EXPORT_JOB_STATUS.Pending },
|
|
658
|
+
{ id: jobId },
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
const second = await runExportJobs({
|
|
662
|
+
db: stack.db,
|
|
663
|
+
registry: stack.registry,
|
|
664
|
+
buildStorageProvider: buildProvider,
|
|
665
|
+
now: NOW(),
|
|
666
|
+
});
|
|
667
|
+
expect(second.completedJobIds).toContain(jobId);
|
|
668
|
+
const secondPlain = second.tokenByJobId.get(jobId);
|
|
669
|
+
expect(secondPlain).toBeDefined();
|
|
670
|
+
expect(secondPlain).not.toBe(firstPlain);
|
|
671
|
+
|
|
672
|
+
// Genau EINE Row, GLEICHES Aggregat, frischer Hash, Audit-Reset.
|
|
673
|
+
const tokenRows = (await selectMany(stack.db, exportDownloadTokensTable, {
|
|
674
|
+
jobId,
|
|
675
|
+
})) as Array<{
|
|
676
|
+
id: string;
|
|
677
|
+
tokenHash: string;
|
|
678
|
+
useCount: number | null;
|
|
679
|
+
lastUsedAt: unknown;
|
|
680
|
+
}>;
|
|
681
|
+
expect(tokenRows).toHaveLength(1);
|
|
682
|
+
expect(tokenRows[0]?.id).toBe(tokenBefore?.id as string);
|
|
683
|
+
expect(tokenRows[0]?.tokenHash).toBe(await hashDownloadToken(secondPlain as string));
|
|
684
|
+
expect(tokenRows[0]?.useCount).toBe(0);
|
|
685
|
+
expect(tokenRows[0]?.lastUsedAt).toBeNull();
|
|
686
|
+
|
|
687
|
+
// Rebuild-Invariante: genau EIN created-Event — der one_per_job-
|
|
688
|
+
// Index kann beim Replay nie kollidieren.
|
|
689
|
+
const events = (await asRawClient(stack.db).unsafe(
|
|
690
|
+
`SELECT type FROM kumiko_events WHERE aggregate_type = 'export-download-token'`,
|
|
691
|
+
)) as unknown as Array<{ type: string }>;
|
|
692
|
+
expect(events.filter((e) => e.type === "export-download-token.created")).toHaveLength(1);
|
|
693
|
+
expect(events.some((e) => e.type === "export-download-token.updated")).toBe(true);
|
|
694
|
+
});
|
|
695
|
+
|
|
576
696
|
test("failed-Job: kein Token wird generiert", async () => {
|
|
577
697
|
// Bewusst keinen Job — leerer Pending-Pass. Aber wir koennen den
|
|
578
698
|
// failure-Pfad pinnen via runUserExport-Fehler. Einfacher: nur
|
|
@@ -602,28 +722,7 @@ describe("runExportJobs :: Atom 4a download-tokens", () => {
|
|
|
602
722
|
// schreibt ZIP, versucht Token-create → UNIQUE hits → throw.
|
|
603
723
|
const jobId = await seedPendingJob();
|
|
604
724
|
|
|
605
|
-
|
|
606
|
-
// direct-INSERT (Test-Exemption). Worker's tokenCrud.create wird
|
|
607
|
-
// dann mit constraintName "read_export_download_tokens_one_per_job"
|
|
608
|
-
// failen.
|
|
609
|
-
await asRawClient(stack.db).unsafe(
|
|
610
|
-
`
|
|
611
|
-
INSERT INTO read_export_download_tokens
|
|
612
|
-
(id, tenant_id, job_id, token_hash, issued_at, expires_at, version, inserted_at, modified_at)
|
|
613
|
-
VALUES (
|
|
614
|
-
gen_random_uuid(),
|
|
615
|
-
$1,
|
|
616
|
-
$2,
|
|
617
|
-
$3,
|
|
618
|
-
now(),
|
|
619
|
-
now() + interval '7 days',
|
|
620
|
-
1,
|
|
621
|
-
now(),
|
|
622
|
-
now()
|
|
623
|
-
)
|
|
624
|
-
`,
|
|
625
|
-
[tenantA, jobId, "existing-hash"],
|
|
626
|
-
);
|
|
725
|
+
await seedConflictingDownloadToken(jobId);
|
|
627
726
|
|
|
628
727
|
const result = await runExportJobs({
|
|
629
728
|
db: stack.db,
|
|
@@ -644,6 +743,133 @@ describe("runExportJobs :: Atom 4a download-tokens", () => {
|
|
|
644
743
|
expect(row?.errorMessage).toMatch(/Token-Creation failed/);
|
|
645
744
|
});
|
|
646
745
|
|
|
746
|
+
test("failed-Job: sendExportFailedEmail wird mit errorMessage + userEmail gerufen", async () => {
|
|
747
|
+
const jobId = await seedPendingJob();
|
|
748
|
+
|
|
749
|
+
await seedConflictingDownloadToken(jobId);
|
|
750
|
+
|
|
751
|
+
type SentArgs = {
|
|
752
|
+
userId: string;
|
|
753
|
+
userEmail: string;
|
|
754
|
+
jobId: string;
|
|
755
|
+
errorMessage: string;
|
|
756
|
+
tenantId: string;
|
|
757
|
+
};
|
|
758
|
+
const sentEmails: SentArgs[] = [];
|
|
759
|
+
|
|
760
|
+
const result = await runExportJobs({
|
|
761
|
+
db: stack.db,
|
|
762
|
+
registry: stack.registry,
|
|
763
|
+
buildStorageProvider: buildProvider,
|
|
764
|
+
now: NOW(),
|
|
765
|
+
sendExportFailedEmail: async (args) => {
|
|
766
|
+
sentEmails.push(args);
|
|
767
|
+
},
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
expect(result.failedJobIds).toContain(jobId);
|
|
771
|
+
expect(sentEmails).toHaveLength(1);
|
|
772
|
+
const sent = sentEmails[0];
|
|
773
|
+
if (!sent) throw new Error("expected 1 sent email");
|
|
774
|
+
expect(sent.userId).toBe(String(aliceUser.id));
|
|
775
|
+
expect(sent.userEmail).toBe("alice@example.com");
|
|
776
|
+
expect(sent.jobId).toBe(jobId);
|
|
777
|
+
expect(sent.errorMessage).toMatch(/Token-Creation failed/);
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
test("failed-Job ohne Callback: kein Email, Worker-Run succeeded", async () => {
|
|
781
|
+
const jobId = await seedPendingJob();
|
|
782
|
+
await seedConflictingDownloadToken(jobId);
|
|
783
|
+
|
|
784
|
+
const result = await runExportJobs({
|
|
785
|
+
db: stack.db,
|
|
786
|
+
registry: stack.registry,
|
|
787
|
+
buildStorageProvider: buildProvider,
|
|
788
|
+
now: NOW(),
|
|
789
|
+
// Kein sendExportFailedEmail
|
|
790
|
+
});
|
|
791
|
+
expect(result.failedJobIds).toContain(jobId);
|
|
792
|
+
// Kein Email, kein Throw — Worker laeuft normal durch
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
test("failed-Job, sendExportFailedEmail-Throw wird abgefangen (best-effort, kein Batch-Abbruch)", async () => {
|
|
796
|
+
// Two jobs, both forced to fail via the same token-collision mechanism
|
|
797
|
+
// as the tests above — the callback throws for job A only, proving the
|
|
798
|
+
// throw doesn't kill the batch loop before job B's callback fires.
|
|
799
|
+
const bobUser = createTestUser({ id: 8, tenantId: tenantA, roles: ["Member"] });
|
|
800
|
+
await seedRow(stack.db, userTable, {
|
|
801
|
+
id: String(bobUser.id),
|
|
802
|
+
tenantId: tenantA,
|
|
803
|
+
email: "bob-failed@example.com",
|
|
804
|
+
passwordHash: "h",
|
|
805
|
+
displayName: "Bob",
|
|
806
|
+
locale: "de",
|
|
807
|
+
emailVerified: true,
|
|
808
|
+
roles: '["Member"]',
|
|
809
|
+
status: USER_STATUS.Active,
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
const jobAId = await seedPendingJob();
|
|
813
|
+
const jobBId = await seedPendingJob({ user: bobUser });
|
|
814
|
+
for (const jobId of [jobAId, jobBId]) {
|
|
815
|
+
await seedConflictingDownloadToken(jobId);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
const calls: string[] = [];
|
|
819
|
+
// Should not throw despite job A's callback throwing — the try/catch
|
|
820
|
+
// around fireExportFailedCallback swallows it (operator-visibility
|
|
821
|
+
// via console.warn only) and the loop continues to job B. A regress to
|
|
822
|
+
// a fully silent swallow (no log call at all) would still pass every
|
|
823
|
+
// assertion below unless the warn itself is pinned.
|
|
824
|
+
const warnSpy = spyOn(console, "warn").mockImplementation(() => {});
|
|
825
|
+
const result = await runExportJobs({
|
|
826
|
+
db: stack.db,
|
|
827
|
+
registry: stack.registry,
|
|
828
|
+
buildStorageProvider: buildProvider,
|
|
829
|
+
now: NOW(),
|
|
830
|
+
sendExportFailedEmail: async (args) => {
|
|
831
|
+
calls.push(args.jobId);
|
|
832
|
+
if (args.jobId === jobAId) {
|
|
833
|
+
throw new Error("synthetic email transport failure for job A");
|
|
834
|
+
}
|
|
835
|
+
},
|
|
836
|
+
});
|
|
837
|
+
expect(result.failedJobIds).toEqual(expect.arrayContaining([jobAId, jobBId]));
|
|
838
|
+
expect(calls.sort()).toEqual([jobAId, jobBId].sort());
|
|
839
|
+
expect(warnSpy).toHaveBeenCalled();
|
|
840
|
+
warnSpy.mockRestore();
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
test("failed-Job, user ohne email → sendExportFailedEmail skipped (kein Throw)", async () => {
|
|
844
|
+
await resetTestTables(stack.db, [userTable]);
|
|
845
|
+
await seedRow(stack.db, userTable, {
|
|
846
|
+
id: String(aliceUser.id),
|
|
847
|
+
tenantId: tenantA,
|
|
848
|
+
email: "", // empty string — lookupUserEmail returns null
|
|
849
|
+
passwordHash: "hashed",
|
|
850
|
+
displayName: "Alice",
|
|
851
|
+
locale: "de",
|
|
852
|
+
emailVerified: true,
|
|
853
|
+
roles: '["Member"]',
|
|
854
|
+
status: USER_STATUS.Active,
|
|
855
|
+
});
|
|
856
|
+
const jobId = await seedPendingJob();
|
|
857
|
+
await seedConflictingDownloadToken(jobId);
|
|
858
|
+
|
|
859
|
+
let callbackInvoked = false;
|
|
860
|
+
const result = await runExportJobs({
|
|
861
|
+
db: stack.db,
|
|
862
|
+
registry: stack.registry,
|
|
863
|
+
buildStorageProvider: buildProvider,
|
|
864
|
+
now: NOW(),
|
|
865
|
+
sendExportFailedEmail: async () => {
|
|
866
|
+
callbackInvoked = true;
|
|
867
|
+
},
|
|
868
|
+
});
|
|
869
|
+
expect(result.failedJobIds).toContain(jobId);
|
|
870
|
+
expect(callbackInvoked).toBe(false);
|
|
871
|
+
});
|
|
872
|
+
|
|
647
873
|
test("failed-Job mit downloadStorageKey → ZIP wird im Cleanup-Pass entfernt (orphan-fix)", async () => {
|
|
648
874
|
// Atom 4a.fix orphan-cleanup: failed-Jobs haben downloadStorageKey
|
|
649
875
|
// gesetzt (path-pre-claim) — der ZIP-Pfad ist persistiert ab claim.
|
|
@@ -729,6 +955,10 @@ describe("runExportJobs :: Atom 3c file-binaries", () => {
|
|
|
729
955
|
},
|
|
730
956
|
],
|
|
731
957
|
}),
|
|
958
|
+
// no-op: this fixture exercises only the export/file path; the erase
|
|
959
|
+
// side is covered by forget-*.integration.test.ts. Required so the
|
|
960
|
+
// V2 boot gate (export-without-erase) does not reject the stack.
|
|
961
|
+
delete: async () => {},
|
|
732
962
|
});
|
|
733
963
|
});
|
|
734
964
|
|
|
@@ -737,6 +967,7 @@ describe("runExportJobs :: Atom 3c file-binaries", () => {
|
|
|
737
967
|
createUserFeature(),
|
|
738
968
|
createDataRetentionFeature(),
|
|
739
969
|
createComplianceProfilesFeature(),
|
|
970
|
+
authFoundationFeature,
|
|
740
971
|
createSessionsFeature(),
|
|
741
972
|
|
|
742
973
|
createUserDataRightsFeature(),
|
|
@@ -997,7 +1228,7 @@ describe("runExportJobs :: Atom 5 notification-callbacks", () => {
|
|
|
997
1228
|
expect(sent.userEmail).toBe("alice@example.com");
|
|
998
1229
|
expect(sent.jobId).toBe(jobId);
|
|
999
1230
|
expect(sent.downloadUrl).toMatch(
|
|
1000
|
-
/^https:\/\/app\.example\.com\/user-export\/by-token
|
|
1231
|
+
/^https:\/\/app\.example\.com\/user-export\/by-token#token=[A-Za-z0-9_%-]+$/,
|
|
1001
1232
|
);
|
|
1002
1233
|
// plain-token aus dem callback-arg entspricht dem result.tokenByJobId
|
|
1003
1234
|
const plainFromResult = result.tokenByJobId.get(jobId);
|
|
@@ -1044,7 +1275,7 @@ describe("runExportJobs :: Atom 5 notification-callbacks", () => {
|
|
|
1044
1275
|
await seedRow(stack.db, userTable, {
|
|
1045
1276
|
id: String(aliceUser.id),
|
|
1046
1277
|
tenantId: tenantA,
|
|
1047
|
-
email: "" as string, // empty string — lookupUserEmail
|
|
1278
|
+
email: "" as string, // empty string — lookupUserEmail returns null
|
|
1048
1279
|
passwordHash: "h",
|
|
1049
1280
|
displayName: "Alice",
|
|
1050
1281
|
locale: "de",
|