@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
|
@@ -2,27 +2,26 @@ import { collectPiiSubjectFields } from "@cosmicdrift/kumiko-framework/crypto";
|
|
|
2
2
|
import { deriveEntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
|
|
3
3
|
import { access, createEntity, createNumberField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
// ============================================================================
|
|
5
|
-
// Read
|
|
5
|
+
// Read models for the three event-sourced aggregates
|
|
6
6
|
// ============================================================================
|
|
7
7
|
//
|
|
8
|
-
// Inline
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
8
|
+
// Inline projection targets. Written EXCLUSIVELY by projection applies
|
|
9
|
+
// (see feature.ts), never directly by the handler.
|
|
10
|
+
// The event-store streams `mail-account` / `inbound-message` / `mail-thread`
|
|
11
|
+
// are the source of truth, so these tables can be rebuilt.
|
|
12
12
|
//
|
|
13
13
|
// **PII convention:** `personal: "tenant"` (not `encrypted`): fields must
|
|
14
|
-
// crypto-
|
|
15
|
-
// tenant
|
|
16
|
-
// maxLength
|
|
17
|
-
// <blob>` — Plaintext×~2.3 +
|
|
14
|
+
// be crypto-shredded when eraseSubjectKeys deletes the tenant subject key on
|
|
15
|
+
// tenant destruction (pattern from billing-foundation).
|
|
16
|
+
// maxLength is budgeted for ciphertext (`kumiko-pii:v1:<subject>:
|
|
17
|
+
// <blob>` — Plaintext×~2.3 + envelope overhead).
|
|
18
18
|
//
|
|
19
|
-
// **
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* (= accountId, random uuid beim connect). */
|
|
19
|
+
// **Design decision:** The PII subject of an inbound mail is currently the
|
|
20
|
+
// TENANT (mailbox owner), not the external sender. A sender-forget flow would
|
|
21
|
+
// require per-sender keys and is deliberately not included; the erasure path
|
|
22
|
+
// is tenant destruction.
|
|
23
|
+
/** A connected mailbox. One row per account, with PK = aggregateId
|
|
24
|
+
* (= accountId, random uuid on connect). */
|
|
26
25
|
export const mailAccountEntity = createEntity({
|
|
27
26
|
table: "read_mail_accounts",
|
|
28
27
|
fields: {
|
|
@@ -38,10 +37,10 @@ export const mailAccountEntity = createEntity({
|
|
|
38
37
|
personal: false,
|
|
39
38
|
reason: "technical_reference",
|
|
40
39
|
}),
|
|
41
|
-
// null = tenant-
|
|
42
|
-
//
|
|
43
|
-
// Owner + TenantAdmin (
|
|
44
|
-
// V1 (
|
|
40
|
+
// null = tenant-shared mailbox (info@), set = this user's personal
|
|
41
|
+
// mailbox. Visibility filters in the list queries:
|
|
42
|
+
// Owner + TenantAdmin (compliance); NO crypto-subject change in
|
|
43
|
+
// V1 (subject remains Tenant, see header).
|
|
45
44
|
ownerUserId: createTextField({ maxLength: 36, personal: false, reason: "pseudonymous_fk" }),
|
|
46
45
|
// Tenant-authored mailbox label, not a person's name.
|
|
47
46
|
displayName: createTextField({
|
|
@@ -49,7 +48,7 @@ export const mailAccountEntity = createEntity({
|
|
|
49
48
|
personal: false,
|
|
50
49
|
reason: "tenant_config_not_personal",
|
|
51
50
|
}),
|
|
52
|
-
//
|
|
51
|
+
// Mailbox address — tenant PII.
|
|
53
52
|
address: createTextField({ required: true, maxLength: 1000, personal: "tenant", find: "none" }),
|
|
54
53
|
status: createTextField({
|
|
55
54
|
required: true,
|
|
@@ -61,8 +60,8 @@ export const mailAccountEntity = createEntity({
|
|
|
61
60
|
connectedAt: createTimestampField({ required: true }),
|
|
62
61
|
},
|
|
63
62
|
});
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
63
|
+
/** An incoming mail (envelope + snippet, NO body — bodyRef
|
|
64
|
+
* points to file-foundation). PK = aggregateId =
|
|
66
65
|
* inboundMessageAggregateId(accountId, providerMessageId). */
|
|
67
66
|
export const inboundMessageEntity = createEntity({
|
|
68
67
|
table: "read_inbound_messages",
|
|
@@ -73,9 +72,9 @@ export const inboundMessageEntity = createEntity({
|
|
|
73
72
|
personal: false,
|
|
74
73
|
reason: "technical_reference",
|
|
75
74
|
}),
|
|
76
|
-
// Scope
|
|
77
|
-
//
|
|
78
|
-
//
|
|
75
|
+
// Scope is inherited from the account at ingest time: messages from a
|
|
76
|
+
// personal mailbox are visible only to the owner (+ TenantAdmin),
|
|
77
|
+
// without joining read_mail_accounts.
|
|
79
78
|
ownerUserId: createTextField({ maxLength: 36, personal: false, reason: "pseudonymous_fk" }),
|
|
80
79
|
messageIdHeader: createTextField({
|
|
81
80
|
required: true,
|
|
@@ -116,27 +115,27 @@ export const mailThreadEntity = createEntity({
|
|
|
116
115
|
messageCount: createNumberField({ required: true, integer: true }),
|
|
117
116
|
},
|
|
118
117
|
});
|
|
119
|
-
// Single source of truth
|
|
120
|
-
// connect-handler)
|
|
121
|
-
//
|
|
122
|
-
//
|
|
118
|
+
// Single source of truth for the PII field lists — encrypt (ingest/
|
|
119
|
+
// connect-handler) and decrypt (list-queries) share the same list,
|
|
120
|
+
// so a future tenantOwned field cannot be omitted in either location
|
|
121
|
+
// (pattern from billing-foundation entities.ts).
|
|
123
122
|
export const MAIL_ACCOUNT_PII_FIELDS = collectPiiSubjectFields(mailAccountEntity);
|
|
124
123
|
export const INBOUND_MESSAGE_PII_FIELDS = collectPiiSubjectFields(inboundMessageEntity);
|
|
125
124
|
export const MAIL_THREAD_PII_FIELDS = collectPiiSubjectFields(mailThreadEntity);
|
|
126
125
|
// ============================================================================
|
|
127
|
-
// Unmanaged
|
|
126
|
+
// Unmanaged direct-write stores — sync machinery, NOT event-sourced
|
|
128
127
|
// ============================================================================
|
|
129
128
|
//
|
|
130
|
-
// SyncCursor + SeenMessage
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
/** Provider
|
|
137
|
-
* Graph deltaLink, Gmail historyId.
|
|
138
|
-
* Write-locked
|
|
139
|
-
*
|
|
129
|
+
// SyncCursor + SeenMessage are technical tick state for the watch/sync
|
|
130
|
+
// loops: high-frequency writes without business-fact semantics. As
|
|
131
|
+
// r.entity, they would (a) flood the event log and (b) be wiped during a
|
|
132
|
+
// projection rebuild (direct write without an event means the rebuild finds
|
|
133
|
+
// nothing). Therefore r.unmanagedTable — migration DDL, but not a rebuild
|
|
134
|
+
// target (pattern from sessions/feature.ts).
|
|
135
|
+
/** Provider cursor per account ("where was I?"): IMAP UIDVALIDITY:UIDNEXT,
|
|
136
|
+
* Graph deltaLink, Gmail historyId. One row per (accountId, scope).
|
|
137
|
+
* Write-locked to privileged — only Foundation handlers/supervisors
|
|
138
|
+
* write it; tenant requests cannot. */
|
|
140
139
|
export const syncCursorEntity = createEntity({
|
|
141
140
|
table: "store_mail_sync_cursors",
|
|
142
141
|
softDelete: false,
|
|
@@ -168,10 +167,10 @@ export const syncCursorEntity = createEntity({
|
|
|
168
167
|
}),
|
|
169
168
|
},
|
|
170
169
|
});
|
|
171
|
-
/**
|
|
172
|
-
*
|
|
173
|
-
* ingest
|
|
174
|
-
*
|
|
170
|
+
/** Deduplication anchor for O(1) idempotency without scanning the stream
|
|
171
|
+
* for very long message histories: (accountId, providerMessageId) UNIQUE.
|
|
172
|
+
* The ingest handler checks here first (cheap); the stream scan remains
|
|
173
|
+
* defense-in-depth. */
|
|
175
174
|
export const seenMessageEntity = createEntity({
|
|
176
175
|
table: "store_mail_seen_messages",
|
|
177
176
|
softDelete: false,
|
|
@@ -196,9 +195,9 @@ export const seenMessageEntity = createEntity({
|
|
|
196
195
|
}),
|
|
197
196
|
},
|
|
198
197
|
});
|
|
199
|
-
// Plain EntityTableMeta (
|
|
200
|
-
//
|
|
201
|
-
//
|
|
198
|
+
// Plain EntityTableMeta (not a branded EntityTable) — unmanaged direct-
|
|
199
|
+
// write stores; handlers write via ctx.db (see user-session.ts-
|
|
200
|
+
// rationale).
|
|
202
201
|
export const syncCursorTable = deriveEntityTableMeta("mail-sync-cursor", syncCursorEntity, {
|
|
203
202
|
source: "unmanaged",
|
|
204
203
|
});
|
|
@@ -52,13 +52,14 @@ export type MailThreadEventPayload = z.infer<typeof mailThreadEventPayloadSchema
|
|
|
52
52
|
export type InboundMessageEventHeaders = {
|
|
53
53
|
readonly providerMessageId: string;
|
|
54
54
|
readonly providerName: string;
|
|
55
|
-
/** Provider
|
|
56
|
-
*
|
|
55
|
+
/** Provider cursor snapshot at ingest time (UIDVALIDITY:UID, deltaLink,
|
|
56
|
+
* historyId ...) — useful for debugging and replay, not part of the
|
|
57
|
+
* payload. */
|
|
57
58
|
readonly providerCursor: string;
|
|
58
59
|
};
|
|
59
60
|
export type MailAccountEventHeaders = {
|
|
60
61
|
readonly providerName: string;
|
|
61
|
-
/**
|
|
62
|
+
/** What triggered the transition ("connect_flow", "watch_supervisor",
|
|
62
63
|
* "oauth_refresh", "tenant_admin"). */
|
|
63
64
|
readonly reason: string;
|
|
64
65
|
};
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
// Domain
|
|
1
|
+
// Domain events for inbound-mail-foundation.
|
|
2
2
|
//
|
|
3
|
-
// **Pattern:** event-sourced —
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
3
|
+
// **Pattern:** event-sourced — each incoming mail and account-lifecycle
|
|
4
|
+
// transition becomes a domain event. Read models = inline projections
|
|
5
|
+
// (read_mail_accounts / read_inbound_messages / read_mail_threads).
|
|
6
|
+
// Future consumers (business processes: ticket creation, receipt
|
|
7
|
+
// recognition, auto-replies) listen directly to `inbound-message-received`
|
|
8
|
+
// and can replay the COMPLETE history retroactively via
|
|
9
|
+
// extendEntityProjection.
|
|
10
10
|
//
|
|
11
|
-
// **Payload
|
|
12
|
-
// -
|
|
13
|
-
// provider-raw
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
11
|
+
// **Payload discipline (events are forever):**
|
|
12
|
+
// - Domain-clean and generic: no app-specific terms (no solon), and no
|
|
13
|
+
// provider-raw structures in the payload — raw data lives in
|
|
14
|
+
// metadata.headers.
|
|
15
|
+
// - NO bodies: bodyRef points to file-foundation storage. The event store
|
|
16
|
+
// is not a blob store.
|
|
17
|
+
// - PII (address/from/to/cc/subject/snippet) is stored as ciphertext in
|
|
18
|
+
// the payload (`kumiko-pii:v1:...`), encrypted BEFORE append in the
|
|
19
|
+
// write handler — the subject key is the tenant, and tenant destruction's
|
|
20
|
+
// eraseSubjectKeys makes both the event log and projection unreadable
|
|
21
|
+
// (crypto-shredding, the billing-foundation pattern).
|
|
21
22
|
import * as z from "zod";
|
|
22
23
|
import { INBOUND_MAIL_FOUNDATION_FEATURE, InboundMailAccountStatuses } from "./constants.js";
|
|
23
|
-
// Aggregate
|
|
24
|
+
// Aggregate types for the event store.
|
|
24
25
|
export const MAIL_ACCOUNT_AGGREGATE_TYPE = "mail-account";
|
|
25
26
|
export const INBOUND_MESSAGE_AGGREGATE_TYPE = "inbound-message";
|
|
26
27
|
export const MAIL_THREAD_AGGREGATE_TYPE = "mail-thread";
|
|
27
|
-
// Event-name
|
|
28
|
-
//
|
|
28
|
+
// Event-name constants — short forms (for r.defineEvent) and qualified
|
|
29
|
+
// FQNs (for ctx.unsafeAppendEvent and projection-apply keys).
|
|
29
30
|
export const MAIL_ACCOUNT_CONNECTED_EVENT_SHORT = "mail-account-connected";
|
|
30
31
|
export const MAIL_ACCOUNT_UPDATED_EVENT_SHORT = "mail-account-updated";
|
|
31
32
|
export const MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT = "mail-account-disconnected";
|
|
@@ -43,46 +44,48 @@ const accountStatusEnum = z.enum([
|
|
|
43
44
|
InboundMailAccountStatuses.disconnected,
|
|
44
45
|
]);
|
|
45
46
|
// ============================================================================
|
|
46
|
-
// mail-account
|
|
47
|
+
// mail-account stream — connected / updated / disconnected
|
|
47
48
|
// ============================================================================
|
|
48
49
|
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// (
|
|
52
|
-
// billing-foundation events.ts).
|
|
50
|
+
// One stream per mailbox (aggregateId = accountId, random UUID on connect).
|
|
51
|
+
// address is PII, so maxLength is 1000 to allow for ciphertext expansion
|
|
52
|
+
// (a 200-character plaintext becomes ~460+ characters in a JSON envelope;
|
|
53
|
+
// see billing-foundation events.ts).
|
|
53
54
|
export const mailAccountEventPayloadSchema = z.object({
|
|
54
55
|
provider: z.string().min(1).max(50),
|
|
55
|
-
/** "password" | "xoauth2" | "oauth" (InboundMailAuthMethods) —
|
|
56
|
-
* string
|
|
56
|
+
/** "password" | "xoauth2" | "oauth" (InboundMailAuthMethods) — deliberately
|
|
57
|
+
* a string rather than an enum, so new auth methods require no event
|
|
58
|
+
* upcaster. */
|
|
57
59
|
authMethod: z.string().min(1).max(30),
|
|
58
|
-
/** null = tenant
|
|
60
|
+
/** null = shared by the tenant; otherwise, this user's personal mailbox. */
|
|
59
61
|
ownerUserId: z.string().max(36).nullable(),
|
|
60
62
|
displayName: z.string().max(200),
|
|
61
63
|
address: z.string().min(1).max(1000),
|
|
62
64
|
status: accountStatusEnum,
|
|
63
|
-
/** Provider-
|
|
64
|
-
*
|
|
65
|
+
/** Provider-agnostic watch state ("idle", "watching", "backoff:3", ...)
|
|
66
|
+
* — an operational signal only, not PII. */
|
|
65
67
|
watchState: z.string().max(100),
|
|
66
68
|
});
|
|
67
69
|
// ============================================================================
|
|
68
|
-
// inbound-message
|
|
70
|
+
// inbound-message stream — exactly ONE received event per message
|
|
69
71
|
// ============================================================================
|
|
70
72
|
//
|
|
71
73
|
// aggregateId = inboundMessageAggregateId(accountId, providerMessageId)
|
|
72
|
-
// → deterministic,
|
|
74
|
+
// → deterministic, so provider replays collide on the same stream.
|
|
73
75
|
//
|
|
74
|
-
// PII
|
|
75
|
-
// to/cc
|
|
76
|
-
//
|
|
76
|
+
// PII fields (from/to/cc/subject/snippet): ciphertext with generous
|
|
77
|
+
// maximum lengths. to/cc are JSON-stringified string[] BEFORE encryption;
|
|
78
|
+
// the payload contains the ciphertext string, not the array (primitives only,
|
|
79
|
+
// upcaster-safe).
|
|
77
80
|
export const inboundMessageEventPayloadSchema = z.object({
|
|
78
81
|
accountId: z.uuid(),
|
|
79
|
-
/** Scope
|
|
82
|
+
/** Scope inherited from the account at ingest time. */
|
|
80
83
|
ownerUserId: z.string().max(36).nullable(),
|
|
81
|
-
/** RFC-5322 Message-ID
|
|
82
|
-
*
|
|
84
|
+
/** RFC-5322 Message-ID header (normalized, without <>) — NOT PII-encrypted:
|
|
85
|
+
* idempotency/threading anchor and opaque technical ID. */
|
|
83
86
|
messageIdHeader: z.string().min(1).max(500),
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
87
|
+
/** Normalized thread key (References-chain root or provider thread ID,
|
|
88
|
+
* prefixed by the provider). */
|
|
86
89
|
threadKey: z.string().min(1).max(500),
|
|
87
90
|
from: z.string().min(1).max(2000),
|
|
88
91
|
/** JSON-stringified string[], dann PII-encrypted. */
|
|
@@ -91,14 +94,14 @@ export const inboundMessageEventPayloadSchema = z.object({
|
|
|
91
94
|
cc: z.string().max(8000),
|
|
92
95
|
subject: z.string().max(4000),
|
|
93
96
|
snippet: z.string().max(4000),
|
|
94
|
-
/** ISO
|
|
95
|
-
* receivedDateTime),
|
|
97
|
+
/** ISO instant — receipt time reported by the provider (INTERNALDATE or
|
|
98
|
+
* receivedDateTime), not ingest time. */
|
|
96
99
|
receivedAtIso: z.string().min(1),
|
|
97
|
-
/** file-foundation
|
|
98
|
-
*
|
|
100
|
+
/** file-foundation reference to the raw body (MIME). Empty when the app
|
|
101
|
+
* is mounted without body persistence (snippet-only mode). */
|
|
99
102
|
bodyRef: z.string().max(500),
|
|
100
|
-
/**
|
|
101
|
-
*
|
|
103
|
+
/** Domain scope hint for downstream business processes — generic
|
|
104
|
+
* ("inbox", folder name), with NO app-specific semantics. */
|
|
102
105
|
scope: z.string().max(200),
|
|
103
106
|
});
|
|
104
107
|
// ============================================================================
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
// kumiko-feature-version: 1
|
|
2
2
|
//
|
|
3
|
-
// inbound-mail-foundation — Plugin
|
|
4
|
-
// (
|
|
5
|
-
//
|
|
6
|
-
// file-foundation (
|
|
3
|
+
// inbound-mail-foundation — Plugin host for inbound e-mail
|
|
4
|
+
// (inbox federation). Counterpart to mail-foundation (outbound): separate
|
|
5
|
+
// extension points, separate state — architectural model is
|
|
6
|
+
// file-foundation (the foundation owns state), not mail-transport.
|
|
7
7
|
//
|
|
8
|
-
// **Multi-
|
|
9
|
-
// `provider
|
|
10
|
-
//
|
|
8
|
+
// **Multi-provider from day one** (as with billing-foundation): NO global
|
|
9
|
+
// `provider` config key. A tenant can connect IMAP and (later) M365/Gmail
|
|
10
|
+
// mailboxes in parallel; the provider is specified per MailAccount.
|
|
11
11
|
//
|
|
12
|
-
// **
|
|
13
|
-
// 1. **Plugin
|
|
12
|
+
// **What this foundation provides:**
|
|
13
|
+
// 1. **Plugin API** for inbound providers via r.extendsRegistrar
|
|
14
14
|
// ("inboundMailProvider"): verify/fetch/oauth?/watch? (types.ts).
|
|
15
|
-
// 2. **3 event-sourced
|
|
16
|
-
// inbound-message (
|
|
17
|
-
// aggregateId ⇒ exactly-once
|
|
18
|
-
// mail-thread (
|
|
19
|
-
//
|
|
20
|
-
// 3. **Inline
|
|
15
|
+
// 2. **3 event-sourced streams** — mail-account (lifecycle),
|
|
16
|
+
// inbound-message (exactly ONE received event per message, deterministic
|
|
17
|
+
// aggregateId ⇒ exactly-once despite at-least-once ingest),
|
|
18
|
+
// mail-thread (rollup). Full replayable history for later
|
|
19
|
+
// consumers (business processes: ticket, receipt, auto-reply).
|
|
20
|
+
// 3. **Inline projections** into read_mail_accounts /
|
|
21
21
|
// read_inbound_messages / read_mail_threads (read-your-own-write).
|
|
22
|
-
// 4. **Write
|
|
22
|
+
// 4. **Write/query handlers**: connect/update/disconnect-account,
|
|
23
23
|
// ingest-message (programmatic, SystemAdmin), account:list +
|
|
24
|
-
// message:list (PII-decrypted, scope-
|
|
25
|
-
// 5. **createInboundMailConnectRoutes**: OAuth
|
|
26
|
-
//
|
|
27
|
-
// 6. **createInboundMailSupervisor**: app-
|
|
28
|
-
//
|
|
24
|
+
// message:list (PII-decrypted, scope-filtered).
|
|
25
|
+
// 5. **createInboundMailConnectRoutes**: OAuth connect + anonymous
|
|
26
|
+
// callback (outside /api/*), with HMAC-signed state.
|
|
27
|
+
// 6. **createInboundMailSupervisor**: app-wired watch (IDLE)
|
|
28
|
+
// supervisor with backoff + reconciliation poll.
|
|
29
29
|
//
|
|
30
|
-
// **
|
|
31
|
-
// -
|
|
32
|
-
//
|
|
33
|
-
// inbound-message-received +
|
|
34
|
-
// -
|
|
35
|
-
// Supervisor-storeBody-Hook
|
|
36
|
-
// -
|
|
30
|
+
// **What this foundation does NOT do:**
|
|
31
|
+
// - No business semantics (intent, ticket, assignment, read/
|
|
32
|
+
// completed) — those belong to the app consumer (for example, via an
|
|
33
|
+
// event job on inbound-message-received + its own projection).
|
|
34
|
+
// - No body blob in the event store: rawMime → file-foundation via
|
|
35
|
+
// the Supervisor-storeBody-Hook; the event carries only bodyRef.
|
|
36
|
+
// - No IMAP flag write-back (V1) — inbox status belongs to the consumer.
|
|
37
37
|
//
|
|
38
38
|
// **PII/GDPR:** address/from/to/cc/subject/snippet are `personal: "tenant"`
|
|
39
39
|
// — encrypted BEFORE every event append (the only write path), event log AND
|
|
40
40
|
// projections carry ciphertext; tenant-destroy shreds the subject key
|
|
41
|
-
// (crypto-shredding, same pattern as billing-foundation
|
|
41
|
+
// (crypto-shredding, the same pattern as billing-foundation). The destroy
|
|
42
42
|
// hook additionally archives all streams + deletes the rows.
|
|
43
43
|
import { defineFeature, EXT_TENANT_DATA } from "@cosmicdrift/kumiko-framework/engine";
|
|
44
44
|
import { createFileProviderForTenant, } from "@cosmicdrift/kumiko-framework/files";
|
|
@@ -64,7 +64,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
64
64
|
category: "notifications",
|
|
65
65
|
recommended: false,
|
|
66
66
|
});
|
|
67
|
-
// EXT_TENANT_DATA
|
|
67
|
+
// The EXT_TENANT_DATA hook requires the tenant-lifecycle host.
|
|
68
68
|
r.requires({ features: ["tenant-lifecycle"] });
|
|
69
69
|
// 5 fine-grained domain-events (Payload-Schemas: events.ts).
|
|
70
70
|
// piiFields: "none" — address/subject/snippet are already ciphertext under the tenant subject key before append (see events.ts).
|
|
@@ -86,7 +86,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
86
86
|
r.defineEvent(MAIL_THREAD_UPDATED_EVENT_SHORT, mailThreadEventPayloadSchema, {
|
|
87
87
|
piiFields: "none",
|
|
88
88
|
});
|
|
89
|
-
// Inline projections — apply in
|
|
89
|
+
// Inline projections — apply in the same transaction as the append.
|
|
90
90
|
r.projection({
|
|
91
91
|
name: "mail-account",
|
|
92
92
|
source: MAIL_ACCOUNT_AGGREGATE_TYPE,
|
|
@@ -126,7 +126,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
126
126
|
});
|
|
127
127
|
// Sync machinery: high-frequency tick state, deliberately NOT
|
|
128
128
|
// event-sourced — r.storeTable keeps the migration DDL but excludes the
|
|
129
|
-
// tables from the projection rebuild
|
|
129
|
+
// tables from the projection rebuild.
|
|
130
130
|
r.storeTable(syncCursorTable, {
|
|
131
131
|
reason: "read_side.mail_sync_cursors_direct_write",
|
|
132
132
|
});
|
|
@@ -148,8 +148,8 @@ export function createInboundMailFoundationFeature() {
|
|
|
148
148
|
r.screen(mailAccountListScreen);
|
|
149
149
|
r.screen(mailAccountEditScreen);
|
|
150
150
|
r.translations({ keys: INBOUND_MAIL_FOUNDATION_I18N });
|
|
151
|
-
// Entity-
|
|
152
|
-
//
|
|
151
|
+
// Entity-specific GDPR destroy hooks — the gdpr-storage boot validator
|
|
152
|
+
// checks the EXT_TENANT_DATA registration for each tenant-subject entity.
|
|
153
153
|
r.useExtension(EXT_TENANT_DATA, "mail-account", {
|
|
154
154
|
destroy: mailAccountTenantDestroyHook,
|
|
155
155
|
escapeHatch: { reason: INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON },
|
|
@@ -162,7 +162,7 @@ export function createInboundMailFoundationFeature() {
|
|
|
162
162
|
destroy: mailThreadTenantDestroyHook,
|
|
163
163
|
escapeHatch: { reason: INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON },
|
|
164
164
|
});
|
|
165
|
-
// Data-Retention
|
|
165
|
+
// Data-Retention — perTenant fan-out (one run per tenant, like
|
|
166
166
|
// data-retention:retention-cleanup): runInboundMailRetention's raw query
|
|
167
167
|
// helpers need the unfiltered runner, so the handler declares escapeHatch
|
|
168
168
|
// and reaches for ctx.db.unsafeRaw(). Without this cron, read_inbound_messages
|
|
@@ -185,10 +185,10 @@ export function createInboundMailFoundationFeature() {
|
|
|
185
185
|
}
|
|
186
186
|
const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
|
|
187
187
|
const retentionDb = ctx.db.unsafeRaw(); // @cast-boundary db-operator — jobs never run inside a DbTx
|
|
188
|
-
// Body
|
|
189
|
-
//
|
|
190
|
-
//
|
|
191
|
-
//
|
|
188
|
+
// Body objects are stored in file-foundation. The provider is lazy and memoized —
|
|
189
|
+
// ingest currently writes no bodyRef (the storeBody hook is not wired),
|
|
190
|
+
// so the provider is never built. Once storeBody is wired, retention
|
|
191
|
+
// also cleans up the bodies.
|
|
192
192
|
let providerPromise = null;
|
|
193
193
|
const deleteBodyObject = async (bodyRef) => {
|
|
194
194
|
if (!providerPromise) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Shared state loader for update-account / disconnect-account.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// "
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// mail-account events are full snapshots (following the billing-foundation
|
|
4
|
+
// pattern: "All events use the same payload shape; the event-type identifies
|
|
5
|
+
// what happened") — a transitional handler loads the latest snapshot, merges
|
|
6
|
+
// its delta fields into it, and appends the new snapshot.
|
|
7
7
|
//
|
|
8
|
-
// **PII
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// **PII discipline:** `address` is already ciphertext in the loaded payload
|
|
9
|
+
// and is copied byte-for-byte — NEVER re-encrypt it (that would require KMS
|
|
10
|
+
// decryption when unavailable or produce double encryption).
|
|
11
11
|
export async function loadCurrentMailAccountPayload(ctx, accountId) {
|
|
12
12
|
const events = await ctx.loadAggregate(accountId);
|
|
13
13
|
const last = events[events.length - 1];
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
// connect-account —
|
|
2
|
-
// mail-account
|
|
3
|
-
//
|
|
1
|
+
// connect-account — A tenant admin connects a mailbox. Creates the
|
|
2
|
+
// mail-account stream (aggregateId = random uuid = accountId =
|
|
3
|
+
// secret-slot key for the IMAP password/OAuth refresh token).
|
|
4
4
|
//
|
|
5
|
-
// **
|
|
6
|
-
// -
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
// asynchron als Status-Übergang).
|
|
5
|
+
// **What does NOT happen here:**
|
|
6
|
+
// - No secret write: IMAP credentials use the secrets path, and OAuth
|
|
7
|
+
// tokens use the generic /inbound-mail/oauth routes—both before or
|
|
8
|
+
// after this call, never in the handler payload (plain passwords must
|
|
9
|
+
// not enter a write payload that can appear in the dispatcher log).
|
|
10
|
+
// - No connection test: the watch supervisor attempts the first fetch
|
|
11
|
+
// and switches to auth_error via update-account on failure—the connect
|
|
12
|
+
// stays fast and offline-capable (the test result arrives asynchronously
|
|
13
|
+
// as a status transition).
|
|
15
14
|
import { configuredPiiSubjectKms, encryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
16
15
|
import { failUnprocessable } from "@cosmicdrift/kumiko-framework/errors";
|
|
17
16
|
import * as z from "zod";
|
|
@@ -19,7 +18,7 @@ import { InboundMailAccountStatuses, InboundMailAuthMethods } from "../constants
|
|
|
19
18
|
import { MAIL_ACCOUNT_PII_FIELDS, mailAccountEntity } from "../entities.js";
|
|
20
19
|
import { MAIL_ACCOUNT_AGGREGATE_TYPE, MAIL_ACCOUNT_CONNECTED_EVENT_QN, } from "../events.js";
|
|
21
20
|
export const connectAccountSchema = z.object({
|
|
22
|
-
/** Provider
|
|
21
|
+
/** Provider key registered with the extension ("imap",
|
|
23
22
|
* "m365-graph", "gmail-rest"). */
|
|
24
23
|
provider: z.string().min(1).max(50),
|
|
25
24
|
authMethod: z.enum([
|
|
@@ -28,16 +27,16 @@ export const connectAccountSchema = z.object({
|
|
|
28
27
|
InboundMailAuthMethods.oauth,
|
|
29
28
|
]),
|
|
30
29
|
displayName: z.string().max(200),
|
|
31
|
-
/**
|
|
30
|
+
/** Mailbox address in plaintext; it is encrypted here. */
|
|
32
31
|
address: z.string().min(1).max(320),
|
|
33
|
-
/** "shared" = tenant
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
/** "shared" = shared across the tenant (info@) · "user" = the caller's
|
|
33
|
+
* personal mailbox (ownerUserId is taken from the session, never from
|
|
34
|
+
* the payload—preventing claims on another user's mailbox). */
|
|
36
35
|
scope: z.enum(["shared", "user"]),
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* HMAC-
|
|
40
|
-
*
|
|
36
|
+
/** Only for the programmatic OAuth callback path (SystemAdmin): there,
|
|
37
|
+
* the dispatcher user is a SystemUser and the actual owner is in the
|
|
38
|
+
* HMAC-verified state. Tenant callers must not set this field (the
|
|
39
|
+
* handler prevents claims on another user's mailbox). */
|
|
41
40
|
ownerUserIdOverride: z.string().max(36).nullable().optional(),
|
|
42
41
|
});
|
|
43
42
|
export const connectAccountHandler = {
|
|
@@ -58,8 +57,8 @@ export const connectAccountHandler = {
|
|
|
58
57
|
: payload.scope === "user"
|
|
59
58
|
? event.user.id
|
|
60
59
|
: null;
|
|
61
|
-
// PII-
|
|
62
|
-
//
|
|
60
|
+
// PII-encrypt the address before the append. This is the only write path to
|
|
61
|
+
// the stream, so it covers both the event log and the projection.
|
|
63
62
|
const piiKms = configuredPiiSubjectKms();
|
|
64
63
|
const plainPii = { tenantId, address: payload.address };
|
|
65
64
|
const encryptedFields = piiKms
|
|
@@ -71,8 +70,8 @@ export const connectAccountHandler = {
|
|
|
71
70
|
ownerUserId,
|
|
72
71
|
displayName: payload.displayName,
|
|
73
72
|
address: encryptedFields.address,
|
|
74
|
-
// active
|
|
75
|
-
//
|
|
73
|
+
// The account is active upon connection; the supervisor picks it up on
|
|
74
|
+
// the next tick and downgrades it when credentials fail.
|
|
76
75
|
status: InboundMailAccountStatuses.active,
|
|
77
76
|
watchState: "idle",
|
|
78
77
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// disconnect-account —
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// disconnect-account — A TenantAdmin disconnects a mailbox. The stream is retained
|
|
2
|
+
// for audit history, the status becomes disconnected, and the watch supervisor
|
|
3
|
+
// skips the account starting with the next tick. Secret cleanup (IMAP password/
|
|
4
|
+
// refresh token in the accountId slot) is handled by the caller flow; this handler
|
|
5
|
+
// does not touch the secrets path.
|
|
6
6
|
//
|
|
7
|
-
// Idempotent:
|
|
8
|
-
//
|
|
7
|
+
// Idempotent: disconnecting an already disconnected account is a success no-op
|
|
8
|
+
// with no second event, making double-clicks and retries safe.
|
|
9
9
|
import { failNotFound } from "@cosmicdrift/kumiko-framework/errors";
|
|
10
10
|
import * as z from "zod";
|
|
11
11
|
import { InboundMailAccountStatuses } from "../constants.js";
|