@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
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
// ingest-message — programmatic entry
|
|
2
|
-
// (watch
|
|
3
|
-
// RawInboundMessage
|
|
1
|
+
// ingest-message — programmatic entry point for provider plugins
|
|
2
|
+
// (watch callback + fetchSince sync). Accepts a normalized
|
|
3
|
+
// RawInboundMessage and performs atomically in ONE TX:
|
|
4
4
|
//
|
|
5
|
-
// 1. Idempotency
|
|
6
|
-
// depth:
|
|
7
|
-
// 2. threadKey
|
|
8
|
-
// References
|
|
9
|
-
// 3. PII
|
|
10
|
-
//
|
|
11
|
-
// 4. inbound-message-received
|
|
12
|
-
// read_inbound_messages in
|
|
5
|
+
// 1. Idempotency check (cheap: store_mail_seen_messages; defense in
|
|
6
|
+
// depth: stream existence check on the deterministic aggregateId).
|
|
7
|
+
// 2. threadKey normalization (provider thread ID preferred, otherwise
|
|
8
|
+
// References chain root, otherwise Message-ID = single-message thread).
|
|
9
|
+
// 3. PII encryption (from/to/cc/subject/snippet) BEFORE the append —
|
|
10
|
+
// both the event log AND projection contain ciphertext.
|
|
11
|
+
// 4. inbound-message-received append (inline projection writes
|
|
12
|
+
// read_inbound_messages in the same TX). Savepoint-scoped
|
|
13
13
|
// (ctx.tryAppendEvent) — a losing concurrent ingest for the same
|
|
14
14
|
// messageAggId returns { duplicate: true } instead of failing the TX.
|
|
15
|
-
// 5. Thread
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// 6. seen-message
|
|
15
|
+
// 5. Thread rollup: mail-thread-updated append with a recalculated
|
|
16
|
+
// snapshot (count+1, max(lastMessageAt)) — the apply is a
|
|
17
|
+
// dumb UPSERT.
|
|
18
|
+
// 6. Insert the seen-message deduplication anchor.
|
|
19
19
|
//
|
|
20
|
-
// SystemAdmin-only:
|
|
21
|
-
//
|
|
20
|
+
// SystemAdmin-only: the caller is the watch/sync supervisor or
|
|
21
|
+
// the poll cron with a programmatic SystemUser — never a tenant request.
|
|
22
22
|
import { configuredPiiSubjectKms, encryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
23
23
|
import { acquireNamespacedAdvisoryLock, countWhere } from "@cosmicdrift/kumiko-framework/db";
|
|
24
24
|
import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
|
|
@@ -29,24 +29,24 @@ import { INBOUND_MESSAGE_PII_FIELDS, inboundMessageEntity, MAIL_THREAD_PII_FIELD
|
|
|
29
29
|
import { INBOUND_MESSAGE_AGGREGATE_TYPE, INBOUND_MESSAGE_RECEIVED_EVENT_QN, MAIL_THREAD_AGGREGATE_TYPE, MAIL_THREAD_UPDATED_EVENT_QN, } from "../events.js";
|
|
30
30
|
import { inboundMessagesProjectionTable } from "../projection.js";
|
|
31
31
|
// =============================================================================
|
|
32
|
-
// Input
|
|
33
|
-
// types.ts)
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
32
|
+
// Input schema — the normalized provider output (RawInboundMessage,
|
|
33
|
+
// types.ts) plus the envelope (accountId/providerName/providerCursor). rawMime
|
|
34
|
+
// is intentionally excluded: the caller persists the body to
|
|
35
|
+
// file-foundation BEFORE the ingest call and passes only bodyRef — the
|
|
36
|
+
// handler payload remains blob-free (event-store discipline).
|
|
37
37
|
// =============================================================================
|
|
38
38
|
export const ingestMessageSchema = z.object({
|
|
39
39
|
accountId: z.uuid(),
|
|
40
|
-
/** Scope
|
|
41
|
-
* MailAccountRecord
|
|
40
|
+
/** Scope inherited from the account — the supervisor knows the
|
|
41
|
+
* MailAccountRecord and passes ownerUserId through. */
|
|
42
42
|
ownerUserId: z.string().max(36).nullable(),
|
|
43
43
|
providerName: z.string().min(1).max(50),
|
|
44
|
-
/** Provider-native Message-ID —
|
|
44
|
+
/** Provider-native Message-ID — idempotency anchor with accountId. */
|
|
45
45
|
providerMessageId: z.string().min(1).max(500),
|
|
46
|
-
/** RFC-5322 Message-ID
|
|
46
|
+
/** RFC-5322 Message-ID without <>; null → deterministic fallback. */
|
|
47
47
|
messageIdHeader: z.string().min(1).max(500).nullable(),
|
|
48
48
|
providerThreadId: z.string().min(1).max(500).nullable(),
|
|
49
|
-
/** References/In-Reply-To
|
|
49
|
+
/** References/In-Reply-To chain, oldest first. */
|
|
50
50
|
references: z.array(z.string().min(1).max(500)).max(200),
|
|
51
51
|
from: z.string().min(1).max(2000),
|
|
52
52
|
to: z.array(z.string().max(2000)).max(200),
|
|
@@ -57,18 +57,18 @@ export const ingestMessageSchema = z.object({
|
|
|
57
57
|
/** file-foundation-Ref; leer im snippet-only-Mode. */
|
|
58
58
|
bodyRef: z.string().max(500),
|
|
59
59
|
scope: z.string().min(1).max(200),
|
|
60
|
-
/** Cursor
|
|
61
|
-
* metadata.headers,
|
|
60
|
+
/** Cursor snapshot at ingest time — used for debugging/replay and stored in
|
|
61
|
+
* metadata.headers, never in the payload. */
|
|
62
62
|
providerCursor: z.string().max(2000),
|
|
63
63
|
});
|
|
64
64
|
/**
|
|
65
|
-
* threadKey
|
|
66
|
-
* 1.
|
|
67
|
-
* IMAP
|
|
68
|
-
* 2.
|
|
69
|
-
*
|
|
70
|
-
* 3.
|
|
71
|
-
*
|
|
65
|
+
* Normalizes threadKey:
|
|
66
|
+
* 1. Use the provider thread ID when present — prefix it with the provider
|
|
67
|
+
* so IMAP References keys and Graph conversationIds never collide.
|
|
68
|
+
* 2. Otherwise use the root of the References chain (the oldest Message-ID,
|
|
69
|
+
* which is the thread anchor shared by all replies).
|
|
70
|
+
* 3. Otherwise use the own Message-ID → single-message thread; a later
|
|
71
|
+
* reply carries it as the References root and joins the same thread.
|
|
72
72
|
*/
|
|
73
73
|
function buildThreadKey(p, effectiveMessageIdHeader) {
|
|
74
74
|
if (p.providerThreadId)
|
|
@@ -99,12 +99,12 @@ export const ingestMessageHandler = {
|
|
|
99
99
|
const tenantId = event.user.tenantId;
|
|
100
100
|
const messageAggId = inboundMessageAggregateId(payload.accountId, payload.providerMessageId);
|
|
101
101
|
// ---------------------------------------------------------------
|
|
102
|
-
// 1. Idempotency.
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
102
|
+
// 1. Idempotency. Use the deduplication anchor row first because it is
|
|
103
|
+
// cheap. The stream check afterward provides defense in depth if
|
|
104
|
+
// an earlier ingest died AFTER the append but BEFORE the seen insert
|
|
105
|
+
// (this cannot happen within one TX, but the check is cheap and makes
|
|
106
|
+
// the handler robust to rebuilding if store_mail_seen_messages is
|
|
107
|
+
// ever truncated).
|
|
108
108
|
// ---------------------------------------------------------------
|
|
109
109
|
const seenRows = await ctx.db.selectMany(seenMessageTable, {
|
|
110
110
|
accountId: payload.accountId,
|
|
@@ -137,11 +137,10 @@ export const ingestMessageHandler = {
|
|
|
137
137
|
const threadKey = buildThreadKey(payload, effectiveMessageIdHeader);
|
|
138
138
|
const threadAggId = mailThreadAggregateId(tenantId, threadKey);
|
|
139
139
|
// ---------------------------------------------------------------
|
|
140
|
-
// 3. PII
|
|
141
|
-
//
|
|
142
|
-
// (primitives only, upcaster-safe).
|
|
143
|
-
// plaintext
|
|
144
|
-
// billing-foundation process-event #724/#800).
|
|
140
|
+
// 3. PII encryption. Serialize to/cc as JSON BEFORE encryption so the
|
|
141
|
+
// payload contains a ciphertext string rather than an array
|
|
142
|
+
// (primitives only, upcaster-safe). If no KMS is configured, pass
|
|
143
|
+
// through plaintext (engine-off behavior).
|
|
145
144
|
// ---------------------------------------------------------------
|
|
146
145
|
const piiKms = configuredPiiSubjectKms();
|
|
147
146
|
const messagePlainPii = {
|
|
@@ -208,14 +207,14 @@ export const ingestMessageHandler = {
|
|
|
208
207
|
// concurrent ingests on the same thread (Watch-Push vs.
|
|
209
208
|
// Poll-Reconciliation overlap, or two different messages of the
|
|
210
209
|
// same thread arriving at once) converge on the true count.
|
|
211
|
-
// acquireNamespacedAdvisoryLock below
|
|
210
|
+
// acquireNamespacedAdvisoryLock below serializes this whole
|
|
212
211
|
// countWhere+append section per threadAggId — transaction-scoped,
|
|
213
212
|
// so it survives tryAppendEvent's inner SAVEPOINT and releases at
|
|
214
213
|
// the enclosing TX's commit/rollback. Without it, a concurrent
|
|
215
214
|
// commit landing between countWhere and tryAppendEvent's own fresh
|
|
216
215
|
// version-read makes the append succeed with a stale count instead
|
|
217
216
|
// of a VersionConflictError, so the retry loop below never sees it
|
|
218
|
-
// as a conflict to retry (
|
|
217
|
+
// as a conflict to retry (the original gap). Unlike step 4, a
|
|
219
218
|
// lost version-conflict race here must NOT be treated as a no-op
|
|
220
219
|
// duplicate — skipping would leave this message's contribution to
|
|
221
220
|
// messageCount/lastMessageAt out of the thread forever. Exhausting
|
|
@@ -264,8 +263,8 @@ export const ingestMessageHandler = {
|
|
|
264
263
|
});
|
|
265
264
|
}
|
|
266
265
|
// ---------------------------------------------------------------
|
|
267
|
-
// 6.
|
|
268
|
-
//
|
|
266
|
+
// 6. Deduplication anchor. It runs in the same TX as the appends, so
|
|
267
|
+
// if the handler fails, everything is rolled back together.
|
|
269
268
|
// ---------------------------------------------------------------
|
|
270
269
|
await ctx.db.insertOne(seenMessageTable, {
|
|
271
270
|
tenantId,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// list-accounts — tenant-scoped
|
|
2
|
-
// Connect
|
|
3
|
-
// billing-foundation list-subscriptions
|
|
1
|
+
// list-accounts — tenant-scoped list of connected mailboxes for the
|
|
2
|
+
// Connect/Settings UI. PII (address) is decrypted on read, following the
|
|
3
|
+
// billing-foundation list-subscriptions pattern.
|
|
4
4
|
//
|
|
5
|
-
// **Scope
|
|
6
|
-
// (ownerUserId=null)
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
5
|
+
// **Scope visibility:** authorized users can see shared mailboxes
|
|
6
|
+
// (ownerUserId=null); personal mailboxes are visible only to their owner,
|
|
7
|
+
// TenantAdmin, or SystemAdmin for compliance access. Filtering runs in memory
|
|
8
|
+
// after the tenant-scoped select because a tenant has only a single- to
|
|
9
|
+
// double-digit number of connected mailboxes.
|
|
10
10
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
11
11
|
import { MAX_LIST_LIMIT } from "@cosmicdrift/kumiko-framework/engine";
|
|
12
12
|
import * as z from "zod";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// list-messages — tenant-scoped
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// list-messages — tenant-scoped message list for the inbox cockpit.
|
|
2
|
+
// Optional filters: accountId (one mailbox), threadKey (one conversation),
|
|
3
|
+
// scope (folder hint). PII (from/to/cc/subject/snippet) is decrypted on read;
|
|
4
|
+
// to/cc remain JSON-stringified strings, which the client parses as documented
|
|
5
|
+
// in the event payload.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// Deliberately no pagination in V1: the projection is tenant-scoped and the
|
|
8
|
+
// inbox cockpit loads bounded time ranges; a `limit` field can be added
|
|
9
|
+
// compatibly without breaking the QN.
|
|
10
10
|
import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
|
|
11
11
|
import * as z from "zod";
|
|
12
12
|
import { INBOUND_MESSAGE_PII_FIELDS } from "../entities.js";
|
|
@@ -35,8 +35,8 @@ export const listMessagesQuery = {
|
|
|
35
35
|
if (payload.scope)
|
|
36
36
|
filter["scope"] = payload.scope;
|
|
37
37
|
const allRows = await ctx.db.selectMany(inboundMessagesProjectionTable, filter);
|
|
38
|
-
// Scope
|
|
39
|
-
//
|
|
38
|
+
// Scope visibility: messages in personal mailboxes are visible only to the
|
|
39
|
+
// owner or TenantAdmin/SystemAdmin.
|
|
40
40
|
const rows = allRows.filter((row) => isVisibleToCaller(row, ctx.user));
|
|
41
41
|
const piiKms = configuredPiiSubjectKms();
|
|
42
42
|
if (!piiKms)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// Scope
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// für read_mail_accounts und read_inbound_messages (Scope-Vererbung).
|
|
1
|
+
// Scope visibility: shared rows (`ownerUserId=null`) are visible to any authorized caller;
|
|
2
|
+
// personal rows are visible only to the owner, `TenantAdmin`, or `SystemAdmin` for compliance.
|
|
3
|
+
// The same rule applies to `read_mail_accounts` and `read_inbound_messages`.
|
|
5
4
|
export function isVisibleToCaller(row, user) {
|
|
6
5
|
const owner = row["ownerUserId"];
|
|
7
6
|
if (owner == null || owner === "")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
export declare const updateAccountSchema: z.ZodObject<{
|
|
4
4
|
accountId: z.ZodUUID;
|
|
@@ -9,6 +9,6 @@ export declare const updateAccountSchema: z.ZodObject<{
|
|
|
9
9
|
}>>;
|
|
10
10
|
watchState: z.ZodOptional<z.ZodString>;
|
|
11
11
|
displayName: z.ZodOptional<z.ZodString>;
|
|
12
|
-
reason: z.ZodString
|
|
12
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
13
13
|
}, z.core.$strip>;
|
|
14
14
|
export declare const updateAccountHandler: WriteHandlerDef;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
// update-account — Account
|
|
2
|
-
// error/backoff, OAuth
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// update-account — Account status transitions: the watch supervisor reports
|
|
2
|
+
// error/backoff, OAuth refresh fails (auth_error), or a tenant admin re-enables
|
|
3
|
+
// the account after fixing its credentials. Full-snapshot event: loads the
|
|
4
|
+
// latest state, merges the delta fields, and appends the new snapshot.
|
|
5
|
+
import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
|
|
6
|
+
import { SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
|
|
5
7
|
import { failNotFound, failUnprocessable } from "@cosmicdrift/kumiko-framework/errors";
|
|
6
8
|
import * as z from "zod";
|
|
7
9
|
import { InboundMailAccountStatuses } from "../constants.js";
|
|
@@ -19,10 +21,16 @@ export const updateAccountSchema = z.object({
|
|
|
19
21
|
/** Ops-Signal ("idle", "watching", "backoff:3", ...). */
|
|
20
22
|
watchState: z.string().max(100).optional(),
|
|
21
23
|
displayName: z.string().max(200).optional(),
|
|
22
|
-
/** Audit
|
|
23
|
-
* "
|
|
24
|
-
reason: z.string().min(1).max(100),
|
|
24
|
+
/** Audit reason for metadata.headers, honored for the system identity only
|
|
25
|
+
* ("watch_supervisor", "oauth_refresh"); user callers get a role-derived reason. */
|
|
26
|
+
reason: z.string().min(1).max(100).optional(),
|
|
25
27
|
});
|
|
28
|
+
const SYSTEM_FALLBACK_REASON = "system";
|
|
29
|
+
function auditReasonFor(user, requestedReason) {
|
|
30
|
+
if (user.id === SYSTEM_USER_ID)
|
|
31
|
+
return requestedReason ?? SYSTEM_FALLBACK_REASON;
|
|
32
|
+
return user.roles.includes(ROLES.SystemAdmin) ? "system_admin" : "tenant_admin";
|
|
33
|
+
}
|
|
26
34
|
export const updateAccountHandler = {
|
|
27
35
|
name: "update-account",
|
|
28
36
|
schema: updateAccountSchema,
|
|
@@ -36,14 +44,14 @@ export const updateAccountHandler = {
|
|
|
36
44
|
return failNotFound("mail-account", payload.accountId);
|
|
37
45
|
}
|
|
38
46
|
if (current.status === InboundMailAccountStatuses.disconnected) {
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
47
|
+
// Disconnected accounts are final; re-enabling requires a fresh connect
|
|
48
|
+
// (new stream, new secret slot). This prevents a delayed supervisor tick
|
|
49
|
+
// from restoring a disconnected account to active (disconnect vs. poll
|
|
50
|
+
// race).
|
|
43
51
|
return failUnprocessable("account_disconnected", { accountId: payload.accountId });
|
|
44
52
|
}
|
|
45
|
-
//
|
|
46
|
-
//
|
|
53
|
+
// address/provider/authMethod come unchanged from the latest snapshot
|
|
54
|
+
// (address remains ciphertext—never re-encrypt it).
|
|
47
55
|
const eventPayload = {
|
|
48
56
|
...current,
|
|
49
57
|
...(payload.status !== undefined ? { status: payload.status } : {}),
|
|
@@ -52,7 +60,7 @@ export const updateAccountHandler = {
|
|
|
52
60
|
};
|
|
53
61
|
const headers = {
|
|
54
62
|
providerName: current.provider,
|
|
55
|
-
reason: payload.reason,
|
|
63
|
+
reason: auditReasonFor(event.user, payload.reason),
|
|
56
64
|
};
|
|
57
65
|
await ctx.unsafeAppendEvent({
|
|
58
66
|
aggregateId: payload.accountId,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
2
2
|
export type OAuthStatePayload = {
|
|
3
3
|
readonly tenantId: string;
|
|
4
|
-
/** null = shared
|
|
4
|
+
/** null = shared mailbox; otherwise this user's personal mailbox. */
|
|
5
5
|
readonly ownerUserId: string | null;
|
|
6
6
|
readonly providerKey: string;
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
7
|
+
/** Mailbox address from the connect request; after token exchange, it is
|
|
8
|
+
* stored in the MailAccount. */
|
|
9
9
|
readonly mailbox: string;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
10
|
+
/** One-time nonce makes each state unique, preventing replay across
|
|
11
|
+
* two parallel connect flows. */
|
|
12
12
|
readonly nonce: string;
|
|
13
13
|
};
|
|
14
14
|
export type VerifyOAuthStateResult = {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
// HMAC-
|
|
1
|
+
// HMAC-signed OAuth-`state` parameter for the connect flow.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// Binds {tenantId, ownerUserId?, providerKey, mailbox, nonce} to the
|
|
4
|
+
// redirect: the anonymous callback (outside /api/*) trusts only the
|
|
5
|
+
// verified state, preventing CSRF and cross-tenant or cross-user claiming
|
|
6
|
+
// because an attacker cannot redirect the callback to another tenant or
|
|
7
|
+
// user without breaking the signature.
|
|
8
8
|
//
|
|
9
9
|
// Format: <payload-base64url>.<expiresAtMs>.<hmac-base64url>
|
|
10
|
-
//
|
|
11
|
-
// HMAC
|
|
10
|
+
// Patterned after auth-email-password/signed-token.ts (HMAC-SHA256, purpose
|
|
11
|
+
// in the HMAC input, timing-safe comparison, expiry in the clear-text
|
|
12
|
+
// segment).
|
|
12
13
|
import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
13
14
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
14
15
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
@@ -40,8 +41,8 @@ export function verifyOAuthState(state, secret, now = Temporal.Now.instant()) {
|
|
|
40
41
|
const expected = sign(hmacInput(payloadB64, expiresAtMs), secret);
|
|
41
42
|
const expectedBuf = Buffer.from(expected, "base64url");
|
|
42
43
|
const providedBuf = Buffer.from(providedSig, "base64url");
|
|
43
|
-
//
|
|
44
|
-
//
|
|
44
|
+
// Check the length before timingSafeEqual: it throws on a length mismatch,
|
|
45
|
+
// and the throw itself leaks information through timing.
|
|
45
46
|
if (expectedBuf.length !== providedBuf.length)
|
|
46
47
|
return { ok: false, reason: "bad_signature" };
|
|
47
48
|
if (!timingSafeEqual(expectedBuf, providedBuf))
|
|
@@ -130,12 +130,12 @@ export declare const mailThreadsProjectionTable: import("@cosmicdrift/kumiko-fra
|
|
|
130
130
|
}, "tenant">>;
|
|
131
131
|
/** mail-account-connected → UPSERT full. */
|
|
132
132
|
export declare const applyMailAccountConnected: import("@cosmicdrift/kumiko-types/projection").SingleStreamApplyFn;
|
|
133
|
-
/** mail-account-updated → UPSERT
|
|
133
|
+
/** mail-account-updated → full UPSERT for status/watchState transitions. */
|
|
134
134
|
export declare const applyMailAccountUpdated: import("@cosmicdrift/kumiko-types/projection").SingleStreamApplyFn;
|
|
135
|
-
/** mail-account-disconnected → UPSERT
|
|
136
|
-
*
|
|
135
|
+
/** mail-account-disconnected → full UPSERT (payload.status=disconnected).
|
|
136
|
+
* The row and stream remain for audit visibility in the account list. */
|
|
137
137
|
export declare const applyMailAccountDisconnected: import("@cosmicdrift/kumiko-types/projection").SingleStreamApplyFn;
|
|
138
138
|
/** inbound-message-received → INSERT ... ON CONFLICT DO NOTHING. */
|
|
139
139
|
export declare const applyInboundMessageReceived: import("@cosmicdrift/kumiko-types/projection").SingleStreamApplyFn;
|
|
140
|
-
/** mail-thread-updated → UPSERT
|
|
140
|
+
/** mail-thread-updated → full UPSERT with the payload snapshot. */
|
|
141
141
|
export declare const applyMailThreadUpdated: import("@cosmicdrift/kumiko-types/projection").SingleStreamApplyFn;
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
// Inline
|
|
1
|
+
// Inline projections for the three event-sourced streams:
|
|
2
2
|
// mail-account → read_mail_accounts (UPSERT, current state)
|
|
3
3
|
// inbound-message → read_inbound_messages (INSERT-ignore, append-only)
|
|
4
|
-
// mail-thread → read_mail_threads (UPSERT,
|
|
4
|
+
// mail-thread → read_mail_threads (UPSERT, rollup)
|
|
5
5
|
//
|
|
6
|
-
// Apply
|
|
7
|
-
// own-write
|
|
6
|
+
// Apply runs in the same transaction as ctx.unsafeAppendEvent, providing
|
|
7
|
+
// read-your-own-write without waiting for a dispatcher tick (as in
|
|
8
|
+
// billing-foundation).
|
|
8
9
|
//
|
|
9
|
-
// **Production-deployment caveat** (
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
10
|
+
// **Production-deployment caveat** (same as billing-foundation):
|
|
11
|
+
// The tables are registered as raw drizzle-pgTable instances in r.projection,
|
|
12
|
+
// NOT as r.entity. Apps must include them in their drizzle/generate.ts
|
|
13
|
+
// (via *-ProjectionTable imports). setupTestStack pushes them automatically
|
|
14
|
+
// via r.projection.table.
|
|
14
15
|
//
|
|
15
|
-
// **PII:**
|
|
16
|
-
//
|
|
17
|
-
// write
|
|
18
|
-
// in
|
|
16
|
+
// **PII:** The payload fields (address/from/to/cc/subject/snippet) already
|
|
17
|
+
// arrive as ciphertext because they are encrypted BEFORE the append in the
|
|
18
|
+
// write handler. The applies only copy them through; decryption happens only
|
|
19
|
+
// in the list queries.
|
|
19
20
|
import { buildEntityTable, insertOnConflictDoNothing, requireEntityTableMeta, upsertOnConflict, } from "@cosmicdrift/kumiko-framework/db";
|
|
20
21
|
import { defineApply } from "@cosmicdrift/kumiko-framework/engine";
|
|
21
22
|
import { inboundMessageEntity, mailAccountEntity, mailThreadEntity } from "./entities.js";
|
|
22
|
-
// Drizzle
|
|
23
|
-
// projection
|
|
23
|
+
// Drizzle table instances derived from the entity shapes, shared between
|
|
24
|
+
// projection applies and list queries to provide one column namespace.
|
|
24
25
|
export const mailAccountsProjectionTable = buildEntityTable("mail-account", mailAccountEntity);
|
|
25
26
|
export const inboundMessagesProjectionTable = buildEntityTable("inbound-message", inboundMessageEntity);
|
|
26
27
|
export const mailThreadsProjectionTable = buildEntityTable("mail-thread", mailThreadEntity);
|
|
@@ -30,9 +31,10 @@ const mailAccountsProjectionMeta = requireEntityTableMeta(mailAccountsProjection
|
|
|
30
31
|
const inboundMessagesProjectionMeta = requireEntityTableMeta(inboundMessagesProjectionTable, "inbound-message");
|
|
31
32
|
const mailThreadsProjectionMeta = requireEntityTableMeta(mailThreadsProjectionTable, "mail-thread");
|
|
32
33
|
// =============================================================================
|
|
33
|
-
// mail-account — connected/updated/disconnected
|
|
34
|
-
//
|
|
35
|
-
// defensive consistency
|
|
34
|
+
// mail-account — connected/updated/disconnected share the payload shape;
|
|
35
|
+
// the event type identifies what happened. All three perform a full UPSERT
|
|
36
|
+
// for defensive consistency during from-scratch rebuilds and out-of-order
|
|
37
|
+
// processing.
|
|
36
38
|
// =============================================================================
|
|
37
39
|
const applyMailAccountUpsert = defineApply(async (event, tx) => {
|
|
38
40
|
const p = event.payload;
|
|
@@ -57,15 +59,15 @@ const applyMailAccountUpsert = defineApply(async (event, tx) => {
|
|
|
57
59
|
});
|
|
58
60
|
/** mail-account-connected → UPSERT full. */
|
|
59
61
|
export const applyMailAccountConnected = applyMailAccountUpsert;
|
|
60
|
-
/** mail-account-updated → UPSERT
|
|
62
|
+
/** mail-account-updated → full UPSERT for status/watchState transitions. */
|
|
61
63
|
export const applyMailAccountUpdated = applyMailAccountUpsert;
|
|
62
|
-
/** mail-account-disconnected → UPSERT
|
|
63
|
-
*
|
|
64
|
+
/** mail-account-disconnected → full UPSERT (payload.status=disconnected).
|
|
65
|
+
* The row and stream remain for audit visibility in the account list. */
|
|
64
66
|
export const applyMailAccountDisconnected = applyMailAccountUpsert;
|
|
65
67
|
// =============================================================================
|
|
66
|
-
// inbound-message —
|
|
67
|
-
// aggregateId). INSERT-ignore
|
|
68
|
-
//
|
|
68
|
+
// inbound-message — exactly one received event per stream (deterministic
|
|
69
|
+
// aggregateId). INSERT-ignore makes replays no-ops on the primary key;
|
|
70
|
+
// there is no update case.
|
|
69
71
|
// =============================================================================
|
|
70
72
|
/** inbound-message-received → INSERT ... ON CONFLICT DO NOTHING. */
|
|
71
73
|
export const applyInboundMessageReceived = defineApply(async (event, tx) => {
|
|
@@ -88,12 +90,12 @@ export const applyInboundMessageReceived = defineApply(async (event, tx) => {
|
|
|
88
90
|
});
|
|
89
91
|
});
|
|
90
92
|
// =============================================================================
|
|
91
|
-
// mail-thread —
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
//
|
|
93
|
+
// mail-thread — rollup per (tenantId, threadKey). The write handler computes
|
|
94
|
+
// messageCount/lastMessageAt and appends the updated event with the NEW state.
|
|
95
|
+
// The apply performs a full UPSERT rather than incrementing, because
|
|
96
|
+
// replays would otherwise not be idempotent.
|
|
95
97
|
// =============================================================================
|
|
96
|
-
/** mail-thread-updated → UPSERT
|
|
98
|
+
/** mail-thread-updated → full UPSERT with the payload snapshot. */
|
|
97
99
|
export const applyMailThreadUpdated = defineApply(async (event, tx) => {
|
|
98
100
|
const p = event.payload;
|
|
99
101
|
const mutable = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type InboundMailContext, type InboundMailProviderPlugin, type MailAccountRecord } from "./types.ts";
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
2
|
+
/** Looks up a provider by key ("imap", "m365-graph", ...); used by OAuth
|
|
3
|
+
* connect routes before an account exists. */
|
|
4
4
|
export declare function resolveInboundProviderForKey(ctx: InboundMailContext, providerKey: string, handlerName?: string): InboundMailProviderPlugin;
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
5
|
+
/** Looks up the provider for a specific account; the standard path for poll jobs
|
|
6
|
+
* and the watch supervisor. */
|
|
7
7
|
export declare function resolveInboundProviderForAccount(ctx: InboundMailContext, account: MailAccountRecord, handlerName?: string): InboundMailProviderPlugin;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// Provider
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// per
|
|
5
|
-
//
|
|
1
|
+
// Provider factory — mirrors mail-foundation's createTransportForTenant, including
|
|
2
|
+
// the three error paths (missing registry, unregistered provider, invalid plugin
|
|
3
|
+
// shape). Unlike the outbound pattern, there is no per-tenant config selector:
|
|
4
|
+
// the provider is specified per MailAccount (`account.provider`), so a tenant can
|
|
5
|
+
// use multiple providers in parallel.
|
|
6
6
|
import { INBOUND_MAIL_FOUNDATION_FEATURE, INBOUND_MAIL_PROVIDER_EXTENSION } from "./constants.js";
|
|
7
7
|
import { isInboundMailProviderPlugin, } from "./types.js";
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
8
|
+
/** Looks up a provider by key ("imap", "m365-graph", ...); used by OAuth
|
|
9
|
+
* connect routes before an account exists. */
|
|
10
10
|
export function resolveInboundProviderForKey(ctx, providerKey, handlerName = "inbound-mail-foundation:provider-factory") {
|
|
11
11
|
if (!ctx.registry) {
|
|
12
12
|
throw new Error(`${handlerName}: ctx.registry is missing — required to look up registered inbound-mail provider plugins`);
|
|
@@ -24,8 +24,8 @@ export function resolveInboundProviderForKey(ctx, providerKey, handlerName = "in
|
|
|
24
24
|
}
|
|
25
25
|
return usage.options;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
27
|
+
/** Looks up the provider for a specific account; the standard path for poll jobs
|
|
28
|
+
* and the watch supervisor. */
|
|
29
29
|
export function resolveInboundProviderForAccount(ctx, account, handlerName = "inbound-mail-foundation:provider-factory") {
|
|
30
30
|
return resolveInboundProviderForKey(ctx, account.provider, handlerName);
|
|
31
31
|
}
|
|
@@ -7,12 +7,14 @@ export declare const SEEN_RETENTION_DAYS = 90;
|
|
|
7
7
|
export interface InboundRetentionArgs {
|
|
8
8
|
readonly db: DbRunner;
|
|
9
9
|
readonly tenantId: TenantId;
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Injects the current time so tests can pin it without a date mock (pattern from keep-for.ts).
|
|
12
|
+
*/
|
|
11
13
|
readonly now: Instant;
|
|
12
14
|
readonly messageRetentionDays?: number;
|
|
13
15
|
readonly seenRetentionDays?: number;
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
+
/** Deletes a file-storage body object by bodyRef key. Wired lazily by the job
|
|
17
|
+
* (createFileProviderForTenant); if absent, no body is deleted. */
|
|
16
18
|
readonly deleteBodyObject?: (bodyRef: string) => Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
export interface InboundRetentionReport {
|