@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.388.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -57
- package/dist/agent-tools/tool-catalog.js +1 -1
- package/dist/agent-tools/tool-dispatch.d.ts +7 -7
- package/dist/agent-tools/tool-dispatch.js +9 -9
- package/dist/audit/handlers/audit-events.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/feature-exports.d.ts +2 -2
- package/dist/auth-mfa/feature.js +8 -0
- 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 +8 -4
- 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-code-or-recovery-field.d.ts +11 -0
- package/dist/auth-mfa/web/mfa-code-or-recovery-field.js +12 -0
- package/dist/auth-mfa/web/mfa-disable-dialog.js +14 -3
- package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +14 -3
- package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +10 -5
- package/dist/auth-mfa/web/mfa-verify-screen.js +32 -11
- package/dist/billing-foundation/aggregate-id.d.ts +5 -5
- package/dist/billing-foundation/aggregate-id.js +10 -11
- package/dist/billing-foundation/checkout-core.d.ts +9 -14
- package/dist/billing-foundation/checkout-core.js +24 -39
- package/dist/billing-foundation/consumer-protection/confirmation-mail.js +8 -2
- package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +1 -0
- package/dist/billing-foundation/consumer-protection/consent-gate.js +1 -0
- package/dist/billing-foundation/consumer-protection/issue-confirmation.js +9 -3
- package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +4 -2
- package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +6 -5
- package/dist/billing-foundation/consumer-protection/termination-record.d.ts +5 -1
- package/dist/billing-foundation/consumer-protection/termination-record.js +27 -17
- package/dist/billing-foundation/consumer-protection/termination-request.js +12 -7
- package/dist/billing-foundation/consumer-protection/termination-revoke.js +12 -7
- package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
- package/dist/billing-foundation/consumer-protection/termination-texts.js +3 -0
- package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +5 -2
- package/dist/billing-foundation/consumer-protection/withdrawal-period.js +8 -9
- package/dist/billing-foundation/entities.js +27 -27
- package/dist/billing-foundation/events.d.ts +1 -0
- package/dist/billing-foundation/events.js +19 -17
- package/dist/billing-foundation/feature.js +45 -44
- 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/billing-plans.query.js +35 -5
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +19 -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/plan-switch-preview.query.d.ts +13 -0
- package/dist/billing-foundation/handlers/plan-switch-preview.query.js +48 -0
- package/dist/billing-foundation/handlers/process-event.write.d.ts +6 -0
- package/dist/billing-foundation/handlers/process-event.write.js +28 -22
- package/dist/billing-foundation/handlers/start-plan-checkout.write.js +32 -5
- package/dist/billing-foundation/handlers/switch-plan.write.d.ts +2 -2
- package/dist/billing-foundation/handlers/switch-plan.write.js +56 -64
- package/dist/billing-foundation/handlers/sync-subscription.write.js +12 -1
- package/dist/billing-foundation/i18n.js +22 -0
- package/dist/billing-foundation/index.d.ts +1 -1
- package/dist/billing-foundation/plan-catalog.d.ts +21 -5
- package/dist/billing-foundation/plan-catalog.js +25 -16
- package/dist/billing-foundation/plan-switch.d.ts +12 -0
- package/dist/billing-foundation/plan-switch.js +60 -0
- 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 +97 -42
- package/dist/billing-foundation/types.js +29 -20
- package/dist/billing-foundation/validate-options.js +17 -0
- package/dist/billing-foundation/web/billing-plans-panel.js +82 -36
- package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +17 -3
- package/dist/billing-foundation/web/checkout-consent-dialog.js +14 -10
- package/dist/billing-foundation/web/constants.d.ts +4 -0
- package/dist/billing-foundation/web/constants.js +4 -0
- package/dist/billing-foundation/web/plan-price.d.ts +15 -0
- package/dist/billing-foundation/web/plan-price.js +32 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.d.ts +15 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +66 -0
- package/dist/cap-counter/aggregate-id.js +8 -9
- package/dist/cap-counter/cap-reservation.js +5 -1
- 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 +49 -49
- 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 +8 -2
- package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
- package/dist/channel-email/feature.js +1 -1
- 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/cascade.query.d.ts +5 -0
- package/dist/config/handlers/cascade.query.js +4 -3
- 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/handlers/values.query.d.ts +5 -0
- package/dist/config/handlers/values.query.js +4 -3
- package/dist/config/resolver.js +4 -4
- package/dist/config/table.js +10 -10
- package/dist/config/write-helpers.d.ts +1 -0
- package/dist/config/write-helpers.js +19 -10
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
- package/dist/crypto-shredding/handlers/forget-subject.write.js +25 -21
- 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/channel-context.js +6 -3
- package/dist/delivery/db/queries/preferences.js +2 -2
- package/dist/delivery/delivery-service.js +22 -7
- package/dist/delivery/feature.js +2 -2
- package/dist/delivery/handlers/log.query.js +1 -1
- package/dist/delivery/handlers/preferences.query.d.ts +1 -1
- package/dist/delivery/handlers/preferences.query.js +20 -1
- package/dist/delivery/handlers/unsubscribe-page-chrome.query.js +1 -1
- package/dist/delivery/tables.js +9 -8
- package/dist/delivery/unsubscribe-link.d.ts +3 -1
- package/dist/delivery/unsubscribe-page-strings.d.ts +1 -0
- package/dist/delivery/unsubscribe-page-strings.js +1 -0
- package/dist/delivery/unsubscribe-page.d.ts +2 -0
- package/dist/delivery/unsubscribe-page.js +5 -0
- package/dist/delivery/unsubscribe.js +29 -11
- 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-foundation/index.d.ts +1 -1
- package/dist/file-foundation/index.js +1 -1
- package/dist/file-foundation/read-file-ref-content.d.ts +3 -0
- package/dist/file-foundation/read-file-ref-content.js +6 -1
- package/dist/file-provider-inmemory/feature.d.ts +1 -1
- package/dist/file-provider-inmemory/feature.js +16 -16
- package/dist/file-provider-s3/env-named-feature.d.ts +0 -2
- 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 +3 -3
- package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
- package/dist/form-draft/decrypt-draft.js +5 -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/host-routing/dispatch.js +11 -20
- 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.d.ts +2 -2
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +22 -14
- package/dist/inbound-mail-foundation/i18n.js +0 -1
- 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/screens.js +0 -3
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
- package/dist/inbound-mail-foundation/types.d.ts +49 -49
- 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 +85 -67
- 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.d.ts +1 -0
- package/dist/jobs/feature.js +13 -10
- 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/handlers/tenant-failures.query.d.ts +1 -1
- package/dist/jobs/handlers/tenant-failures.query.js +45 -41
- package/dist/jobs/handlers/tenant-runs.query.d.ts +1 -1
- package/dist/jobs/handlers/tenant-runs.query.js +54 -50
- package/dist/jobs/job-instant.js +1 -1
- package/dist/jobs/job-run-logger.js +15 -15
- 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 +5 -5
- package/dist/mail-foundation/feature.js +27 -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.d.ts +1 -1
- package/dist/personal-access-tokens/feature.js +9 -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/renderer-pdf/render-table-pdf.d.ts +1 -1
- package/dist/renderer-pdf/render-table-pdf.js +22 -10
- 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.d.ts +2 -2
- package/dist/sessions/feature.js +12 -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.d.ts +1 -0
- package/dist/shared/decrypt-stored-pii.js +7 -2
- package/dist/shared/encrypt-for-direct-write.js +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/mail-template-body.d.ts +6 -2
- package/dist/shared/mail-template-body.js +7 -4
- 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/step-dispatcher/feature.js +1 -0
- package/dist/subscription-dodo/client.d.ts +17 -0
- package/dist/subscription-dodo/client.js +31 -0
- package/dist/subscription-dodo/constants.d.ts +12 -0
- package/dist/subscription-dodo/constants.js +19 -0
- package/dist/subscription-dodo/feature.d.ts +37 -0
- package/dist/subscription-dodo/feature.js +144 -0
- package/dist/subscription-dodo/index.d.ts +2 -0
- package/dist/subscription-dodo/index.js +4 -0
- package/dist/subscription-dodo/plugin-methods.d.ts +23 -0
- package/dist/subscription-dodo/plugin-methods.js +260 -0
- package/dist/subscription-dodo/runtime.d.ts +27 -0
- package/dist/subscription-dodo/runtime.js +89 -0
- package/dist/subscription-dodo/verify-webhook.d.ts +37 -0
- package/dist/subscription-dodo/verify-webhook.js +189 -0
- 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 +36 -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 +8 -7
- 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.d.ts +3 -2
- package/dist/template-resolver/api.js +34 -12
- package/dist/template-resolver/compile-document-body.js +1 -0
- package/dist/template-resolver/feature.js +2 -2
- package/dist/template-resolver/handlers/bundle-import.js +3 -3
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +5 -1
- package/dist/template-resolver/handlers/copy-locale.write.js +22 -7
- package/dist/template-resolver/handlers/diff-to-system.query.js +3 -2
- package/dist/template-resolver/handlers/document-base.js +3 -2
- package/dist/template-resolver/handlers/find-by-id.query.js +8 -7
- package/dist/template-resolver/handlers/list.query.js +6 -7
- package/dist/template-resolver/handlers/overview.query.d.ts +3 -0
- package/dist/template-resolver/handlers/overview.query.js +6 -3
- package/dist/template-resolver/handlers/shared.js +2 -2
- package/dist/template-resolver/handlers/template-write.js +3 -3
- package/dist/template-resolver/handlers/tenant-override-counts.query.js +1 -3
- package/dist/template-resolver/handlers/tenant-override-selection.d.ts +2 -1
- package/dist/template-resolver/handlers/tenant-overrides.query.js +28 -5
- 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/handlers/usage.query.d.ts +2 -1
- package/dist/template-resolver/handlers/usage.query.js +26 -16
- package/dist/template-resolver/handlers/validate.query.js +7 -2
- package/dist/template-resolver/seeding.js +30 -14
- package/dist/template-resolver/store-template-resource.d.ts +1 -0
- package/dist/template-resolver/store-template-resource.js +19 -4
- package/dist/template-resolver/table.js +10 -11
- package/dist/template-resolver/template-delivery-policy.d.ts +0 -5
- package/dist/template-resolver/template-delivery-policy.js +0 -6
- package/dist/template-resolver/template-meta.js +7 -4
- package/dist/template-resolver/template-preview.js +4 -3
- package/dist/template-resolver/web/client-plugin.js +2 -2
- package/dist/template-resolver/web/constants.d.ts +2 -2
- package/dist/template-resolver/web/constants.js +3 -3
- package/dist/template-resolver/web/index.d.ts +1 -0
- package/dist/template-resolver/web/index.js +1 -0
- package/dist/template-resolver/web/mail-layout-constants.d.ts +5 -0
- package/dist/template-resolver/web/mail-layout-constants.js +7 -0
- package/dist/tenant/feature.js +7 -7
- package/dist/tenant/handlers/member-directory.query.d.ts +1 -0
- package/dist/tenant/handlers/member-directory.query.js +11 -4
- 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.d.ts +1 -0
- package/dist/tenant/handlers/tenant-directory.query.js +9 -5
- 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/constants.d.ts +1 -0
- package/dist/tenant-lifecycle/constants.js +4 -0
- package/dist/tenant-lifecycle/feature.js +1 -1
- package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -2
- 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 +7 -8
- package/dist/tier-engine/handlers/set-tenant-tier.write.js +7 -4
- package/dist/tier-engine/tier-resolver.js +2 -2
- package/dist/tier-engine/trial.js +8 -8
- package/dist/tier-engine/web/constants.js +2 -2
- 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 +130 -237
- package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
- package/dist/user-data-rights/run-forget-cleanup.js +65 -83
- 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/waitlist/handlers/export-purge.write.js +2 -1
- package/dist/waitlist/handlers/submit.write.js +5 -5
- package/dist/waitlist/import.d.ts +1 -0
- package/dist/waitlist/import.js +4 -0
- package/dist/waitlist/legacy-migrate.js +17 -6
- package/dist/waitlist/link-on-signup.js +18 -6
- package/dist/waitlist/options.d.ts +3 -0
- 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 +20 -10
- package/src/agent-tools/changes.json +6 -0
- package/src/audit/changes.json +12 -0
- package/src/auth-mfa/changes.json +6 -0
- package/src/billing-foundation/changes.json +55 -0
- package/src/cap-counter/changes.json +18 -0
- package/src/channel-email/changes.json +6 -0
- package/src/config/changes.json +12 -0
- package/src/crypto-shredding/changes.json +6 -0
- package/src/delivery/changes.json +30 -0
- package/src/form-draft/changes.json +6 -0
- package/src/host-routing/changes.json +6 -0
- package/src/inbound-mail-foundation/changes.json +18 -0
- package/src/jobs/changes.json +13 -0
- package/src/mail-foundation/changes.json +6 -0
- package/src/renderer-pdf/changes.json +6 -0
- package/src/step-dispatcher/changes.json +6 -0
- package/src/subscription-dodo/changes.json +14 -0
- package/src/subscription-stripe/changes.json +12 -0
- package/src/template-resolver/changes.json +48 -0
- package/src/tenant/changes.json +6 -0
- package/src/tenant-lifecycle/changes.json +6 -0
- package/src/tier-engine/changes.json +6 -0
- package/src/waitlist/changes.json +18 -0
- package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +0 -1
- package/dist/billing-foundation/consumer-protection/stored-user-email.js +0 -8
|
@@ -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",
|
|
@@ -10,6 +10,10 @@ export const defaultTranslations = {
|
|
|
10
10
|
"auth.mfa.verify.submit": "Verify",
|
|
11
11
|
"auth.mfa.verify.submitting": "…",
|
|
12
12
|
"auth.mfa.verify.backToLogin": "Back to login",
|
|
13
|
+
"auth.mfa.verify.recoveryCode": "Recovery code",
|
|
14
|
+
"auth.mfa.verify.recoverySubtitle": "Enter one of the recovery codes you saved when you set up two-factor authentication.",
|
|
15
|
+
"auth.mfa.verify.useAuthenticatorCode": "Use the code from your app",
|
|
16
|
+
"auth.mfa.verify.useRecoveryCode": "Use a recovery code instead",
|
|
13
17
|
"auth.mfa.errors.invalidCode": "Invalid code. Please try again.",
|
|
14
18
|
"auth.mfa.errors.invalidTotpCode": "Invalid code. Please try again.",
|
|
15
19
|
"auth.mfa.errors.invalidChallengeToken": "Your sign-in has expired. Please sign in again.",
|
|
@@ -35,7 +39,7 @@ export const defaultTranslations = {
|
|
|
35
39
|
"auth.mfa.setup.confirm": "Complete setup",
|
|
36
40
|
"auth.mfa.disable.title": "Disable two-factor authentication",
|
|
37
41
|
"auth.mfa.disable.description": "Confirm with a code from your authenticator app or a recovery code. Your account will then be protected by your password alone.",
|
|
38
|
-
"auth.mfa.disable.code": "Code from your authenticator app
|
|
42
|
+
"auth.mfa.disable.code": "Code from your authenticator app",
|
|
39
43
|
"auth.mfa.disable.confirm": "Disable",
|
|
40
44
|
"auth.mfa.disable.cancel": "Cancel",
|
|
41
45
|
"auth.mfa.disable.trigger": "Disable 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",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type MfaCodeOrRecoveryFieldProps = {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly codeLabel: string;
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly onCodeChange: (code: string) => void;
|
|
7
|
+
readonly useRecovery: boolean;
|
|
8
|
+
readonly onUseRecoveryChange: (useRecovery: boolean) => void;
|
|
9
|
+
readonly disabled?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function MfaCodeOrRecoveryField({ id, codeLabel, code, onCodeChange, useRecovery, onUseRecoveryChange, disabled, }: MfaCodeOrRecoveryFieldProps): ReactNode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
3
|
+
export function MfaCodeOrRecoveryField({ id, codeLabel, code, onCodeChange, useRecovery, onUseRecoveryChange, disabled, }) {
|
|
4
|
+
const t = useTranslation();
|
|
5
|
+
const { Button, Field, Input } = usePrimitives();
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsx(Field, { id: id, label: useRecovery ? t("auth.mfa.verify.recoveryCode") : codeLabel, required: true, children: useRecovery ? (_jsx(Input, { kind: "text", id: id, name: id, value: code, onChange: onCodeChange, disabled: disabled, autoFocus: true, autoComplete: "off" })) : (_jsx(Input, { kind: "code", length: 6, id: id, name: id, value: code, onChange: onCodeChange, disabled: disabled, autoFocus: true })) }), _jsx(Button, { type: "button", variant: "link", disabled: disabled, onClick: () => {
|
|
7
|
+
onUseRecoveryChange(!useRecovery);
|
|
8
|
+
onCodeChange("");
|
|
9
|
+
}, children: useRecovery
|
|
10
|
+
? t("auth.mfa.verify.useAuthenticatorCode")
|
|
11
|
+
: t("auth.mfa.verify.useRecoveryCode") })] }));
|
|
12
|
+
}
|
|
@@ -12,20 +12,31 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
12
12
|
import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
13
13
|
import { useState } from "react";
|
|
14
14
|
import { AuthMfaHandlers } from "./constants.js";
|
|
15
|
+
import { MfaCodeOrRecoveryField } from "./mfa-code-or-recovery-field.js";
|
|
15
16
|
// kumiko-lint-ignore no-custom-primitives Uses usePrimitives().Dialog internally, name is an MFA domain action, not a primitive reimplementation
|
|
16
17
|
export function MfaDisableDialog({ open, onOpenChange, onDisabled, onError, }) {
|
|
17
18
|
const t = useTranslation();
|
|
18
|
-
const { Dialog
|
|
19
|
+
const { Dialog } = usePrimitives();
|
|
19
20
|
const dispatcher = useDispatcher();
|
|
20
21
|
const [code, setCode] = useState("");
|
|
22
|
+
const [useRecovery, setUseRecovery] = useState(false);
|
|
23
|
+
const reset = () => {
|
|
24
|
+
setCode("");
|
|
25
|
+
setUseRecovery(false);
|
|
26
|
+
};
|
|
27
|
+
const handleOpenChange = (nextOpen) => {
|
|
28
|
+
if (!nextOpen)
|
|
29
|
+
reset();
|
|
30
|
+
onOpenChange(nextOpen);
|
|
31
|
+
};
|
|
21
32
|
const confirm = async () => {
|
|
22
33
|
const res = await dispatcher.write(AuthMfaHandlers.disable, { code });
|
|
23
|
-
|
|
34
|
+
reset();
|
|
24
35
|
if (!res.isSuccess) {
|
|
25
36
|
onError(res.error.i18nKey);
|
|
26
37
|
return;
|
|
27
38
|
}
|
|
28
39
|
onDisabled();
|
|
29
40
|
};
|
|
30
|
-
return (_jsx(Dialog, { open: open, onOpenChange:
|
|
41
|
+
return (_jsx(Dialog, { open: open, onOpenChange: handleOpenChange, variant: "danger", title: t("auth.mfa.disable.title"), description: t("auth.mfa.disable.description"), confirmLabel: t("auth.mfa.disable.confirm"), cancelLabel: t("auth.mfa.disable.cancel"), onConfirm: confirm, testId: "mfa-disable-dialog", children: _jsx(MfaCodeOrRecoveryField, { id: "mfa-disable-code", codeLabel: t("auth.mfa.disable.code"), code: code, onCodeChange: setCode, useRecovery: useRecovery, onUseRecoveryChange: setUseRecovery }) }));
|
|
31
42
|
}
|
|
@@ -9,20 +9,31 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
import { AuthMfaHandlers } from "./constants.js";
|
|
12
|
+
import { MfaCodeOrRecoveryField } from "./mfa-code-or-recovery-field.js";
|
|
12
13
|
// kumiko-lint-ignore no-custom-primitives Uses usePrimitives().Dialog internally, name is an MFA domain action, not a primitive reimplementation
|
|
13
14
|
export function MfaRegenerateRecoveryDialog({ open, onOpenChange, onRegenerated, onError, }) {
|
|
14
15
|
const t = useTranslation();
|
|
15
|
-
const { Dialog
|
|
16
|
+
const { Dialog } = usePrimitives();
|
|
16
17
|
const dispatcher = useDispatcher();
|
|
17
18
|
const [code, setCode] = useState("");
|
|
19
|
+
const [useRecovery, setUseRecovery] = useState(false);
|
|
20
|
+
const reset = () => {
|
|
21
|
+
setCode("");
|
|
22
|
+
setUseRecovery(false);
|
|
23
|
+
};
|
|
24
|
+
const handleOpenChange = (nextOpen) => {
|
|
25
|
+
if (!nextOpen)
|
|
26
|
+
reset();
|
|
27
|
+
onOpenChange(nextOpen);
|
|
28
|
+
};
|
|
18
29
|
const confirm = async () => {
|
|
19
30
|
const res = await dispatcher.write(AuthMfaHandlers.regenerateRecovery, { code });
|
|
20
|
-
|
|
31
|
+
reset();
|
|
21
32
|
if (!res.isSuccess) {
|
|
22
33
|
onError(res.error.i18nKey);
|
|
23
34
|
return;
|
|
24
35
|
}
|
|
25
36
|
onRegenerated(res.data.recoveryCodes);
|
|
26
37
|
};
|
|
27
|
-
return (_jsx(Dialog, { open: open, onOpenChange:
|
|
38
|
+
return (_jsx(Dialog, { open: open, onOpenChange: handleOpenChange, title: t("auth.mfa.regenerate.title"), description: t("auth.mfa.regenerate.description"), confirmLabel: t("auth.mfa.regenerate.confirm"), cancelLabel: t("auth.mfa.regenerate.cancel"), onConfirm: confirm, testId: "mfa-regenerate-recovery-dialog", children: _jsx(MfaCodeOrRecoveryField, { id: "mfa-regenerate-code", codeLabel: t("auth.mfa.regenerate.code"), code: code, onCodeChange: setCode, useRecovery: useRecovery, onUseRecoveryChange: setUseRecovery }) }));
|
|
28
39
|
}
|
|
@@ -48,6 +48,7 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
|
|
|
48
48
|
const [setup, setSetup] = useState(null);
|
|
49
49
|
const [acknowledged, setAcknowledged] = useState(false);
|
|
50
50
|
const [code, setCode] = useState("");
|
|
51
|
+
const [attempt, setAttempt] = useState(0);
|
|
51
52
|
const [busy, setBusy] = useState(false);
|
|
52
53
|
const [error, setError] = useState(null);
|
|
53
54
|
const [retryAfterSeconds, setRetryAfterSeconds] = useState(null);
|
|
@@ -78,14 +79,14 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
|
|
|
78
79
|
setBusy(false);
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
|
-
const confirmSetup = async () => {
|
|
82
|
-
if (!setup)
|
|
82
|
+
const confirmSetup = async (submittedCode) => {
|
|
83
|
+
if (!setup || busy)
|
|
83
84
|
return;
|
|
84
85
|
setBusy(true);
|
|
85
86
|
setError(null);
|
|
86
87
|
setRetryAfterSeconds(null);
|
|
87
88
|
try {
|
|
88
|
-
const res = await confirmMfaSetupPreauth(setup.setupToken,
|
|
89
|
+
const res = await confirmMfaSetupPreauth(setup.setupToken, submittedCode);
|
|
89
90
|
if (res.kind !== "success") {
|
|
90
91
|
setError(res.error.reason);
|
|
91
92
|
setRetryAfterSeconds(res.error.retryAfterSeconds ?? null);
|
|
@@ -98,7 +99,11 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
|
|
|
98
99
|
setSetup(null);
|
|
99
100
|
setAcknowledged(false);
|
|
100
101
|
setCode("");
|
|
102
|
+
return;
|
|
101
103
|
}
|
|
104
|
+
// Remount: the field was disabled during confirm and lost focus.
|
|
105
|
+
setCode("");
|
|
106
|
+
setAttempt((n) => n + 1);
|
|
102
107
|
return;
|
|
103
108
|
}
|
|
104
109
|
onSuccess?.(res.data.landingPath);
|
|
@@ -112,7 +117,7 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
|
|
|
112
117
|
};
|
|
113
118
|
const onSubmit = (e) => {
|
|
114
119
|
e?.preventDefault();
|
|
115
|
-
void confirmSetup();
|
|
120
|
+
void confirmSetup(code);
|
|
116
121
|
};
|
|
117
122
|
return (_jsxs(AuthCard, { title: title ?? t("auth.mfa.setup.title"), subtitle: subtitle ?? t("auth.mfa.setup.subtitle"), children: [error !== null ? (_jsx(Banner, { variant: "error", children: error === "too_many_attempts" && retryAfterSeconds !== null
|
|
118
123
|
? t("auth.mfa.errors.tooManyAttemptsWithSeconds", { seconds: retryAfterSeconds })
|
|
@@ -124,5 +129,5 @@ export function MfaSetupPreauthScreen({ preauthSetupToken, accountLabel, title,
|
|
|
124
129
|
copyable: false,
|
|
125
130
|
multiline: false,
|
|
126
131
|
},
|
|
127
|
-
], copyLabel: t("kumiko.secretMint.copy"), copiedLabel: t("kumiko.secretMint.copied"), testId: "mfa-setup-preauth-qr" })) : (_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.scanTitle") })), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.manualEntry") }), _jsx("code", { className: "inline-block break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.secretParam })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.recoveryTitle") }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.recoveryHint") }), _jsx("code", { className: "block whitespace-pre-wrap break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.recoveryCodes.join("\n") }), _jsx(Field, { id: "mfa-setup-preauth-ack", label: t("auth.mfa.enable.acknowledge"), children: _jsx(Input, { kind: "boolean", id: "mfa-setup-preauth-ack", name: "mfa-setup-preauth-ack", value: acknowledged, onChange: setAcknowledged }) })] }), _jsx(Field, { id: "mfa-setup-preauth-code", label: t("auth.mfa.enable.code"), required: true, children: _jsx(Input, { kind: "
|
|
132
|
+
], copyLabel: t("kumiko.secretMint.copy"), copiedLabel: t("kumiko.secretMint.copied"), testId: "mfa-setup-preauth-qr" })) : (_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.scanTitle") })), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.manualEntry") }), _jsx("code", { className: "inline-block break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.secretParam })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("span", { className: "text-sm font-semibold", children: t("auth.mfa.enable.recoveryTitle") }), _jsx("span", { className: "text-xs text-muted-foreground", children: t("auth.mfa.enable.recoveryHint") }), _jsx("code", { className: "block whitespace-pre-wrap break-all rounded bg-muted px-3 py-2 font-mono text-sm", children: setup.recoveryCodes.join("\n") }), _jsx(Field, { id: "mfa-setup-preauth-ack", label: t("auth.mfa.enable.acknowledge"), children: _jsx(Input, { kind: "boolean", id: "mfa-setup-preauth-ack", name: "mfa-setup-preauth-ack", value: acknowledged, onChange: setAcknowledged }) })] }), _jsx(Field, { id: "mfa-setup-preauth-code", label: t("auth.mfa.enable.code"), required: true, children: _jsx(Input, { kind: "code", length: 6, id: "mfa-setup-preauth-code", name: "mfa-setup-preauth-code", value: code, onChange: setCode, onComplete: (next) => void confirmSetup(next), disabled: busy || !acknowledged, hasError: error !== null, autoFocus: attempt > 0 }, attempt) }), _jsx("div", { className: "flex justify-end", children: _jsx(Button, { type: "submit", variant: "primary", loading: busy, disabled: busy || !acknowledged || code.length !== 6, children: t("auth.mfa.setup.confirm") }) })] }) })), onCancel ? (_jsx("div", { className: "flex justify-center", children: _jsx(Button, { type: "button", variant: "secondary", onClick: onCancel, disabled: busy, children: t("auth.mfa.verify.backToLogin") }) })) : null] }));
|
|
128
133
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
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
|
|
11
11
|
import { AuthCard, useSession } from "../../auth-email-password/web/index.js";
|
|
12
12
|
import { verifyMfaChallenge } from "./mfa-client.js";
|
|
13
|
+
const MFA_CODE_LENGTH = 6;
|
|
13
14
|
function reasonToKey(reason) {
|
|
14
15
|
switch (reason) {
|
|
15
16
|
case "invalid_totp_code":
|
|
@@ -31,13 +32,17 @@ export function MfaVerifyScreen({ challengeToken, title, subtitle, submitLabel,
|
|
|
31
32
|
const t = useTranslation();
|
|
32
33
|
const { Form, Field, Input, Button, Banner } = usePrimitives();
|
|
33
34
|
const session = useSession();
|
|
35
|
+
const [mode, setMode] = useState("authenticator");
|
|
34
36
|
const [code, setCode] = useState("");
|
|
37
|
+
const [attempt, setAttempt] = useState(0);
|
|
35
38
|
const [submitting, setSubmitting] = useState(false);
|
|
36
39
|
const [error, setError] = useState(null);
|
|
37
|
-
const doSubmit = async () => {
|
|
40
|
+
const doSubmit = async (submittedCode) => {
|
|
41
|
+
if (submitting)
|
|
42
|
+
return;
|
|
38
43
|
setSubmitting(true);
|
|
39
44
|
setError(null);
|
|
40
|
-
const res = await verifyMfaChallenge(challengeToken,
|
|
45
|
+
const res = await verifyMfaChallenge(challengeToken, submittedCode);
|
|
41
46
|
if (res.kind === "success") {
|
|
42
47
|
await session.refresh();
|
|
43
48
|
setSubmitting(false);
|
|
@@ -46,12 +51,28 @@ export function MfaVerifyScreen({ challengeToken, title, subtitle, submitLabel,
|
|
|
46
51
|
}
|
|
47
52
|
setSubmitting(false);
|
|
48
53
|
setError(res.error.reason);
|
|
54
|
+
// Remount: the input was disabled during submit and lost focus.
|
|
55
|
+
setAttempt((n) => n + 1);
|
|
56
|
+
if (mode === "authenticator")
|
|
57
|
+
setCode("");
|
|
49
58
|
};
|
|
50
59
|
const onSubmit = (e) => {
|
|
51
60
|
e?.preventDefault();
|
|
52
|
-
void doSubmit();
|
|
61
|
+
void doSubmit(code);
|
|
62
|
+
};
|
|
63
|
+
const toggleMode = () => {
|
|
64
|
+
setMode(mode === "authenticator" ? "recovery" : "authenticator");
|
|
65
|
+
setCode("");
|
|
66
|
+
setError(null);
|
|
53
67
|
};
|
|
54
|
-
|
|
68
|
+
const isRecovery = mode === "recovery";
|
|
69
|
+
const fieldId = isRecovery ? "mfa-verify-recovery-code" : "mfa-verify-code";
|
|
70
|
+
const defaultSubtitle = isRecovery
|
|
71
|
+
? t("auth.mfa.verify.recoverySubtitle")
|
|
72
|
+
: t("auth.mfa.verify.subtitle");
|
|
73
|
+
return (_jsx(AuthCard, { title: title ?? t("auth.mfa.verify.title"), subtitle: subtitle ?? defaultSubtitle, children: _jsxs(Form, { onSubmit: onSubmit, children: [_jsx(Field, { id: fieldId, label: isRecovery ? t("auth.mfa.verify.recoveryCode") : t("auth.mfa.verify.code"), required: true, children: isRecovery ? (_jsx(Input, { kind: "text", id: fieldId, name: fieldId, value: code, onChange: setCode, disabled: submitting, required: true, autoFocus: true, autoComplete: "off" }, `${mode}-${attempt}`)) : (_jsx(Input, { kind: "code", length: MFA_CODE_LENGTH, id: fieldId, name: fieldId, value: code, onChange: setCode, onComplete: (next) => void doSubmit(next), disabled: submitting, hasError: error !== null, required: true, autoFocus: true }, `${mode}-${attempt}`)) }), error !== null ? _jsx(Banner, { variant: "error", children: t(reasonToKey(error)) }) : null, _jsx(Button, { type: "submit", loading: submitting, disabled: submitting, children: submitting
|
|
55
74
|
? t("auth.mfa.verify.submitting")
|
|
56
|
-
: (submitLabel ?? t("auth.mfa.verify.submit")) }),
|
|
75
|
+
: (submitLabel ?? t("auth.mfa.verify.submit")) }), _jsx(Button, { type: "button", variant: "link", onClick: toggleMode, disabled: submitting, children: isRecovery
|
|
76
|
+
? t("auth.mfa.verify.useAuthenticatorCode")
|
|
77
|
+
: t("auth.mfa.verify.useRecoveryCode") }), onCancel ? (_jsx(Button, { type: "button", variant: "secondary", onClick: onCancel, disabled: submitting, children: t("auth.mfa.verify.backToLogin") })) : null] }) }));
|
|
57
78
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deterministic aggregate
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Stripe→Mollie
|
|
6
|
-
*
|
|
2
|
+
* Deterministic aggregate ID for a platform tenant's subscription. Exactly
|
|
3
|
+
* one subscription exists per tenant; add-ons are line items in that
|
|
4
|
+
* subscription, not separate aggregates. A provider change, such as a
|
|
5
|
+
* Stripe→Mollie migration, appends a new event to the same stream because
|
|
6
|
+
* the tenant and aggregate stream remain the same.
|
|
7
7
|
*/
|
|
8
8
|
export declare function subscriptionAggregateId(tenantId: string): string;
|
|
9
9
|
/**
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { v5 as uuidv5 } from "uuid";
|
|
2
|
-
// Fixed UUID
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
/** Pro Plattform-Tenant existiert genau EIN subscription-Aggregate. */
|
|
2
|
+
// Fixed UUID namespace for deterministic aggregate-id derivation.
|
|
3
|
+
// Generated once and immutable: changing it would re-key every existing
|
|
4
|
+
// aggregate stream, breaking subscription state and audit history. The drift
|
|
5
|
+
// pin in __tests__/feature.test.ts locks the UUID.
|
|
6
|
+
/** Exactly one subscription aggregate exists per platform tenant. */
|
|
8
7
|
const SUBSCRIPTION_NAMESPACE = "5c3b2d1e-9a4f-4e8c-b7a3-1f8d6c2e9a4b";
|
|
9
8
|
/** Exactly ONE payment-aggregate-stream exists per platform tenant (it
|
|
10
9
|
* collects many payment-received events — one stream per tenant, not one
|
|
@@ -20,11 +19,11 @@ const PAYMENT_ROW_NAMESPACE = "3a1c9f4e-6b2d-4c8a-9e5f-7d4b1a2c8e6f";
|
|
|
20
19
|
* declaration (one stream per request). Generated 2026-10-03, set in stone. */
|
|
21
20
|
const TERMINATION_UNMATCHED_NAMESPACE = "7e2f4b9a-3c1d-4a68-8d05-b6c9e1f27a34";
|
|
22
21
|
/**
|
|
23
|
-
* Deterministic aggregate
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* Stripe→Mollie
|
|
27
|
-
*
|
|
22
|
+
* Deterministic aggregate ID for a platform tenant's subscription. Exactly
|
|
23
|
+
* one subscription exists per tenant; add-ons are line items in that
|
|
24
|
+
* subscription, not separate aggregates. A provider change, such as a
|
|
25
|
+
* Stripe→Mollie migration, appends a new event to the same stream because
|
|
26
|
+
* the tenant and aggregate stream remain the same.
|
|
28
27
|
*/
|
|
29
28
|
// @wrapper-known uuid-domain
|
|
30
29
|
export function subscriptionAggregateId(tenantId) {
|
|
@@ -17,20 +17,15 @@ export type ResolvedProvider = {
|
|
|
17
17
|
* entityName is registered. */
|
|
18
18
|
export declare function findProviderPlugin(ctx: HandlerContext, providerName: string): ResolvedProvider | null;
|
|
19
19
|
export declare function resolveProviderPlugin(ctx: HandlerContext, providerName: string): ResolvedProvider;
|
|
20
|
-
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* start-plan-checkout and switch-plan. `FeatureDisabledError` (not
|
|
30
|
-
* `UnconfiguredError`) when none is found: an unconfigured provider is
|
|
31
|
-
* the same "billing isn't live yet" state as `isPluginBillingEnabled`
|
|
32
|
-
* returning false, and the panel already renders both the same way. */
|
|
33
|
-
export declare function resolveCatalogProvider(ctx: HandlerContext, catalog: BillingPlanCatalog, handlerName: string): ResolvedProvider;
|
|
20
|
+
/** The providers a catalog sells through, in registration order: an explicit
|
|
21
|
+
* `catalog.providerName` (only that one), otherwise every registered provider
|
|
22
|
+
* exposing `priceToTier`. Empty when none qualifies, a state `billing-plans`
|
|
23
|
+
* renders as `enabled: false` instead of erroring. An explicit `providerName`
|
|
24
|
+
* that is not registered is a config bug and throws `UnconfiguredError`. */
|
|
25
|
+
export declare function listCatalogProviders(ctx: HandlerContext, catalog: BillingPlanCatalog): readonly ResolvedProvider[];
|
|
26
|
+
export declare function filterOfferedProviders(ctx: HandlerContext, providers: readonly ResolvedProvider[]): Promise<readonly ResolvedProvider[]>;
|
|
27
|
+
/** The catalog providers that are live right now: what a buyer can choose from. */
|
|
28
|
+
export declare function listOfferedCatalogProviders(ctx: HandlerContext, catalog: BillingPlanCatalog): Promise<readonly ResolvedProvider[]>;
|
|
34
29
|
/** `plugin.isBillingEnabled?.(ctx) ?? true` — the one place this fallback is
|
|
35
30
|
* spelled out, so no call-site forgets to await the optional method before
|
|
36
31
|
* applying the `?? true` default. */
|