@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.387.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/audit/screens.js +1 -1
- package/dist/auth-email-password/feature.js +1 -1
- package/dist/auth-email-password/handlers/change-password.write.js +3 -3
- package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
- package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
- package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.js +1 -1
- package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
- package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
- package/dist/auth-email-password/index.js +5 -5
- package/dist/auth-email-password/lockout-store.js +1 -1
- package/dist/auth-email-password/seeding.d.ts +42 -45
- package/dist/auth-email-password/seeding.js +51 -53
- package/dist/auth-email-password/signup-token-store.js +8 -8
- package/dist/auth-email-password/testing.js +3 -3
- package/dist/auth-email-password/web/auth-client.d.ts +2 -2
- package/dist/auth-email-password/web/auth-client.js +36 -37
- package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
- package/dist/auth-email-password/web/auth-gate.js +15 -16
- package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
- package/dist/auth-email-password/web/client-plugin.js +4 -5
- package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
- package/dist/auth-email-password/web/constants.js +3 -3
- package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
- package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
- package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
- package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
- package/dist/auth-email-password/web/index.js +5 -5
- package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
- package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
- package/dist/auth-email-password/web/login-screen.d.ts +1 -1
- package/dist/auth-email-password/web/login-screen.js +2 -3
- package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
- package/dist/auth-email-password/web/reset-password-screen.js +12 -13
- package/dist/auth-email-password/web/session.d.ts +10 -9
- package/dist/auth-email-password/web/session.js +28 -29
- package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
- package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
- package/dist/auth-email-password/web/signup-screen.js +13 -13
- package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
- package/dist/auth-email-password/web/tenant-switcher.js +21 -22
- package/dist/auth-email-password/web/use-shell-user.js +12 -13
- package/dist/auth-email-password/web/user-menu.d.ts +4 -4
- package/dist/auth-email-password/web/user-menu.js +12 -13
- package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
- package/dist/auth-email-password/web/verify-email-screen.js +9 -10
- package/dist/auth-foundation/boot-checks.js +4 -4
- package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
- package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
- package/dist/auth-foundation/types.js +2 -2
- package/dist/auth-mfa/handlers/disable.write.js +3 -3
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
- package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
- package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
- package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
- package/dist/auth-mfa/handlers/verify.write.js +1 -1
- package/dist/auth-mfa/token-secrets.js +1 -1
- package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
- package/dist/auth-mfa/web/client-plugin.js +1 -1
- package/dist/auth-mfa/web/i18n.js +3 -3
- package/dist/auth-mfa/web/index.js +4 -4
- package/dist/auth-mfa/web/mfa-client.js +17 -16
- package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.js +18 -17
- package/dist/billing-foundation/feature.js +42 -43
- package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
- package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
- package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
- package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
- package/dist/billing-foundation/handlers/process-event.write.js +20 -20
- package/dist/billing-foundation/projection.d.ts +15 -11
- package/dist/billing-foundation/projection.js +38 -37
- package/dist/billing-foundation/subscription-tier-sync.js +3 -3
- package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
- package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
- package/dist/billing-foundation/types.d.ts +40 -41
- package/dist/billing-foundation/types.js +20 -20
- package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/constants.js +11 -12
- package/dist/cap-counter/enforce-cap.d.ts +59 -62
- package/dist/cap-counter/enforce-cap.js +47 -48
- package/dist/cap-counter/entity.js +29 -29
- package/dist/cap-counter/feature.js +34 -35
- package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
- package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
- package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
- package/dist/cap-counter/stock-cap-guard.js +1 -1
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/smtp-transport.d.ts +18 -17
- package/dist/channel-email/smtp-transport.js +24 -21
- package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
- package/dist/compliance-profiles/feature.js +4 -4
- package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
- package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
- package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
- package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
- package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
- package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
- package/dist/compliance-profiles/schema/profile-selection.js +18 -23
- package/dist/compliance-profiles/seeding.js +14 -15
- package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
- package/dist/compliance-profiles-ops/index.js +2 -2
- package/dist/config/handlers/readiness.query.d.ts +4 -4
- package/dist/config/handlers/readiness.query.js +1 -1
- package/dist/config/handlers/reencrypt.job.js +4 -5
- package/dist/config/handlers/set.write.js +4 -4
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.js +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
- package/dist/custom-fields/aggregate-id.d.ts +12 -13
- package/dist/custom-fields/aggregate-id.js +16 -17
- package/dist/custom-fields/entity.js +49 -47
- package/dist/custom-fields/events.js +7 -8
- package/dist/custom-fields/feature.d.ts +14 -14
- package/dist/custom-fields/feature.js +53 -54
- package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
- package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
- package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
- package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
- package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
- package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
- package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
- package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
- package/dist/custom-fields/lib/field-access.js +2 -2
- package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
- package/dist/custom-fields/lib/quota.js +1 -1
- package/dist/custom-fields/lib/value-schema.js +10 -12
- package/dist/custom-fields/run-retention.js +3 -3
- package/dist/custom-fields/schemas.js +14 -14
- package/dist/custom-fields/web/client-plugin.js +2 -5
- package/dist/custom-fields/web/constants.js +2 -2
- package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
- package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
- package/dist/custom-fields/wire-for-entity.js +65 -67
- package/dist/custom-fields/wire-user-data-rights.js +3 -3
- package/dist/data-retention/_internal/parse-override.js +2 -3
- package/dist/data-retention/feature.js +11 -18
- package/dist/data-retention/handlers/policy-for.query.js +6 -6
- package/dist/data-retention/keep-for.d.ts +7 -7
- package/dist/data-retention/keep-for.js +15 -15
- package/dist/data-retention/override-schema.d.ts +3 -4
- package/dist/data-retention/override-schema.js +13 -15
- package/dist/data-retention/presets.d.ts +4 -5
- package/dist/data-retention/presets.js +18 -23
- package/dist/data-retention/resolve-tenant-preset.js +17 -16
- package/dist/data-retention/resolver.d.ts +12 -12
- package/dist/data-retention/resolver.js +24 -23
- package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
- package/dist/data-retention/run-retention-cleanup.js +61 -51
- package/dist/data-retention/schema/tenant-retention-override.js +13 -11
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe.js +4 -4
- package/dist/document-ingest-foundation/entity.js +4 -4
- package/dist/document-ingest-foundation/events.js +2 -2
- package/dist/document-ingest-foundation/feature.js +2 -2
- package/dist/document-ingest-foundation/pages.js +1 -1
- package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
- package/dist/feature-toggles/compose-tier-resolver.js +1 -1
- package/dist/feature-toggles/feature.js +1 -1
- package/dist/feature-toggles/global-feature-state-table.js +1 -1
- package/dist/feature-toggles/handlers/registered.query.js +5 -5
- package/dist/feature-toggles/toggle-sync-signal.js +1 -1
- package/dist/feature-toggles/web/constants.js +1 -1
- package/dist/file-derivatives/feature.d.ts +1 -1
- package/dist/file-derivatives/feature.js +1 -1
- package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
- package/dist/file-derivatives/presets.js +1 -1
- package/dist/file-foundation/feature.js +6 -6
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/feature.js +16 -16
- package/dist/file-provider-s3/lib/s3-provider.js +6 -6
- package/dist/files/feature.js +6 -6
- package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
- package/dist/files-tenant-data/hooks.js +24 -26
- package/dist/files-tenant-data/index.js +1 -1
- package/dist/folders/feature.d.ts +1 -1
- package/dist/folders/web/folder-manager.js +2 -2
- package/dist/folders/web/tree.js +5 -5
- package/dist/form-draft/db/queries/cleanup.js +1 -1
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/entity.js +3 -3
- package/dist/form-draft/feature.js +4 -5
- package/dist/form-draft/handlers/discard.write.js +1 -1
- package/dist/form-draft/release-file-refs.js +6 -6
- package/dist/form-draft/schemas.js +3 -3
- package/dist/form-draft/web/constants.js +0 -2
- package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
- package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
- package/dist/inbound-mail-foundation/connect-routes.js +4 -3
- package/dist/inbound-mail-foundation/constants.d.ts +22 -24
- package/dist/inbound-mail-foundation/constants.js +30 -33
- package/dist/inbound-mail-foundation/entities.d.ts +12 -12
- package/dist/inbound-mail-foundation/entities.js +47 -48
- package/dist/inbound-mail-foundation/events.d.ts +4 -3
- package/dist/inbound-mail-foundation/events.js +50 -47
- package/dist/inbound-mail-foundation/feature.js +39 -39
- package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
- package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
- package/dist/inbound-mail-foundation/oauth-state.js +11 -10
- package/dist/inbound-mail-foundation/projection.d.ts +4 -4
- package/dist/inbound-mail-foundation/projection.js +31 -29
- package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
- package/dist/inbound-mail-foundation/provider-factory.js +9 -9
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
- package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +45 -46
- package/dist/inbound-mail-foundation/types.js +21 -21
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
- package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
- package/dist/inbound-provider-imap/credential-document.js +13 -13
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +42 -40
- package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
- package/dist/inbound-provider-imap/imap-client.js +20 -19
- package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
- package/dist/inbound-provider-inmemory/feature.js +19 -19
- package/dist/jobs/db/queries/retention.js +2 -2
- package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
- package/dist/jobs/events.js +1 -1
- package/dist/jobs/feature.js +5 -6
- package/dist/jobs/handlers/detail.query.js +4 -4
- package/dist/jobs/handlers/list.query.js +1 -1
- package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
- package/dist/jobs/handlers/reindex-entity.job.js +1 -1
- package/dist/jobs/handlers/retry.write.js +1 -1
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +10 -11
- package/dist/jobs/job-run-table.js +3 -3
- package/dist/jobs/screens.js +1 -1
- package/dist/jobs/tenant-job-failure-table.js +1 -1
- package/dist/jobs/tenant-job-run-table.js +1 -1
- package/dist/ledger/entity.js +5 -5
- package/dist/ledger/feature.js +3 -3
- package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
- package/dist/ledger/recurring.js +12 -12
- package/dist/ledger/schemas.js +1 -1
- package/dist/ledger/web/constants.js +2 -2
- package/dist/ledger/web/index.js +7 -7
- package/dist/legal-pages/feature.d.ts +4 -4
- package/dist/legal-pages/feature.js +25 -26
- package/dist/legal-pages/markdown.js +3 -3
- package/dist/legal-pages/web/client-plugin.js +23 -24
- package/dist/legal-pages/web/index.js +0 -1
- package/dist/mail-foundation/feature.d.ts +2 -2
- package/dist/mail-foundation/feature.js +24 -25
- package/dist/mail-transport-inmemory/feature.d.ts +4 -4
- package/dist/mail-transport-inmemory/feature.js +27 -28
- package/dist/mail-transport-smtp/feature.js +20 -20
- package/dist/managed-pages/branding.js +6 -6
- package/dist/managed-pages/feature.d.ts +26 -26
- package/dist/managed-pages/feature.js +34 -34
- package/dist/managed-pages/handlers/by-slug.query.js +5 -6
- package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
- package/dist/managed-pages/handlers/set.write.js +5 -7
- package/dist/managed-pages/screens/page-screens.js +11 -11
- package/dist/managed-pages/seeding.js +8 -8
- package/dist/managed-pages/table.js +13 -12
- package/dist/managed-pages/web/client-plugin.d.ts +1 -1
- package/dist/managed-pages/web/client-plugin.js +5 -5
- package/dist/managed-pages/web/i18n.js +1 -1
- package/dist/notes-history/entity.js +4 -4
- package/dist/notes-history/feature.d.ts +2 -2
- package/dist/notes-history-user-data/hooks.js +1 -1
- package/dist/page-render/layout.js +9 -9
- package/dist/page-render/markdown.js +11 -11
- package/dist/page-render/security-headers.js +7 -6
- package/dist/personal-access-tokens/feature.js +5 -5
- package/dist/personal-access-tokens/roles.js +2 -2
- package/dist/readiness/handlers/status.query.js +3 -3
- package/dist/renderer-foundation/api.js +12 -13
- package/dist/renderer-foundation/constants.js +2 -2
- package/dist/renderer-foundation/feature.js +7 -7
- package/dist/secrets/feature.js +9 -9
- package/dist/secrets/web/constants.js +2 -2
- package/dist/seo/feature.js +3 -3
- package/dist/sessions/constants.d.ts +1 -1
- package/dist/sessions/constants.js +1 -1
- package/dist/sessions/feature.js +8 -8
- package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
- package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
- package/dist/sessions/handlers/revoke.write.js +1 -1
- package/dist/sessions/schema/user-session.js +4 -4
- package/dist/sessions/screens.js +2 -2
- package/dist/sessions/session-callbacks.js +2 -2
- package/dist/sessions/session-revoked-event.js +2 -2
- package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
- package/dist/shared/decrypt-stored-pii.js +1 -1
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/map-with-concurrency.js +5 -4
- package/dist/shared/parent-visibility.js +2 -2
- package/dist/shared/password-hashing.js +1 -1
- package/dist/shared/signup-handover.js +1 -2
- package/dist/shared/single-use-token-store.js +1 -1
- package/dist/subscription-mollie/constants.js +15 -17
- package/dist/subscription-mollie/feature.d.ts +17 -18
- package/dist/subscription-mollie/feature.js +24 -24
- package/dist/subscription-mollie/index.js +3 -3
- package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
- package/dist/subscription-mollie/plugin-methods.js +15 -14
- package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
- package/dist/subscription-mollie/verify-webhook.js +27 -27
- package/dist/subscription-stripe/constants.js +4 -6
- package/dist/subscription-stripe/feature.d.ts +14 -14
- package/dist/subscription-stripe/feature.js +35 -34
- package/dist/subscription-stripe/index.js +6 -6
- package/dist/subscription-stripe/plugin-methods.js +18 -18
- package/dist/subscription-stripe/runtime.d.ts +1 -1
- package/dist/subscription-stripe/runtime.js +1 -1
- package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
- package/dist/subscription-stripe/verify-webhook.js +59 -61
- package/dist/tags/feature.d.ts +3 -3
- package/dist/tags/screens.js +1 -1
- package/dist/template-resolver/api.js +10 -10
- package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
- package/dist/template-resolver/handlers/list.query.js +1 -1
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
- package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
- package/dist/template-resolver/seeding.js +4 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.js +1 -1
- package/dist/tenant/handlers/members.query.js +1 -1
- package/dist/tenant/handlers/team-list.query.js +1 -1
- package/dist/tenant/handlers/tenant-directory.query.js +1 -1
- package/dist/tenant/invitation-table.js +37 -40
- package/dist/tenant/membership-table.js +3 -3
- package/dist/tenant/schema/tenant.js +7 -9
- package/dist/tenant/screens.js +1 -1
- package/dist/tenant/seeding.d.ts +6 -5
- package/dist/tenant/seeding.js +12 -12
- package/dist/tenant/testing.js +5 -6
- package/dist/tenant/web/constants.js +2 -2
- package/dist/tenant-handover/events.js +5 -7
- package/dist/tenant-handover/feature.js +1 -1
- package/dist/tenant-handover/grant.js +1 -1
- package/dist/tenant-handover/handlers/claim.write.js +1 -1
- package/dist/tenant-handover/move-entity-graph.js +8 -9
- package/dist/tenant-handover/signup-handover-provider.js +1 -2
- package/dist/tenant-handover/transfer-graph.js +4 -5
- package/dist/tenant-lifecycle/boot-checks.js +1 -1
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-settings/constants.js +1 -1
- package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
- package/dist/tenant-settings/tenant-defaults.js +9 -2
- package/dist/tier-engine/aggregate-id.d.ts +11 -11
- package/dist/tier-engine/aggregate-id.js +15 -16
- package/dist/tier-engine/compose-app.d.ts +14 -14
- package/dist/tier-engine/compose-app.js +1 -1
- package/dist/tier-engine/entity.js +18 -19
- package/dist/tier-engine/feature.d.ts +19 -17
- package/dist/tier-engine/feature.js +68 -69
- package/dist/tier-engine/handlers/active-tier.query.js +6 -7
- package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/index.js +4 -4
- package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
- package/dist/user/handlers/create.write.js +4 -4
- package/dist/user/schema/user.d.ts +11 -11
- package/dist/user/schema/user.js +45 -44
- package/dist/user/seeding.d.ts +15 -15
- package/dist/user/seeding.js +28 -28
- package/dist/user/testing.js +3 -3
- package/dist/user-data-rights/audit-download.d.ts +8 -8
- package/dist/user-data-rights/audit-download.js +19 -20
- package/dist/user-data-rights/boot-checks.js +1 -1
- package/dist/user-data-rights/deletion-token.js +1 -1
- package/dist/user-data-rights/feature.d.ts +49 -50
- package/dist/user-data-rights/feature.js +54 -53
- package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
- package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
- package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
- package/dist/user-data-rights/handlers/export-status.query.js +8 -9
- package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
- package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
- package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
- package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
- package/dist/user-data-rights/handlers/request-export.write.js +42 -41
- package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
- package/dist/user-data-rights/index.js +8 -10
- package/dist/user-data-rights/lib/default-mailers.js +3 -3
- package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
- package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
- package/dist/user-data-rights/run-export-jobs.js +127 -233
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +63 -82
- package/dist/user-data-rights/run-user-export.d.ts +34 -33
- package/dist/user-data-rights/run-user-export.js +55 -57
- package/dist/user-data-rights/schema/download-attempt.js +11 -11
- package/dist/user-data-rights/schema/download-token.js +37 -41
- package/dist/user-data-rights/schema/export-job.d.ts +4 -4
- package/dist/user-data-rights/schema/export-job.js +65 -67
- package/dist/user-data-rights/token-helpers.d.ts +8 -9
- package/dist/user-data-rights/token-helpers.js +21 -25
- package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
- package/dist/user-data-rights/web/client-plugin.js +1 -1
- package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
- package/dist/user-data-rights/web/constants.js +1 -1
- package/dist/user-data-rights/web/index.js +5 -5
- package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
- package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
- package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
- package/dist/user-data-rights/zip-path.d.ts +15 -15
- package/dist/user-data-rights/zip-path.js +41 -40
- package/dist/user-data-rights-defaults/feature.js +15 -15
- package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
- package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
- package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
- package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
- package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
- package/dist/user-profile/handlers/change-email.write.js +13 -13
- package/dist/user-profile/index.js +3 -3
- package/dist/user-profile/web/client-plugin.js +1 -1
- package/dist/user-profile/web/constants.js +1 -1
- package/dist/user-profile/web/profile-screen.js +1 -1
- package/dist/workflow-runner/aggregate-id.d.ts +1 -1
- package/dist/workflow-runner/aggregate-id.js +1 -1
- package/dist/workflow-runner/event-subscriber.js +4 -5
- package/dist/workflow-runner/event-trigger.js +4 -17
- package/dist/workflow-runner/feature.js +2 -2
- package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
- package/dist/workflow-runner/pending-projection.js +6 -7
- package/dist/workflow-runner/runner.js +6 -6
- package/dist/workflow-runner/tables.js +6 -6
- package/dist/workflow-runner/workflow-registry.js +1 -1
- package/package.json +10 -10
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// SignupScreen — Magic-Link-
|
|
2
|
+
// SignupScreen — Magic-Link self-signup, Step 1.
|
|
3
3
|
//
|
|
4
|
-
// Form
|
|
5
|
-
// (silent
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// existing
|
|
4
|
+
// Form with an email input. Submission triggers /api/auth/signup-request
|
|
5
|
+
// (silent success, no account enumeration). The UI always shows a
|
|
6
|
+
// "email on its way" confirmation with a Resend button, even if the email
|
|
7
|
+
// is already registered (the server then sends the same email with the
|
|
8
|
+
// existing token from Redis, making the request idempotent).
|
|
9
9
|
//
|
|
10
|
-
//
|
|
11
|
-
// /signup)
|
|
12
|
-
// AuthGate).
|
|
13
|
-
// /signup
|
|
10
|
+
// The app is responsible for mounting the screen at a URL (e.g.
|
|
11
|
+
// /signup) and making it anonymously reachable (AuthPathGate before
|
|
12
|
+
// AuthGate). An apex marketing site can route its "Start for free" link to
|
|
13
|
+
// the /signup path.
|
|
14
14
|
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
15
15
|
import { useState } from "react";
|
|
16
16
|
import { requestSignup } from "./auth-client.js";
|
|
@@ -53,9 +53,9 @@ export function SignupScreen({ title, subtitle, loginHref = "/login", }) {
|
|
|
53
53
|
void doSubmit();
|
|
54
54
|
};
|
|
55
55
|
const onResend = async () => {
|
|
56
|
-
// Resend
|
|
57
|
-
//
|
|
58
|
-
//
|
|
56
|
+
// Resend uses the same endpoint: the server returns the existing
|
|
57
|
+
// token from Redis and sends a second email with the SAME
|
|
58
|
+
// activation link, so the old email remains valid.
|
|
59
59
|
setSubmitting(true);
|
|
60
60
|
setError(null);
|
|
61
61
|
try {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
export type TenantSwitcherProps = {
|
|
3
|
-
/** Optional:
|
|
4
|
-
* Default:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
/** Optional: provides a human-readable name for each tenant ID.
|
|
4
|
+
* Default: displays the ID directly (a short UUID is sufficient for
|
|
5
|
+
* development environments). In production, the host should cache
|
|
6
|
+
* tenant names at login and pass them here. */
|
|
7
7
|
readonly tenantName?: (tenantId: string) => string;
|
|
8
8
|
};
|
|
9
9
|
export declare function TenantSwitcher({ tenantName }: TenantSwitcherProps): ReactNode;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// TenantSwitcher —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// TenantSwitcher — compact dropdown showing the active tenant and
|
|
3
|
+
// allowing switches to other memberships. Uses Radix-DropdownMenu for
|
|
4
|
+
// consistent click-outside, Escape, and keyboard-navigation behavior.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// Switcher).
|
|
6
|
+
// Does NOT render when no user is logged in or when the user has only one
|
|
7
|
+
// tenant (single-tenant apps do not need a switcher).
|
|
9
8
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
9
|
+
// The display name comes from the optional `tenantName` prop or falls back
|
|
10
|
+
// to the ID hash. Design decision: TenantSwitcher does NOT fetch
|
|
11
|
+
// tenant:query:me itself, which would cost round trips per mount and
|
|
12
|
+
// require query-caching infrastructure. Instead, the host passes in the
|
|
13
|
+
// resolver (for example, from a useTenantNames() hook loaded once at app
|
|
14
|
+
// boot).
|
|
16
15
|
import { useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
17
16
|
import { cn, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuLabel, DropdownMenuTrigger, } from "@cosmicdrift/kumiko-renderer/web";
|
|
18
17
|
import { Building2, ChevronDown } from "lucide-react";
|
|
@@ -30,25 +29,25 @@ export function TenantSwitcher({ tenantName }) {
|
|
|
30
29
|
await switchTenant(tenantId);
|
|
31
30
|
}
|
|
32
31
|
finally {
|
|
33
|
-
// In
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
32
|
+
// In practice, switchTenant causes a full-page reload, so we never see
|
|
33
|
+
// the cleared state — `finally` only handles the edge case where
|
|
34
|
+
// switchTenant throws, preventing the UI from remaining stuck with
|
|
35
|
+
// the spinner.
|
|
37
36
|
setSwitching(null);
|
|
38
37
|
}
|
|
39
38
|
}, [activeTenantId, switchTenant]);
|
|
40
|
-
// Label
|
|
41
|
-
// name/key
|
|
42
|
-
//
|
|
39
|
+
// Label priority: app-provided resolver (prop) > server-provided
|
|
40
|
+
// name/key from /auth/tenants > UUID prefix. The latter is only a
|
|
41
|
+
// last resort — it is indistinguishable for seeded tenants (00000000-…).
|
|
43
42
|
const nameOf = (tenantId) => {
|
|
44
43
|
if (tenantName !== undefined)
|
|
45
44
|
return tenantName(tenantId);
|
|
46
45
|
const membership = tenants.find((m) => m.tenantId === tenantId);
|
|
47
|
-
// ||
|
|
46
|
+
// || instead of ??: an empty name/key string must not be used as a label.
|
|
48
47
|
return membership?.name || membership?.key || tenantId.slice(0, 8);
|
|
49
48
|
};
|
|
50
|
-
// Rendering
|
|
51
|
-
// (
|
|
49
|
+
// Rendering gate: no user → nothing; only one tenant → nothing as well
|
|
50
|
+
// (single-tenant apps do not need a switcher).
|
|
52
51
|
if (user === null || tenants.length <= 1)
|
|
53
52
|
return null;
|
|
54
53
|
const activeLabel = activeTenantId !== null ? nameOf(activeTenantId) : t("auth.tenant.switcher.none");
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// custom permission checks).
|
|
1
|
+
// Reads the logged-in user and roles for the active tenant from the session.
|
|
2
|
+
// This hook is the standard bridge between session state and layout components
|
|
3
|
+
// (WorkspaceShell.user, DefaultAppShell gates, custom permission checks).
|
|
5
4
|
//
|
|
6
|
-
// Returns undefined
|
|
7
|
-
// -
|
|
8
|
-
// -
|
|
9
|
-
// -
|
|
10
|
-
//
|
|
5
|
+
// Returns undefined while:
|
|
6
|
+
// - the session is loading (status="loading")
|
|
7
|
+
// - the user is unauthenticated
|
|
8
|
+
// - activeTenantId is missing from the tenants list (a defensive path that
|
|
9
|
+
// should not occur, but is harmless to check)
|
|
11
10
|
//
|
|
12
|
-
// WorkspaceShell
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
11
|
+
// WorkspaceShell and DefaultAppShell treat undefined as "no workspaces
|
|
12
|
+
// visible", which is the correct UX while loading or logged out. Apps that
|
|
13
|
+
// need more (such as a loading indicator) should check useSession().status
|
|
14
|
+
// directly.
|
|
16
15
|
import { useMemo } from "react";
|
|
17
16
|
import { useSession } from "./session.js";
|
|
18
17
|
export function useShellUser() {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
export type UserMenuVariant = "pill" | "sidebar";
|
|
3
3
|
export type UserMenuProps = {
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
4
|
+
/** Additional menu items above logout. The caller controls per-item
|
|
5
|
+
* classes and behavior; this component only provides the surrounding frame. */
|
|
6
6
|
readonly children?: ReactNode;
|
|
7
|
-
/** "pill" (
|
|
8
|
-
*
|
|
7
|
+
/** "pill" (default) = compact top-bar trigger; "sidebar" = full NavUser-
|
|
8
|
+
* row (avatar + name + email) for the App-Shell's `sidebarFooter` slot.
|
|
9
9
|
* Requires a `SidebarProvider` ancestor — the default App-Shell
|
|
10
10
|
* `sidebarFooter` slot already provides one. */
|
|
11
11
|
readonly variant?: UserMenuVariant;
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// UserMenu —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
2
|
+
// UserMenu — avatar dropdown for the top bar (variant="pill", default) or the
|
|
3
|
+
// sidebar footer (variant="sidebar" = the sidebar-07-NavUser-Row). Shows
|
|
4
|
+
// name/email and logout. Uses Radix-DropdownMenu so click-outside, Escape,
|
|
5
|
+
// focus management, keyboard navigation (↑↓/Home/End), and ARIA roles work
|
|
6
|
+
// out of the box.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// Fehler entsteht.
|
|
8
|
+
// Renders nothing when no user is logged in, so hosts can mount the component
|
|
9
|
+
// outside AuthGate without causing a hard error.
|
|
11
10
|
import { useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
12
11
|
import { cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from "@cosmicdrift/kumiko-renderer/web";
|
|
13
12
|
import { ChevronDown, ChevronsUpDown, LogOut } from "lucide-react";
|
|
14
13
|
import { useSession } from "./session.js";
|
|
15
14
|
function initials(value) {
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
15
|
+
// Uses the first and last name when the display name contains a space;
|
|
16
|
+
// otherwise uses the first two characters of the email local part. This is
|
|
17
|
+
// deterministic, so the avatar content does not change between re-renders.
|
|
19
18
|
const trimmed = value.trim();
|
|
20
19
|
if (trimmed.length === 0)
|
|
21
20
|
return "?";
|
|
@@ -34,8 +33,8 @@ export function UserMenu({ children, variant = "pill" }) {
|
|
|
34
33
|
const displayName = hasName ? user.displayName : user.email;
|
|
35
34
|
const avatarText = initials(displayName);
|
|
36
35
|
const content = (_jsxs(DropdownMenuContent, { align: variant === "sidebar" ? "start" : "end", "aria-label": t("auth.user.menu.label"), children: [_jsxs(DropdownMenuLabel, { className: "text-xs", children: [_jsx("div", { className: "font-medium text-foreground truncate", children: displayName }), hasName && _jsx("div", { className: "truncate", children: user.email })] }), _jsx(DropdownMenuSeparator, {}), children !== undefined && (_jsxs(_Fragment, { children: [children, _jsx(DropdownMenuSeparator, {})] })), _jsxs(DropdownMenuItem, { "data-testid": "user-menu-logout", onSelect: () => void logout(), children: [_jsx(LogOut, { className: "h-4 w-4" }), _jsx("span", { children: t("auth.user.menu.logout") })] })] }));
|
|
37
|
-
// Sidebar
|
|
38
|
-
//
|
|
36
|
+
// Sidebar footer: full NavUser row (sidebar-07) as the dropdown trigger —
|
|
37
|
+
// matches SidebarUser visually while providing clickable logout/profile actions.
|
|
39
38
|
if (variant === "sidebar") {
|
|
40
39
|
return (_jsx(SidebarMenu, { children: _jsx(SidebarMenuItem, { children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(SidebarMenuButton, { size: "lg", className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground", children: [_jsx("span", { "aria-hidden": "true", className: "flex size-7 shrink-0 items-center justify-center rounded-full bg-sidebar-accent text-xs font-medium text-sidebar-accent-foreground", children: avatarText }), _jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [_jsx("span", { className: "truncate font-medium text-sidebar-foreground", children: displayName }), hasName && (_jsx("span", { className: "truncate text-xs text-sidebar-muted", children: user.email }))] }), _jsx(ChevronsUpDown, { className: "ml-auto size-4 text-sidebar-muted" })] }) }), content] }) }) }));
|
|
41
40
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
export type VerifyEmailScreenProps = {
|
|
3
3
|
readonly title?: string;
|
|
4
|
-
/** Override
|
|
4
|
+
/** Override the token from the URL. Default: parsed from `?token=...`. */
|
|
5
5
|
readonly token?: string;
|
|
6
|
-
/** href
|
|
6
|
+
/** href for the "Zum Login" link. Default "/login". */
|
|
7
7
|
readonly loginHref?: string;
|
|
8
8
|
};
|
|
9
9
|
export declare function VerifyEmailScreen({ title, token: tokenProp, loginHref, }: VerifyEmailScreenProps): ReactNode;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// VerifyEmailScreen —
|
|
3
|
-
// /api/auth/verify-email
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// VerifyEmailScreen — reads `?token=...` from the URL and automatically sends it to
|
|
3
|
+
// /api/auth/verify-email on mount, then shows success/error. The server-side
|
|
4
|
+
// operation is idempotent (repeating it sets emailVerified=true again), so
|
|
5
|
+
// retries are safe.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// Banner sehen.
|
|
7
|
+
// The empty-deps effect and once guard prevent React Strict Mode from firing
|
|
8
|
+
// the verification call twice (Strict Mode dispatches useEffect twice in dev).
|
|
9
|
+
// The token roundtrip is single-use server-side, but this avoids showing an
|
|
10
|
+
// invalid-token banner after the first valid mount call.
|
|
12
11
|
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
13
12
|
import { useEffect, useRef, useState } from "react";
|
|
14
13
|
import { verifyEmail } from "./auth-client.js";
|
|
@@ -19,7 +18,7 @@ export function VerifyEmailScreen({ title, token: tokenProp, loginHref = "/login
|
|
|
19
18
|
const token = useUrlToken(tokenProp);
|
|
20
19
|
const [status, setStatus] = useState(token === "" ? "missing-token" : "verifying");
|
|
21
20
|
const startedRef = useRef(false);
|
|
22
|
-
// kumiko-lint-ignore no-raw-hooks
|
|
21
|
+
// kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
|
|
23
22
|
useEffect(() => {
|
|
24
23
|
if (status !== "verifying")
|
|
25
24
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Multiplicity boot-check for auth-foundation's `tokenVerifier` extension
|
|
2
|
-
// point
|
|
2
|
+
// point. Two static-shape conflicts a boot-check CAN catch (a
|
|
3
3
|
// runtime shape-match predicate's overlap can't be proven at boot): a
|
|
4
4
|
// malformed plugin registration, and two providers both claiming the same
|
|
5
5
|
// shape (resolveTokenVerifier can't tell them apart). Zero tokenVerifier
|
|
@@ -30,7 +30,7 @@ export function validateTokenVerifierMultiplicity(features) {
|
|
|
30
30
|
}
|
|
31
31
|
if (namesByShape.size === 0) {
|
|
32
32
|
// Session-only apps (email-password + sessions) never hit tokenVerifier —
|
|
33
|
-
// cookie JWT auth uses sessionStore alone
|
|
33
|
+
// cookie JWT auth uses sessionStore alone.
|
|
34
34
|
for (const feature of features) {
|
|
35
35
|
for (const usage of feature.extensionUsages) {
|
|
36
36
|
// skip: sessionStore present — tokenVerifier optional for cookie-session apps.
|
|
@@ -79,7 +79,7 @@ function validateSingleProvider(features, opts) {
|
|
|
79
79
|
`only one ${label} provider may be mounted at a time.`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
// Multiplicity boot-check for the `sessionStore` extension point
|
|
82
|
+
// Multiplicity boot-check for the `sessionStore` extension point.
|
|
83
83
|
// Single-provider, unlike tokenVerifier — no shape to route on, so ≥2 fails
|
|
84
84
|
// boot. Zero registrations is a valid configuration (see
|
|
85
85
|
// validateSingleProvider doc) — a pure machine API using auth-foundation for
|
|
@@ -93,7 +93,7 @@ export function validateSessionStoreMultiplicity(features) {
|
|
|
93
93
|
shapeHint: "SessionStoreProvider — options must have a { build } shape",
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
-
// Optional single-provider
|
|
96
|
+
// Optional single-provider. Zero registrations = OK (single-tenant /
|
|
97
97
|
// header-cookie path). ≥2 or malformed = boot fail.
|
|
98
98
|
export function validateTenantResolverMultiplicity(features) {
|
|
99
99
|
validateSingleProvider(features, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Merge app-facing AnonymousAccessConfig with auth-foundation tenant providers.
|
|
3
|
-
* Providers win over any leftover callback fields
|
|
3
|
+
* Providers win over any leftover callback fields.
|
|
4
4
|
* Test stacks may still pass Resolved callbacks when no provider is mounted.
|
|
5
5
|
*/
|
|
6
6
|
import type { AnonymousAccessConfig, AnonymousAccessResolved } from "@cosmicdrift/kumiko-framework/api";
|
|
@@ -10,7 +10,7 @@ export async function resolveAnonymousAccessFromRegistry(base, deps) {
|
|
|
10
10
|
// (EXT_TENANT_RESOLVER/EXT_TENANT_EXISTENCE) alone must never make
|
|
11
11
|
// anonymousAccess become defined for an app that never set it — that
|
|
12
12
|
// would upgrade every roles:["anonymous"] handler to reachable without
|
|
13
|
-
// a JWT the moment such a routing feature is mounted
|
|
13
|
+
// a JWT the moment such a routing feature is mounted.
|
|
14
14
|
if (!base) {
|
|
15
15
|
const needing = ANONYMOUS_ROUTE_FEATURES.filter((name) => deps.registry.getFeature(name));
|
|
16
16
|
if (needing.length > 0) {
|
|
@@ -19,7 +19,7 @@ export async function resolveAnonymousAccessFromRegistry(base, deps) {
|
|
|
19
19
|
}
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
22
|
-
// Fail-closed (
|
|
22
|
+
// Fail-closed (security): inline tenantResolver without trust is the
|
|
23
23
|
// old ambiguous config — providers always carry trust; test stacks must too.
|
|
24
24
|
if (!tenantResolver &&
|
|
25
25
|
base &&
|
|
@@ -29,7 +29,7 @@ export async function resolveAnonymousAccessFromRegistry(base, deps) {
|
|
|
29
29
|
throw new Error("[auth-foundation] anonymousAccess.tenantResolver is set without resolverTrust — " +
|
|
30
30
|
'declare "authoritative" or "fallback-only" (or mount an EXT_TENANT_RESOLVER provider).');
|
|
31
31
|
}
|
|
32
|
-
// Providers win
|
|
32
|
+
// Providers win. When none are mounted, keep any test-injected
|
|
33
33
|
// Resolved callbacks so framework middleware suites stay self-contained.
|
|
34
34
|
return {
|
|
35
35
|
...(base ?? {}),
|
|
@@ -42,14 +42,14 @@ export function tokenShapeMatches(shape, rawToken) {
|
|
|
42
42
|
export function tokenShapeKey(shape) {
|
|
43
43
|
return shape.kind === "jwt" ? "jwt" : `prefix:${shape.prefix}`;
|
|
44
44
|
}
|
|
45
|
-
// Session-store extension point
|
|
45
|
+
// Session-store extension point. Unlike EXT_TOKEN_VERIFIER, this is
|
|
46
46
|
// single-provider — sessions have no per-provider shape to route on, so
|
|
47
47
|
// exactly one implementation must be registered (boot-fails on 0 or ≥2).
|
|
48
48
|
export const EXT_SESSION_STORE = "sessionStore";
|
|
49
49
|
export function isSessionStoreProvider(o) {
|
|
50
50
|
return typeof o === "object" && o !== null && "build" in o && typeof o.build === "function";
|
|
51
51
|
}
|
|
52
|
-
// Tenant-resolution extension points
|
|
52
|
+
// Tenant-resolution extension points. Both are single-provider and
|
|
53
53
|
// optional — zero registered means today's single-tenant / header-cookie
|
|
54
54
|
// path (no subdomain resolver, no existence check). ≥2 fails boot.
|
|
55
55
|
export const EXT_TENANT_RESOLVER = "tenantResolver";
|
|
@@ -30,9 +30,9 @@ export function createDisableHandler(opts) {
|
|
|
30
30
|
if (!row)
|
|
31
31
|
return mfaNotEnabled();
|
|
32
32
|
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
33
|
+
// without ctx.redis, verifyMfaFactor's TOTP-replay burn is skipped, and
|
|
34
|
+
// a code observed once (phishing proxy/shoulder-surfing) could be
|
|
35
|
+
// replayed within the ±1-step window to disable MFA outright.
|
|
36
36
|
// "no ctx.redis means no one gets through MFA login" doesn't cover
|
|
37
37
|
// this route — it's session-authed, and JWTs issued before Redis was
|
|
38
38
|
// unwired stay valid until they expire.
|
|
@@ -108,8 +108,8 @@ export function createEnableConfirmPreauthHandler(opts) {
|
|
|
108
108
|
// re-enrollment until an operator manually disables MFA. NOT fixed by
|
|
109
109
|
// this ordering: burnToken() above still runs before this check, so a
|
|
110
110
|
// mid-flight restricted/deleted user still burns their setup token
|
|
111
|
-
//
|
|
112
|
-
//
|
|
111
|
+
// — moving the burn later would need care around the
|
|
112
|
+
// existing userId-unique-constraint backstop between the
|
|
113
113
|
// `existing` check above and executor.create() below.
|
|
114
114
|
const systemUser = createSystemUser(tenantId, ["SystemAdmin"]);
|
|
115
115
|
const userRow = (await ctx.queryAs(systemUser, UserQueries.findForAuth, {
|
|
@@ -150,10 +150,10 @@ export function createEnableConfirmPreauthHandler(opts) {
|
|
|
150
150
|
id: userId,
|
|
151
151
|
tenantId,
|
|
152
152
|
roles: mergedRoles,
|
|
153
|
-
// This endpoint logs the user in directly
|
|
153
|
+
// This endpoint logs the user in directly, so a stored
|
|
154
154
|
// timezone must survive the preauth-MFA-enrollment login just like
|
|
155
155
|
// a plain password login does — same helper as verify.write.ts /
|
|
156
|
-
// invite-accept-with-login.write.ts
|
|
156
|
+
// invite-accept-with-login.write.ts.
|
|
157
157
|
...sessionTimezoneField(userRow?.timezone),
|
|
158
158
|
...sessionLocaleField(userRow?.locale),
|
|
159
159
|
};
|
|
@@ -38,8 +38,8 @@ export function createEnableConfirmHandler(opts) {
|
|
|
38
38
|
// already rules that out).
|
|
39
39
|
if (verify.payload.userId !== event.user.id)
|
|
40
40
|
return invalidSetupToken();
|
|
41
|
-
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts
|
|
42
|
-
//
|
|
41
|
+
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts:
|
|
42
|
+
// session-authed (lower risk — the caller already has a
|
|
43
43
|
// valid JWT), but silently skipping the single-use burn here would
|
|
44
44
|
// still let a double-confirm race complete twice instead of the
|
|
45
45
|
// second seeing invalidSetupToken(). Checked before the TOTP verify
|
|
@@ -37,7 +37,7 @@ export function createEnableStartPreauthHandler(opts) {
|
|
|
37
37
|
const verified = verifyMfaPreauthSetupToken(event.payload.preauthSetupToken, opts.challengeTokenSecret);
|
|
38
38
|
// Same generic "sign in again" error as an expired/invalid MFA
|
|
39
39
|
// challenge token — both mean the login-flow token expired, no
|
|
40
|
-
// distinct i18n needed
|
|
40
|
+
// distinct i18n needed.
|
|
41
41
|
if (!verified.ok)
|
|
42
42
|
return invalidChallengeToken();
|
|
43
43
|
const { userId, tenantId } = verified.payload;
|
|
@@ -97,7 +97,7 @@ export async function mfaReencryptJob(rawPayload, ctx, db) {
|
|
|
97
97
|
}
|
|
98
98
|
// After PII peel (when configured), values must be current-cipher
|
|
99
99
|
// envelopes — non-JSON/non-envelope is not a supported legacy decrypt
|
|
100
|
-
// path
|
|
100
|
+
// path, matching config behavior.
|
|
101
101
|
const totpClass = classifyStoredEnvelope(envelopeValues.totpSecret, targetVersion);
|
|
102
102
|
const recoveryClass = classifyStoredEnvelope(envelopeValues.recoveryCodes, targetVersion);
|
|
103
103
|
if (totpClass === "unrecognized" || recoveryClass === "unrecognized") {
|
|
@@ -36,11 +36,11 @@ export function createRegenerateRecoveryHandler(opts) {
|
|
|
36
36
|
// count, since either way the presented code is consumed/irrelevant
|
|
37
37
|
// afterward.
|
|
38
38
|
//
|
|
39
|
-
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
39
|
+
// Fail closed, matching verify.write.ts/enable-confirm-preauth.write.ts:
|
|
40
|
+
// without ctx.redis, verifyMfaFactor's TOTP-replay burn is skipped,
|
|
41
|
+
// letting an observed code be replayed within the ±1-step window to
|
|
42
|
+
// regenerate (and thus invalidate) recovery codes — a session-authed
|
|
43
|
+
// route, so pre-unwiring JWTs stay a valid attack path.
|
|
44
44
|
if (!ctx.redis) {
|
|
45
45
|
return writeFailure(new InternalError({
|
|
46
46
|
message: "regenerate-recovery (mfa) requires ctx.redis for TOTP replay protection",
|
|
@@ -42,7 +42,7 @@ export function createMfaVerifyHandler(opts) {
|
|
|
42
42
|
if (!verified.ok)
|
|
43
43
|
return invalidChallengeToken();
|
|
44
44
|
const { userId, tenantId } = verified.payload;
|
|
45
|
-
// Fail closed, matching enable-confirm-preauth.write.ts
|
|
45
|
+
// Fail closed, matching enable-confirm-preauth.write.ts:
|
|
46
46
|
// this route sits behind a challenge token from a successful login,
|
|
47
47
|
// but its own secret is still just a short TOTP/recovery code —
|
|
48
48
|
// silently skipping the brute-force cap and single-use burn when
|
|
@@ -6,7 +6,7 @@ const SETUP_TOKEN_PURPOSE = "mfa-setup-token-v1";
|
|
|
6
6
|
const CHALLENGE_TOKEN_PURPOSE = "mfa-challenge-token-v1";
|
|
7
7
|
// A blank or whitespace-only override is treated as absent — an empty env
|
|
8
8
|
// var (MFA_SETUP_TOKEN_SECRET="") must fall back to derivation, not sign
|
|
9
|
-
// tokens with an empty/near-empty HMAC key
|
|
9
|
+
// tokens with an empty/near-empty HMAC key.
|
|
10
10
|
function resolveSecret(override, fallback) {
|
|
11
11
|
return override !== undefined && override.trim() !== "" ? override : fallback();
|
|
12
12
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
2
2
|
import type { ComponentType, ReactNode } from "react";
|
|
3
3
|
export type AuthMfaClientOptions = {
|
|
4
|
-
/** Key
|
|
4
|
+
/** Key overrides per locale, merged with the default bundles (de/en). */
|
|
5
5
|
readonly translations?: TranslationsByLocale;
|
|
6
6
|
};
|
|
7
7
|
export type AuthMfaClientFeature = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Client
|
|
1
|
+
// Client feature factory for auth-mfa — mirrors emailPasswordClient()'s
|
|
2
2
|
// shape so apps register both the same way:
|
|
3
3
|
// createKumikoApp({ clientFeatures: [emailPasswordClient(), authMfaClient()] }).
|
|
4
4
|
// No gates: MfaVerifyScreen isn't a route gate, it's a state swap wired
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Default
|
|
2
|
-
// authMfaClient()
|
|
3
|
-
// Keys
|
|
1
|
+
// Default bundles for the auth-mfa feature UI, merged by
|
|
2
|
+
// authMfaClient() analogously to emailPasswordClient() from auth-email-password.
|
|
3
|
+
// Keys follow `auth.mfa.<area>.<slug>`.
|
|
4
4
|
export const defaultTranslations = {
|
|
5
5
|
en: {
|
|
6
6
|
"screen:auth-mfa-enable.title": "Two-factor authentication",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// Public exports
|
|
2
|
-
//
|
|
3
|
-
// (defineFeature)
|
|
4
|
-
// password/web/index.ts
|
|
1
|
+
// Public exports for the browser side of the auth-mfa feature. The subpath
|
|
2
|
+
// export `@cosmicdrift/kumiko-bundled-features/auth-mfa/web` keeps the server
|
|
3
|
+
// side (`defineFeature`) free of React/DOM dependencies, matching the same
|
|
4
|
+
// separation in auth-email-password/web/index.ts.
|
|
5
5
|
export { authMfaClient } from "./client-plugin.js";
|
|
6
6
|
export { defaultTranslations, mergeTranslations } from "./i18n.js";
|
|
7
7
|
export { confirmMfaSetupPreauth, startMfaSetupPreauth, verifyMfaChallenge } from "./mfa-client.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// Browser
|
|
2
|
-
// login LoginScreen started when the server responded mfaRequired.
|
|
3
|
-
// fetch/CSRF pattern as auth-email-password's login()
|
|
4
|
-
//
|
|
1
|
+
// Browser side of POST /api/auth/mfa/verify — completes the two-step
|
|
2
|
+
// login that LoginScreen started when the server responded with mfaRequired.
|
|
3
|
+
// Uses the same fetch/CSRF pattern as auth-email-password's login(), but runs
|
|
4
|
+
// before a session exists, so it does not call csrfHeader(). The response is
|
|
5
5
|
// byte-identical to /auth/login's ({isSuccess, token, user} | {isSuccess:
|
|
6
|
-
// false, error})
|
|
7
|
-
//
|
|
6
|
+
// false, error}) because auth-routes.ts uses mintSessionAndRespond() for both
|
|
7
|
+
// routes.
|
|
8
8
|
// kumiko-lint-ignore cross-feature-import client-only types, the feature's server barrel has no web/ re-export
|
|
9
9
|
import { toLoginResponse, } from "../../auth-email-password/web/index.js";
|
|
10
10
|
export async function verifyMfaChallenge(challengeToken, code) {
|
|
@@ -40,11 +40,12 @@ export async function verifyMfaChallenge(challengeToken, code) {
|
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
// Browser
|
|
43
|
+
// Browser side of POST /api/auth/mfa/preauth-enable-start — lets a user
|
|
44
44
|
// blocked at login by MFA enforcement generate a TOTP secret/QR without a
|
|
45
|
-
// session, using the preauthSetupToken login()'s
|
|
46
|
-
//
|
|
47
|
-
//
|
|
45
|
+
// session, using the preauthSetupToken carried by login()'s
|
|
46
|
+
// mfa-setup-required result. No JWT/cookie is issued here (see the route
|
|
47
|
+
// comment in auth-routes.ts); the response's
|
|
48
|
+
// setupToken is consumed by confirmMfaSetupPreauth below.
|
|
48
49
|
export async function startMfaSetupPreauth(preauthSetupToken, accountLabel) {
|
|
49
50
|
const res = await fetch("/api/auth/mfa/preauth-enable-start", {
|
|
50
51
|
method: "POST",
|
|
@@ -85,12 +86,12 @@ export async function startMfaSetupPreauth(preauthSetupToken, accountLabel) {
|
|
|
85
86
|
},
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
|
-
// Browser
|
|
89
|
-
//
|
|
90
|
-
// required block.
|
|
91
|
-
// the same mintSessionAndRespond()
|
|
92
|
-
//
|
|
93
|
-
//
|
|
89
|
+
// Browser side of POST /api/auth/mfa/preauth-confirm — completes both the
|
|
90
|
+
// enrollment started by startMfaSetupPreauth and the login
|
|
91
|
+
// mfa-setup-required block. Its response mirrors /auth/mfa/verify's and is
|
|
92
|
+
// minted via the same mintSessionAndRespond(). It remains a separate function
|
|
93
|
+
// so this file's two already-tested request shapes stay independently
|
|
94
|
+
// editable.
|
|
94
95
|
export async function confirmMfaSetupPreauth(setupToken, code) {
|
|
95
96
|
const res = await fetch("/api/auth/mfa/preauth-confirm", {
|
|
96
97
|
method: "POST",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
// Login
|
|
3
|
-
// (/auth/login
|
|
4
|
-
// useState
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
2
|
+
// Login challenge step, rendered when LoginScreen's onMfaChallenge fires
|
|
3
|
+
// (/auth/login returned mfaRequired). It follows login-screen.tsx:
|
|
4
|
+
// useState plus a direct fetch call, without a dispatcher because no JWT
|
|
5
|
+
// exists yet. After success, it calls session.refresh() instead of a hard
|
|
6
|
+
// reload so the caller (typically wizard state in the app root) can render
|
|
7
|
+
// immediately when status:"authenticated" arrives.
|
|
8
8
|
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
9
9
|
import { useState } from "react";
|
|
10
10
|
// kumiko-lint-ignore cross-feature-import client-only barrel, the feature's server barrel has no web/ re-export
|