@cosmicdrift/kumiko-bundled-features 0.392.2 → 0.394.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/dist/account-security/feature.d.ts +2 -0
- package/dist/account-security/feature.js +3 -1
- package/dist/audit/event-classification.js +1 -0
- package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/confirm-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/logout.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/reset-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/token-request-handler.d.ts +1 -1
- package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
- package/dist/auth-email-password/web/auth-client.d.ts +3 -7
- package/dist/auth-email-password/web/auth-client.js +3 -24
- package/dist/auth-email-password/web/auth-gate.d.ts +2 -4
- package/dist/auth-email-password/web/auth-redirect.d.ts +2 -2
- package/dist/auth-email-password/web/auth-redirect.js +3 -12
- package/dist/auth-email-password/web/index.d.ts +2 -1
- package/dist/auth-email-password/web/index.js +1 -0
- package/dist/auth-email-password/web/login-failure.d.ts +9 -0
- package/dist/auth-email-password/web/login-failure.js +32 -0
- package/dist/auth-email-password/web/login-url.d.ts +5 -0
- package/dist/auth-email-password/web/login-url.js +13 -0
- package/dist/auth-email-password/web/static-login.d.ts +42 -0
- package/dist/auth-email-password/web/static-login.js +122 -0
- package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-client.js +4 -43
- package/dist/billing-foundation/checkout-core.d.ts +2 -1
- package/dist/billing-foundation/checkout-core.js +2 -11
- package/dist/billing-foundation/events.d.ts +1 -0
- package/dist/billing-foundation/events.js +2 -0
- package/dist/billing-foundation/feature.js +1 -1
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +9 -2
- package/dist/billing-foundation/handlers/process-payment-event.write.d.ts +1 -0
- package/dist/billing-foundation/handlers/process-payment-event.write.js +2 -0
- package/dist/billing-foundation/index.d.ts +1 -1
- package/dist/billing-foundation/one-off-checkout-gate.d.ts +9 -0
- package/dist/billing-foundation/one-off-checkout-gate.js +30 -0
- package/dist/billing-foundation/one-off-customer.d.ts +6 -0
- package/dist/billing-foundation/one-off-customer.js +12 -0
- package/dist/billing-foundation/plan-catalog.js +1 -0
- package/dist/billing-foundation/types.d.ts +25 -0
- package/dist/billing-foundation/web/billing-plans-panel.js +1 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +7 -3
- package/dist/billing-foundation/web/plan-switch-recurring.d.ts +16 -0
- package/dist/billing-foundation/web/plan-switch-recurring.js +10 -0
- package/dist/billing-foundation/webhook-handler.js +1 -0
- package/dist/cap-overview/handlers/caps-usage.query.js +3 -3
- package/dist/cap-overview/types.d.ts +2 -0
- package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
- package/dist/compliance-profiles/web/compliance-profile-catalog.js +8 -1
- package/dist/config/handlers/reset.write.d.ts +1 -1
- package/dist/config/handlers/set.write.d.ts +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
- package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
- package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
- package/dist/file-foundation/read-file-ref-content.d.ts +2 -0
- package/dist/file-foundation/read-file-ref-content.js +9 -3
- package/dist/form-draft/handlers/discard.write.d.ts +1 -1
- package/dist/form-draft/handlers/save.write.d.ts +1 -1
- package/dist/inbound-mail-foundation/account-health.d.ts +17 -0
- package/dist/inbound-mail-foundation/account-health.js +101 -0
- package/dist/inbound-mail-foundation/account-poll-schedule.d.ts +19 -0
- package/dist/inbound-mail-foundation/account-poll-schedule.js +44 -0
- package/dist/inbound-mail-foundation/account-poll.d.ts +24 -0
- package/dist/inbound-mail-foundation/account-poll.js +157 -0
- package/dist/inbound-mail-foundation/account-record.d.ts +1 -0
- package/dist/inbound-mail-foundation/account-record.js +1 -0
- package/dist/inbound-mail-foundation/account-wake.d.ts +3 -0
- package/dist/inbound-mail-foundation/account-wake.js +17 -0
- package/dist/inbound-mail-foundation/connect-callback-verify.d.ts +10 -0
- package/dist/inbound-mail-foundation/connect-callback-verify.js +31 -0
- package/dist/inbound-mail-foundation/connect-route-responses.d.ts +13 -0
- package/dist/inbound-mail-foundation/connect-route-responses.js +16 -0
- package/dist/inbound-mail-foundation/connect-routes.js +52 -33
- package/dist/inbound-mail-foundation/constants.d.ts +50 -2
- package/dist/inbound-mail-foundation/constants.js +53 -3
- package/dist/inbound-mail-foundation/content-refetch.d.ts +14 -0
- package/dist/inbound-mail-foundation/content-refetch.js +93 -0
- package/dist/inbound-mail-foundation/describe-error.d.ts +1 -0
- package/dist/inbound-mail-foundation/describe-error.js +5 -0
- package/dist/inbound-mail-foundation/entities.d.ts +26 -0
- package/dist/inbound-mail-foundation/entities.js +43 -3
- package/dist/inbound-mail-foundation/events.d.ts +97 -0
- package/dist/inbound-mail-foundation/events.js +57 -2
- package/dist/inbound-mail-foundation/feature.d.ts +5 -2
- package/dist/inbound-mail-foundation/feature.js +122 -106
- package/dist/inbound-mail-foundation/file-storage-failure.d.ts +8 -0
- package/dist/inbound-mail-foundation/file-storage-failure.js +19 -0
- package/dist/inbound-mail-foundation/handlers/account-address.d.ts +16 -0
- package/dist/inbound-mail-foundation/handlers/account-address.js +51 -0
- package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.js +39 -0
- package/dist/inbound-mail-foundation/handlers/attach-message-content.write.d.ts +60 -0
- package/dist/inbound-mail-foundation/handlers/attach-message-content.write.js +128 -0
- package/dist/inbound-mail-foundation/handlers/connect-account.write.d.ts +3 -2
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +97 -56
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +55 -42
- package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.d.ts +26 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.js +131 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-schema.d.ts +64 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-schema.js +39 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.d.ts +74 -21
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +57 -134
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +60 -26
- package/dist/inbound-mail-foundation/handlers/list-messages.query.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +43 -29
- package/dist/inbound-mail-foundation/handlers/list-quarantine.query.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/list-quarantine.query.js +75 -0
- package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.d.ts +7 -0
- package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.js +38 -0
- package/dist/inbound-mail-foundation/handlers/message-content.d.ts +70 -0
- package/dist/inbound-mail-foundation/handlers/message-content.js +137 -0
- package/dist/inbound-mail-foundation/handlers/message-content.query.d.ts +19 -0
- package/dist/inbound-mail-foundation/handlers/message-content.query.js +59 -0
- package/dist/inbound-mail-foundation/handlers/message-detail.query.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/message-detail.query.js +23 -0
- package/dist/inbound-mail-foundation/handlers/reactivate-account.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/reactivate-account.write.js +84 -0
- package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.js +34 -0
- package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +10 -2
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +27 -8
- package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.d.ts +13 -0
- package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.js +54 -0
- package/dist/inbound-mail-foundation/handlers/thread-rollup.d.ts +24 -0
- package/dist/inbound-mail-foundation/handlers/thread-rollup.js +98 -0
- package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.js +3 -0
- package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +13 -3
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +62 -46
- package/dist/inbound-mail-foundation/i18n.js +72 -2
- package/dist/inbound-mail-foundation/inbound-oauth-flow.d.ts +43 -0
- package/dist/inbound-mail-foundation/inbound-oauth-flow.js +1 -0
- package/dist/inbound-mail-foundation/index.d.ts +19 -6
- package/dist/inbound-mail-foundation/index.js +17 -6
- package/dist/inbound-mail-foundation/ingest-failures.d.ts +77 -0
- package/dist/inbound-mail-foundation/ingest-failures.js +79 -0
- package/dist/inbound-mail-foundation/ingest-payload.d.ts +7 -0
- package/dist/inbound-mail-foundation/ingest-payload.js +34 -0
- package/dist/inbound-mail-foundation/mail-roles.d.ts +21 -0
- package/dist/inbound-mail-foundation/mail-roles.js +83 -0
- package/dist/inbound-mail-foundation/normalize-inbound-message.d.ts +17 -0
- package/dist/inbound-mail-foundation/normalize-inbound-message.js +90 -0
- package/dist/inbound-mail-foundation/oauth-access-token.d.ts +3 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +13 -2
- package/dist/inbound-mail-foundation/outbound-attachment-access.d.ts +5 -0
- package/dist/inbound-mail-foundation/outbound-attachment-access.js +16 -0
- package/dist/inbound-mail-foundation/outbound-attachments.d.ts +18 -0
- package/dist/inbound-mail-foundation/outbound-attachments.js +77 -0
- package/dist/inbound-mail-foundation/outbound-mail.d.ts +15 -1
- package/dist/inbound-mail-foundation/outbound-mail.js +4 -0
- package/dist/inbound-mail-foundation/probe.js +1 -1
- package/dist/inbound-mail-foundation/projection.d.ts +28 -0
- package/dist/inbound-mail-foundation/projection.js +25 -3
- package/dist/inbound-mail-foundation/provider-errors.d.ts +28 -0
- package/dist/inbound-mail-foundation/provider-errors.js +66 -0
- package/dist/inbound-mail-foundation/quarantine-entities.d.ts +61 -0
- package/dist/inbound-mail-foundation/quarantine-entities.js +47 -0
- package/dist/inbound-mail-foundation/quarantine-header-import.d.ts +9 -0
- package/dist/inbound-mail-foundation/quarantine-header-import.js +53 -0
- package/dist/inbound-mail-foundation/quarantine-retry.d.ts +13 -0
- package/dist/inbound-mail-foundation/quarantine-retry.js +97 -0
- package/dist/inbound-mail-foundation/quarantine-screens.d.ts +4 -0
- package/dist/inbound-mail-foundation/quarantine-screens.js +57 -0
- package/dist/inbound-mail-foundation/quarantine.d.ts +13 -0
- package/dist/inbound-mail-foundation/quarantine.js +46 -0
- package/dist/inbound-mail-foundation/retention-job.d.ts +2 -0
- package/dist/inbound-mail-foundation/retention-job.js +62 -0
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +4 -0
- package/dist/inbound-mail-foundation/retention-sweep.js +35 -8
- package/dist/inbound-mail-foundation/screens.d.ts +14 -2
- package/dist/inbound-mail-foundation/screens.js +217 -79
- package/dist/inbound-mail-foundation/send-from-account.d.ts +11 -1
- package/dist/inbound-mail-foundation/send-from-account.js +19 -2
- package/dist/inbound-mail-foundation/sender-auth.d.ts +63 -0
- package/dist/inbound-mail-foundation/sender-auth.js +198 -0
- package/dist/inbound-mail-foundation/supervisor-ingest.d.ts +43 -0
- package/dist/inbound-mail-foundation/supervisor-ingest.js +195 -0
- package/dist/inbound-mail-foundation/sync-account-now.d.ts +22 -0
- package/dist/inbound-mail-foundation/sync-account-now.js +29 -0
- package/dist/inbound-mail-foundation/sync-cursor-store.d.ts +9 -0
- package/dist/inbound-mail-foundation/sync-cursor-store.js +54 -0
- package/dist/inbound-mail-foundation/syncable-accounts.d.ts +16 -0
- package/dist/inbound-mail-foundation/syncable-accounts.js +79 -0
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +5 -1
- package/dist/inbound-mail-foundation/types.d.ts +61 -62
- package/dist/inbound-mail-foundation/types.js +0 -54
- package/dist/inbound-mail-foundation/wake-consumer.d.ts +2 -0
- package/dist/inbound-mail-foundation/wake-consumer.js +30 -0
- package/dist/inbound-mail-foundation/watch-catch-up.d.ts +19 -0
- package/dist/inbound-mail-foundation/watch-catch-up.js +33 -0
- package/dist/inbound-mail-foundation/watch-lease.d.ts +15 -0
- package/dist/inbound-mail-foundation/watch-lease.js +81 -0
- package/dist/inbound-mail-foundation/watch-supervisor-types.d.ts +83 -0
- package/dist/inbound-mail-foundation/watch-supervisor-types.js +1 -0
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +1 -53
- package/dist/inbound-mail-foundation/watch-supervisor.js +123 -290
- package/dist/inbound-mail-foundation/web/client-plugin.d.ts +14 -0
- package/dist/inbound-mail-foundation/web/client-plugin.js +40 -0
- package/dist/inbound-mail-foundation/web/constants.d.ts +5 -0
- package/dist/inbound-mail-foundation/web/constants.js +6 -0
- package/dist/inbound-mail-foundation/web/index.d.ts +1 -0
- package/dist/inbound-mail-foundation/web/index.js +1 -0
- package/dist/inbound-provider-imap/connect-mailbox.d.ts +28 -5
- package/dist/inbound-provider-imap/connect-mailbox.js +91 -41
- package/dist/inbound-provider-imap/connect-my-mailbox.d.ts +13 -0
- package/dist/inbound-provider-imap/connect-my-mailbox.js +25 -0
- package/dist/inbound-provider-imap/constants.d.ts +12 -1
- package/dist/inbound-provider-imap/constants.js +12 -1
- package/dist/inbound-provider-imap/credential-document.js +2 -2
- package/dist/inbound-provider-imap/download-batch.d.ts +6 -0
- package/dist/inbound-provider-imap/download-batch.js +24 -0
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +49 -32
- package/dist/inbound-provider-imap/fetch-content.d.ts +4 -0
- package/dist/inbound-provider-imap/fetch-content.js +68 -0
- package/dist/inbound-provider-imap/i18n.js +18 -2
- package/dist/inbound-provider-imap/imap-client.d.ts +27 -23
- package/dist/inbound-provider-imap/imap-client.js +30 -68
- package/dist/inbound-provider-imap/index.d.ts +2 -1
- package/dist/inbound-provider-imap/index.js +2 -1
- package/dist/inbound-provider-imap/mime-content.d.ts +11 -0
- package/dist/inbound-provider-imap/mime-content.js +66 -0
- package/dist/inbound-provider-imap/parse-message.d.ts +35 -0
- package/dist/inbound-provider-imap/parse-message.js +113 -0
- package/dist/inbound-provider-imap/reconnect-account.d.ts +17 -0
- package/dist/inbound-provider-imap/reconnect-account.js +18 -0
- package/dist/inbound-provider-imap/reconnect-mailbox.d.ts +14 -0
- package/dist/inbound-provider-imap/reconnect-mailbox.js +71 -0
- package/dist/inbound-provider-imap/reconnect-prefill.query.d.ts +3 -0
- package/dist/inbound-provider-imap/reconnect-prefill.query.js +34 -0
- package/dist/inbound-provider-imap/screens.d.ts +6 -1
- package/dist/inbound-provider-imap/screens.js +174 -41
- package/dist/inbound-provider-imap/send-mail.d.ts +2 -2
- package/dist/inbound-provider-imap/send-mail.js +8 -1
- package/dist/inbound-provider-imap/sender-auth-headers.d.ts +3 -0
- package/dist/inbound-provider-imap/sender-auth-headers.js +18 -0
- package/dist/inbound-provider-inmemory/feature.d.ts +15 -0
- package/dist/inbound-provider-inmemory/feature.js +57 -2
- package/dist/inbound-provider-inmemory/index.d.ts +1 -1
- package/dist/inbound-provider-inmemory/index.js +1 -1
- package/dist/jobs/handlers/consumer.write.d.ts +4 -4
- package/dist/jobs/handlers/retry.write.d.ts +1 -1
- package/dist/jobs/handlers/trigger.write.d.ts +1 -1
- package/dist/managed-pages/handlers/set.write.d.ts +1 -1
- package/dist/managed-pages/web/i18n.js +1 -0
- package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
- package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
- package/dist/readiness/handlers/run-probes.write.d.ts +1 -1
- package/dist/secrets/handlers/delete.write.d.ts +1 -1
- package/dist/secrets/handlers/set.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke.write.d.ts +1 -1
- package/dist/subscription-paddle/checkout-config.query.d.ts +3 -0
- package/dist/subscription-paddle/checkout-config.query.js +14 -0
- package/dist/subscription-paddle/checkout-methods.d.ts +6 -0
- package/dist/subscription-paddle/checkout-methods.js +85 -0
- package/dist/subscription-paddle/checkout-page.d.ts +19 -0
- package/dist/subscription-paddle/checkout-page.js +126 -0
- package/dist/subscription-paddle/client.d.ts +24 -0
- package/dist/subscription-paddle/client.js +60 -0
- package/dist/subscription-paddle/constants.d.ts +16 -0
- package/dist/subscription-paddle/constants.js +25 -0
- package/dist/subscription-paddle/feature.d.ts +49 -0
- package/dist/subscription-paddle/feature.js +192 -0
- package/dist/subscription-paddle/index.d.ts +2 -0
- package/dist/subscription-paddle/index.js +4 -0
- package/dist/subscription-paddle/plan-switch-methods.d.ts +6 -0
- package/dist/subscription-paddle/plan-switch-methods.js +114 -0
- package/dist/subscription-paddle/price-methods.d.ts +15 -0
- package/dist/subscription-paddle/price-methods.js +105 -0
- package/dist/subscription-paddle/runtime.d.ts +42 -0
- package/dist/subscription-paddle/runtime.js +109 -0
- package/dist/subscription-paddle/subscription-state.d.ts +34 -0
- package/dist/subscription-paddle/subscription-state.js +48 -0
- package/dist/subscription-paddle/tenant-binding.d.ts +8 -0
- package/dist/subscription-paddle/tenant-binding.js +26 -0
- package/dist/subscription-paddle/verify-webhook.d.ts +4 -0
- package/dist/subscription-paddle/verify-webhook.js +55 -0
- package/dist/subscription-paddle/webhook-events.d.ts +9 -0
- package/dist/subscription-paddle/webhook-events.js +124 -0
- package/dist/template-resolver/handlers/collection-item.query.js +2 -2
- package/dist/template-resolver/handlers/collection-list.query.js +4 -2
- package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-shared.d.ts +11 -0
- package/dist/template-resolver/handlers/collection-shared.js +16 -0
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +1 -1
- package/dist/template-resolver/handlers/discard-draft.write.d.ts +2 -2
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +1 -1
- package/dist/template-resolver/handlers/patch-draft.write.d.ts +1 -1
- package/dist/template-resolver/handlers/reset-to-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-remove.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +1 -1
- package/dist/template-resolver/handlers/send-test.write.d.ts +1 -1
- package/dist/template-resolver/handlers/set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +4 -4
- package/dist/template-resolver/handlers/upsert-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +1 -1
- package/dist/template-resolver/web/client-plugin.d.ts +4 -0
- package/dist/template-resolver/web/client-plugin.js +134 -52
- package/dist/template-resolver/web/i18n.js +1 -1
- package/dist/tenant/handlers/add-member.write.d.ts +1 -1
- package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
- package/dist/tenant/handlers/create.write.d.ts +1 -1
- package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
- package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
- package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
- package/dist/tenant/handlers/update.write.d.ts +1 -1
- package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
- package/dist/user/handlers/create.write.d.ts +1 -1
- package/dist/user/handlers/update.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +2 -1
- package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
- package/dist/waitlist/handlers/export-purge.write.d.ts +2 -2
- package/dist/waitlist/handlers/invite.write.d.ts +1 -1
- package/dist/waitlist/handlers/reject.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.d.ts +1 -1
- package/package.json +33 -17
- package/src/account-security/changes.json +6 -0
- package/src/auth-email-password/changes.json +6 -0
- package/src/billing-foundation/changes.json +30 -0
- package/src/cap-overview/changes.json +6 -0
- package/src/files/changes.json +18 -0
- package/src/inbound-mail-foundation/changes.json +155 -0
- package/src/inbound-provider-imap/changes.json +42 -0
- package/src/jobs/changes.json +18 -0
- package/src/subscription-paddle/changes.json +15 -0
- package/src/template-resolver/changes.json +12 -0
- package/dist/subscription-dodo/client.d.ts +0 -17
- package/dist/subscription-dodo/client.js +0 -31
- package/dist/subscription-dodo/constants.d.ts +0 -12
- package/dist/subscription-dodo/constants.js +0 -19
- package/dist/subscription-dodo/feature.d.ts +0 -37
- package/dist/subscription-dodo/feature.js +0 -144
- package/dist/subscription-dodo/index.d.ts +0 -2
- package/dist/subscription-dodo/index.js +0 -4
- package/dist/subscription-dodo/plugin-methods.d.ts +0 -23
- package/dist/subscription-dodo/plugin-methods.js +0 -260
- package/dist/subscription-dodo/runtime.d.ts +0 -27
- package/dist/subscription-dodo/runtime.js +0 -89
- package/dist/subscription-dodo/verify-webhook.d.ts +0 -37
- package/dist/subscription-dodo/verify-webhook.js +0 -189
- package/src/subscription-dodo/changes.json +0 -14
|
@@ -9,29 +9,41 @@
|
|
|
9
9
|
// Providers register no routes of their own — their oauth block is
|
|
10
10
|
// resolved via resolveInboundProviderForKey. The callback trusts ONLY the
|
|
11
11
|
// HMAC-verified state (CSRF-/foreign-claiming lock, see oauth-state.ts).
|
|
12
|
-
import {
|
|
12
|
+
import { signatureRoute } from "@cosmicdrift/kumiko-framework/api";
|
|
13
13
|
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
14
|
+
import { refreshTokenOrRefusal, verifyCallbackRequest, } from "./connect-callback-verify.js";
|
|
15
|
+
import { connectFailureResponse, errorJson } from "./connect-route-responses.js";
|
|
16
|
+
import { INBOUND_MAIL_CONNECT_PATH, INBOUND_MAIL_FOUNDATION_FEATURE, InboundMailAuthMethods, InboundMailFoundationHandlers, } from "./constants.js";
|
|
17
|
+
import { isMailAdmin } from "./handlers/scope-visibility.js";
|
|
18
|
+
import { readInboundMailRoles } from "./mail-roles.js";
|
|
19
|
+
import { storeOAuthCallbackCredential, } from "./oauth-access-token.js";
|
|
20
|
+
import { signOAuthState } from "./oauth-state.js";
|
|
17
21
|
import { resolveInboundProviderForKey } from "./provider-factory.js";
|
|
18
22
|
const DEFAULT_STATE_TTL_MINUTES = 15;
|
|
19
|
-
const DEFAULT_CONNECT_PATH = "/api/inbound-mail/connect";
|
|
20
23
|
const DEFAULT_CALLBACK_PATH = "/inbound-mail/oauth/callback";
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
// connect-account leaves a reopened mailbox off: switched on before its token is stored, the
|
|
25
|
+
// supervisor would sync it with the old, failing credential.
|
|
26
|
+
async function reactivateIfReopened(c, deps, tenantId, accountId, connected) {
|
|
27
|
+
if (propertyOf(connected, "reconnected") !== true)
|
|
28
|
+
return undefined;
|
|
29
|
+
const reactivated = await deps.dispatchSystemWrite({
|
|
30
|
+
handlerQn: InboundMailFoundationHandlers.reactivateAccount,
|
|
31
|
+
tenantId,
|
|
32
|
+
payload: { accountId },
|
|
33
|
+
});
|
|
34
|
+
return reactivated.isSuccess ? undefined : connectFailureResponse(c, reactivated.error);
|
|
23
35
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
// The callback connects as a system user, so connect-account's role rules (mail member at all,
|
|
37
|
+
// admin for a shared mailbox) have to hold here, before the signed state is handed out.
|
|
38
|
+
function connectRoleRefusal(c, deps, scope) {
|
|
39
|
+
const { memberRoles, adminRoles } = readInboundMailRoles(deps.registry);
|
|
40
|
+
if (!memberRoles.some((role) => deps.user.roles.includes(role))) {
|
|
41
|
+
return errorJson(c, 403, "mail_role_required", `${INBOUND_MAIL_FOUNDATION_FEATURE}: connecting a mailbox needs one of the roles ${memberRoles.join(", ")}`);
|
|
29
42
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
throw new ExtraRouteRejection(400, { error: { code: "invalid_state", message: `state rejected: ${verified.reason}` } }, `inbound-mail oauth callback state rejected: ${verified.reason}`);
|
|
43
|
+
if (scope === "shared" && !isMailAdmin(deps.user, adminRoles)) {
|
|
44
|
+
return errorJson(c, 403, "shared_mailbox_requires_admin", `${INBOUND_MAIL_FOUNDATION_FEATURE}: only ${adminRoles.join(", ")} connect a shared mailbox`);
|
|
33
45
|
}
|
|
34
|
-
return
|
|
46
|
+
return undefined;
|
|
35
47
|
}
|
|
36
48
|
/** Builds the `entry:"user"`/`entry:"signature"` extraRoute pair. Mount via
|
|
37
49
|
* `extraRoutes: createInboundMailConnectRoutes(options)`. */
|
|
@@ -39,7 +51,7 @@ export function createInboundMailConnectRoutes(options) {
|
|
|
39
51
|
const ttl = options.stateTtlMinutes ?? DEFAULT_STATE_TTL_MINUTES;
|
|
40
52
|
const connectRoute = {
|
|
41
53
|
method: "GET",
|
|
42
|
-
path: options.connectPath ??
|
|
54
|
+
path: options.connectPath ?? INBOUND_MAIL_CONNECT_PATH,
|
|
43
55
|
entry: "user",
|
|
44
56
|
handler: async (c, deps) => {
|
|
45
57
|
const providerKey = c.req.query("provider") ?? "";
|
|
@@ -48,6 +60,9 @@ export function createInboundMailConnectRoutes(options) {
|
|
|
48
60
|
if (!providerKey || (scope !== "user" && scope !== "shared") || !mailbox) {
|
|
49
61
|
return errorJson(c, 400, "invalid_connect_request", `${INBOUND_MAIL_FOUNDATION_FEATURE}: expected ?provider=<key>&scope=user|shared&mailbox=<address>`);
|
|
50
62
|
}
|
|
63
|
+
const refused = connectRoleRefusal(c, deps, scope);
|
|
64
|
+
if (refused)
|
|
65
|
+
return refused;
|
|
51
66
|
let plugin;
|
|
52
67
|
try {
|
|
53
68
|
plugin = resolveInboundProviderForKey({ registry: deps.registry }, providerKey);
|
|
@@ -108,12 +123,9 @@ export function createInboundMailConnectRoutes(options) {
|
|
|
108
123
|
// Provider error messages can carry token/response data — code only.
|
|
109
124
|
return errorJson(c, 502, "token_exchange_failed", "token exchange with the provider failed");
|
|
110
125
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// oauth block owns the scopes.
|
|
115
|
-
return errorJson(c, 502, "no_refresh_token", `provider "${state.providerKey}" returned no refresh token — check the offline-access scope in the provider's oauth.scopes`);
|
|
116
|
-
}
|
|
126
|
+
const refreshToken = refreshTokenOrRefusal(c, state, tokens);
|
|
127
|
+
if (typeof refreshToken !== "string")
|
|
128
|
+
return refreshToken;
|
|
117
129
|
// Account creation (programmatic SystemUser; the real owner comes from
|
|
118
130
|
// the HMAC-verified state → ownerUserIdOverride).
|
|
119
131
|
const dispatched = await deps.dispatchSystemWrite({
|
|
@@ -129,22 +141,29 @@ export function createInboundMailConnectRoutes(options) {
|
|
|
129
141
|
},
|
|
130
142
|
});
|
|
131
143
|
if (!dispatched.isSuccess) {
|
|
132
|
-
return
|
|
144
|
+
return connectFailureResponse(c, dispatched.error);
|
|
133
145
|
}
|
|
134
146
|
const accountId = propertyOf(dispatched.data, "accountId");
|
|
135
147
|
if (typeof accountId !== "string") {
|
|
136
148
|
return errorJson(c, 502, "account_create_failed", "connect-account returned no accountId");
|
|
137
149
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// them from the refresh token (oauth-access-token.ts).
|
|
141
|
-
if (options.oauthTokens) {
|
|
142
|
-
await options.oauthTokens.storeRefreshToken({ id: accountId, tenantId: state.tenantId }, tokens.refreshToken);
|
|
143
|
-
options.oauthTokens.primeFromExchange({ id: accountId }, tokens);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
await deps.secrets.set(state.tenantId, inboundCredentialSecretKey(accountId), tokens.refreshToken, inboundRefreshTokenSecretOptions(accountId));
|
|
150
|
+
try {
|
|
151
|
+
await storeOAuthCallbackCredential(options.oauthTokens, deps.secrets, { id: accountId, tenantId: state.tenantId }, tokens, refreshToken);
|
|
147
152
|
}
|
|
153
|
+
catch {
|
|
154
|
+
return errorJson(c, 502, "credential_store_failed", "the sign-in worked but its token could not be saved; the mailbox keeps its previous state, connect it again");
|
|
155
|
+
}
|
|
156
|
+
const refused = await reactivateIfReopened(c, deps, state.tenantId, accountId, dispatched.data);
|
|
157
|
+
if (refused)
|
|
158
|
+
return refused;
|
|
159
|
+
// Best effort: the account commit already woke the supervisor before the token existed.
|
|
160
|
+
// Without this event the first sync would wait for the next poll tick; a failure here
|
|
161
|
+
// only costs that delay, so the connect itself still succeeds.
|
|
162
|
+
await deps.dispatchSystemWrite({
|
|
163
|
+
handlerQn: InboundMailFoundationHandlers.markCredentialStored,
|
|
164
|
+
tenantId: state.tenantId,
|
|
165
|
+
payload: { accountId },
|
|
166
|
+
});
|
|
148
167
|
if (options.successRedirectUrl) {
|
|
149
168
|
const target = new URL(options.successRedirectUrl);
|
|
150
169
|
target.searchParams.set("accountId", accountId);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { INBOUND_MAIL_CONNECT_PATH, INBOUND_MAIL_FOUNDATION_FEATURE, INBOUND_MAIL_RECONNECT_OAUTH_ACTION, } from "./web/constants.ts";
|
|
2
2
|
export declare const INBOUND_MAIL_PROVIDER_EXTENSION: "inboundMailProvider";
|
|
3
3
|
export declare const InboundMailFoundationHandlers: {
|
|
4
4
|
/** Programmatic entry point for provider plugins (watch callback +
|
|
@@ -14,6 +14,18 @@ export declare const InboundMailFoundationHandlers: {
|
|
|
14
14
|
/** Tenant admin disconnects a mailbox. The stream remains for auditing;
|
|
15
15
|
* the status becomes disconnected and the watch stops. */
|
|
16
16
|
readonly disconnectAccount: "inbound-mail-foundation:write:disconnect-account";
|
|
17
|
+
/** The only way from disconnected back to active; also clears auth_error
|
|
18
|
+
* and degraded. update-account keeps rejecting disconnected accounts. */
|
|
19
|
+
readonly reactivateAccount: "inbound-mail-foundation:write:reactivate-account";
|
|
20
|
+
readonly setTrustedAuthservId: "inbound-mail-foundation:write:set-trusted-authserv-id";
|
|
21
|
+
/** Owner or admin asks for one quarantined mail to be loaded again on the next sync. */
|
|
22
|
+
readonly retryQuarantinedMessage: "inbound-mail-foundation:write:retry-quarantined-message";
|
|
23
|
+
/** Marks all open quarantine entries of a mailbox as acknowledged. */
|
|
24
|
+
readonly acknowledgeQuarantine: "inbound-mail-foundation:write:acknowledge-quarantine";
|
|
25
|
+
/** Supervisor-only: stores the content of an already imported snippet mail. */
|
|
26
|
+
readonly attachMessageContent: "inbound-mail-foundation:write:attach-message-content";
|
|
27
|
+
/** OAuth callback only: the refresh token is stored now, so an active account can sync. */
|
|
28
|
+
readonly markCredentialStored: "inbound-mail-foundation:write:mark-credential-stored";
|
|
17
29
|
};
|
|
18
30
|
export declare const InboundMailFoundationQueries: {
|
|
19
31
|
/** Tenant-scoped list of connected mailboxes. */
|
|
@@ -21,18 +33,45 @@ export declare const InboundMailFoundationQueries: {
|
|
|
21
33
|
/** Tenant-scoped message list (inbox cockpit). PII is decrypted on read.
|
|
22
34
|
*/
|
|
23
35
|
readonly listMessages: "inbound-mail-foundation:query:message:list";
|
|
36
|
+
/** Open quarantine entries of the mailboxes the caller may manage, with sender and subject from the header import. */
|
|
37
|
+
readonly listQuarantine: "inbound-mail-foundation:query:quarantine:list";
|
|
38
|
+
/** Decrypted full text, attachment ids and content state of one message. */
|
|
39
|
+
readonly messageContent: "inbound-mail-foundation:query:message:content";
|
|
24
40
|
};
|
|
25
41
|
export declare const InboundMailAccountStatuses: {
|
|
26
42
|
/** Connected; watch/sync is running or ready to start. */
|
|
27
43
|
readonly active: "active";
|
|
28
44
|
/** Credentials or token are invalid; the tenant admin must reconnect. */
|
|
29
45
|
readonly authError: "auth_error";
|
|
30
|
-
/**
|
|
46
|
+
/** Interrupted: transient failure, quarantined mail, missing file storage or KMS; see lastError. */
|
|
31
47
|
readonly degraded: "degraded";
|
|
32
48
|
/** Disconnected by the tenant admin; no further syncs run. */
|
|
33
49
|
readonly disconnected: "disconnected";
|
|
34
50
|
};
|
|
35
51
|
export type InboundMailAccountStatus = (typeof InboundMailAccountStatuses)[keyof typeof InboundMailAccountStatuses];
|
|
52
|
+
export declare const InboundMailLastErrors: {
|
|
53
|
+
readonly connectionFailed: "connection_failed";
|
|
54
|
+
readonly rateLimited: "rate_limited";
|
|
55
|
+
readonly messageQuarantined: "message_quarantined";
|
|
56
|
+
readonly fileStorageUnavailable: "file_storage_unavailable";
|
|
57
|
+
readonly encryptionUnavailable: "encryption_unavailable";
|
|
58
|
+
readonly ingestUnavailable: "ingest_unavailable";
|
|
59
|
+
};
|
|
60
|
+
export type InboundMailLastError = (typeof InboundMailLastErrors)[keyof typeof InboundMailLastErrors];
|
|
61
|
+
export declare const InboundMailConnectErrors: {
|
|
62
|
+
readonly addressAlreadyConnected: {
|
|
63
|
+
readonly reason: "address_already_connected";
|
|
64
|
+
readonly i18nKey: "inboundMail.accounts.errors.addressAlreadyConnected";
|
|
65
|
+
};
|
|
66
|
+
readonly addressDisconnected: {
|
|
67
|
+
readonly reason: "address_disconnected";
|
|
68
|
+
readonly i18nKey: "inboundMail.accounts.errors.addressDisconnected";
|
|
69
|
+
};
|
|
70
|
+
readonly credentialRequired: {
|
|
71
|
+
readonly reason: "credential_required";
|
|
72
|
+
readonly i18nKey: "inboundMail.accounts.errors.credentialRequired";
|
|
73
|
+
};
|
|
74
|
+
};
|
|
36
75
|
/**
|
|
37
76
|
* Tenant secret slot for an account: IMAP app password OR OAuth refresh
|
|
38
77
|
* token. The provider interprets the contents according to `authMethod`.
|
|
@@ -51,3 +90,12 @@ export declare const InboundMailAuthMethods: {
|
|
|
51
90
|
readonly oauth: "oauth";
|
|
52
91
|
};
|
|
53
92
|
export type InboundMailAuthMethod = (typeof InboundMailAuthMethods)[keyof typeof InboundMailAuthMethods];
|
|
93
|
+
/** Provider key of inbound-provider-imap: only its password mailboxes have a credential form. */
|
|
94
|
+
export declare const IMAP_PROVIDER_KEY = "imap";
|
|
95
|
+
export declare const MailAccountReactivationPaths: {
|
|
96
|
+
/** The IMAP form of inbound-provider-imap (reconnect-mailbox). */
|
|
97
|
+
readonly passwordForm: "password_form";
|
|
98
|
+
/** The provider's OAuth sign-in through the connect route; its callback reopens the account. */
|
|
99
|
+
readonly oauthFlow: "oauth_flow";
|
|
100
|
+
};
|
|
101
|
+
export type MailAccountReactivationPath = (typeof MailAccountReactivationPaths)[keyof typeof MailAccountReactivationPaths];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { INBOUND_MAIL_FOUNDATION_FEATURE } from "./web/constants.js";
|
|
2
|
+
export { INBOUND_MAIL_CONNECT_PATH, INBOUND_MAIL_FOUNDATION_FEATURE, INBOUND_MAIL_RECONNECT_OAUTH_ACTION, } from "./web/constants.js";
|
|
3
3
|
// Extension-point name for provider plugins (inbound-provider-imap,
|
|
4
4
|
// inbound-provider-m365-graph, inbound-provider-gmail-rest, ...).
|
|
5
5
|
export const INBOUND_MAIL_PROVIDER_EXTENSION = "inboundMailProvider";
|
|
@@ -18,6 +18,18 @@ export const InboundMailFoundationHandlers = {
|
|
|
18
18
|
/** Tenant admin disconnects a mailbox. The stream remains for auditing;
|
|
19
19
|
* the status becomes disconnected and the watch stops. */
|
|
20
20
|
disconnectAccount: "inbound-mail-foundation:write:disconnect-account",
|
|
21
|
+
/** The only way from disconnected back to active; also clears auth_error
|
|
22
|
+
* and degraded. update-account keeps rejecting disconnected accounts. */
|
|
23
|
+
reactivateAccount: "inbound-mail-foundation:write:reactivate-account",
|
|
24
|
+
setTrustedAuthservId: "inbound-mail-foundation:write:set-trusted-authserv-id",
|
|
25
|
+
/** Owner or admin asks for one quarantined mail to be loaded again on the next sync. */
|
|
26
|
+
retryQuarantinedMessage: "inbound-mail-foundation:write:retry-quarantined-message",
|
|
27
|
+
/** Marks all open quarantine entries of a mailbox as acknowledged. */
|
|
28
|
+
acknowledgeQuarantine: "inbound-mail-foundation:write:acknowledge-quarantine",
|
|
29
|
+
/** Supervisor-only: stores the content of an already imported snippet mail. */
|
|
30
|
+
attachMessageContent: "inbound-mail-foundation:write:attach-message-content",
|
|
31
|
+
/** OAuth callback only: the refresh token is stored now, so an active account can sync. */
|
|
32
|
+
markCredentialStored: "inbound-mail-foundation:write:mark-credential-stored",
|
|
21
33
|
};
|
|
22
34
|
// Qualified query handler names.
|
|
23
35
|
export const InboundMailFoundationQueries = {
|
|
@@ -26,6 +38,10 @@ export const InboundMailFoundationQueries = {
|
|
|
26
38
|
/** Tenant-scoped message list (inbox cockpit). PII is decrypted on read.
|
|
27
39
|
*/
|
|
28
40
|
listMessages: "inbound-mail-foundation:query:message:list",
|
|
41
|
+
/** Open quarantine entries of the mailboxes the caller may manage, with sender and subject from the header import. */
|
|
42
|
+
listQuarantine: "inbound-mail-foundation:query:quarantine:list",
|
|
43
|
+
/** Decrypted full text, attachment ids and content state of one message. */
|
|
44
|
+
messageContent: "inbound-mail-foundation:query:message:content",
|
|
29
45
|
};
|
|
30
46
|
// Normalized account status values — provider-agnostic.
|
|
31
47
|
export const InboundMailAccountStatuses = {
|
|
@@ -33,11 +49,35 @@ export const InboundMailAccountStatuses = {
|
|
|
33
49
|
active: "active",
|
|
34
50
|
/** Credentials or token are invalid; the tenant admin must reconnect. */
|
|
35
51
|
authError: "auth_error",
|
|
36
|
-
/**
|
|
52
|
+
/** Interrupted: transient failure, quarantined mail, missing file storage or KMS; see lastError. */
|
|
37
53
|
degraded: "degraded",
|
|
38
54
|
/** Disconnected by the tenant admin; no further syncs run. */
|
|
39
55
|
disconnected: "disconnected",
|
|
40
56
|
};
|
|
57
|
+
// Why a mailbox is degraded. Codes only, never provider error text (that carries hosts/tokens).
|
|
58
|
+
export const InboundMailLastErrors = {
|
|
59
|
+
connectionFailed: "connection_failed",
|
|
60
|
+
rateLimited: "rate_limited",
|
|
61
|
+
messageQuarantined: "message_quarantined",
|
|
62
|
+
fileStorageUnavailable: "file_storage_unavailable",
|
|
63
|
+
encryptionUnavailable: "encryption_unavailable",
|
|
64
|
+
ingestUnavailable: "ingest_unavailable",
|
|
65
|
+
};
|
|
66
|
+
// Business reasons of failed connect writes; connect-routes maps both to 409 with the reason code.
|
|
67
|
+
export const InboundMailConnectErrors = {
|
|
68
|
+
addressAlreadyConnected: {
|
|
69
|
+
reason: "address_already_connected",
|
|
70
|
+
i18nKey: "inboundMail.accounts.errors.addressAlreadyConnected",
|
|
71
|
+
},
|
|
72
|
+
addressDisconnected: {
|
|
73
|
+
reason: "address_disconnected",
|
|
74
|
+
i18nKey: "inboundMail.accounts.errors.addressDisconnected",
|
|
75
|
+
},
|
|
76
|
+
credentialRequired: {
|
|
77
|
+
reason: "credential_required",
|
|
78
|
+
i18nKey: "inboundMail.accounts.errors.credentialRequired",
|
|
79
|
+
},
|
|
80
|
+
};
|
|
41
81
|
/**
|
|
42
82
|
* Tenant secret slot for an account: IMAP app password OR OAuth refresh
|
|
43
83
|
* token. The provider interprets the contents according to `authMethod`.
|
|
@@ -60,6 +100,16 @@ export const InboundMailAuthMethods = {
|
|
|
60
100
|
/** Nativer OAuth-Provider (m365-graph, gmail-rest). */
|
|
61
101
|
oauth: "oauth",
|
|
62
102
|
};
|
|
103
|
+
/** Provider key of inbound-provider-imap: only its password mailboxes have a credential form. */
|
|
104
|
+
export const IMAP_PROVIDER_KEY = "imap";
|
|
105
|
+
// How a mailbox the caller may re-arm gets its credential back, computed by account:list because a
|
|
106
|
+
// screen row condition cannot combine provider, auth method, status and owner.
|
|
107
|
+
export const MailAccountReactivationPaths = {
|
|
108
|
+
/** The IMAP form of inbound-provider-imap (reconnect-mailbox). */
|
|
109
|
+
passwordForm: "password_form",
|
|
110
|
+
/** The provider's OAuth sign-in through the connect route; its callback reopens the account. */
|
|
111
|
+
oauthFlow: "oauth_flow",
|
|
112
|
+
};
|
|
63
113
|
// **Multi-provider:** no global `provider` config key
|
|
64
114
|
// (unlike mail-foundation, as with billing-foundation). A tenant can connect
|
|
65
115
|
// an IMAP mailbox and an M365 mailbox in parallel; the provider is stored per
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import type { DispatchWrite } from "./supervisor-ingest.ts";
|
|
3
|
+
import type { InboundMailContext, InboundMailProviderPlugin, MailAccountRecord } from "./types.ts";
|
|
4
|
+
export declare const CONTENT_REFETCH_BUDGET_PER_TICK = 50;
|
|
5
|
+
export declare function refetchSnippetOnlyMessages(args: {
|
|
6
|
+
readonly db: DbConnection;
|
|
7
|
+
readonly dispatchWrite: DispatchWrite;
|
|
8
|
+
readonly providerCtx: InboundMailContext;
|
|
9
|
+
readonly account: MailAccountRecord;
|
|
10
|
+
readonly plugin: InboundMailProviderPlugin;
|
|
11
|
+
readonly windowDays: number;
|
|
12
|
+
readonly accessToken?: string | undefined;
|
|
13
|
+
readonly signal?: AbortSignal | undefined;
|
|
14
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Reloads the content of mails that were imported as snippet only (event version 1, before full text
|
|
2
|
+
// storage existed). Runs after a successful poll with a small per-account budget, so a large backlog
|
|
3
|
+
// is worked off over several ticks without slowing the regular sync. "unavailable" is terminal:
|
|
4
|
+
// mails that are gone from the server stop being candidates.
|
|
5
|
+
import { selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
6
|
+
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
7
|
+
import { inboundMessageAggregateId } from "./aggregate-id.js";
|
|
8
|
+
import { InboundMailFoundationHandlers } from "./constants.js";
|
|
9
|
+
import { seenMessageTable } from "./entities.js";
|
|
10
|
+
import { normalizeRawInboundMessage } from "./normalize-inbound-message.js";
|
|
11
|
+
import { inboundMessagesProjectionTable } from "./projection.js";
|
|
12
|
+
export const CONTENT_REFETCH_BUDGET_PER_TICK = 50;
|
|
13
|
+
const SEEN_PAGE_SIZE = 250;
|
|
14
|
+
const SEEN_MAX_PAGES = 4;
|
|
15
|
+
function needsContent(row) {
|
|
16
|
+
const bodyMissing = row.bodyRef === undefined || row.bodyRef === null || row.bodyRef === "";
|
|
17
|
+
return bodyMissing && (row.contentState == null || row.contentState === "snippet");
|
|
18
|
+
}
|
|
19
|
+
async function findSnippetOnlyMessageIds(db, account, windowDays) {
|
|
20
|
+
const cutoff = Temporal.Now.instant().subtract({ hours: windowDays * 24 });
|
|
21
|
+
const found = [];
|
|
22
|
+
let before;
|
|
23
|
+
for (let page = 0; page < SEEN_MAX_PAGES && found.length < CONTENT_REFETCH_BUDGET_PER_TICK; page++) {
|
|
24
|
+
const seen = await selectMany(db, seenMessageTable, {
|
|
25
|
+
tenantId: account.tenantId,
|
|
26
|
+
accountId: account.id,
|
|
27
|
+
seenAt: before ? { gte: cutoff, lt: before } : { gte: cutoff },
|
|
28
|
+
}, {
|
|
29
|
+
fields: ["providerMessageId", "seenAt"],
|
|
30
|
+
orderBy: { col: "seenAt", direction: "desc" },
|
|
31
|
+
limit: SEEN_PAGE_SIZE,
|
|
32
|
+
});
|
|
33
|
+
if (seen.length === 0)
|
|
34
|
+
break;
|
|
35
|
+
const aggregateToProvider = new Map(seen.map((row) => [
|
|
36
|
+
inboundMessageAggregateId(account.id, row.providerMessageId),
|
|
37
|
+
row.providerMessageId,
|
|
38
|
+
]));
|
|
39
|
+
const rows = await selectMany(db, inboundMessagesProjectionTable, { tenantId: account.tenantId, id: { in: [...aggregateToProvider.keys()] } }, { fields: ["id", "bodyRef", "contentState"] });
|
|
40
|
+
for (const row of rows) {
|
|
41
|
+
const providerMessageId = aggregateToProvider.get(row.id);
|
|
42
|
+
if (providerMessageId !== undefined && needsContent(row))
|
|
43
|
+
found.push(providerMessageId);
|
|
44
|
+
}
|
|
45
|
+
const oldest = seen[seen.length - 1];
|
|
46
|
+
if (seen.length < SEEN_PAGE_SIZE || !oldest)
|
|
47
|
+
break;
|
|
48
|
+
before = oldest.seenAt;
|
|
49
|
+
}
|
|
50
|
+
return found.slice(0, CONTENT_REFETCH_BUDGET_PER_TICK);
|
|
51
|
+
}
|
|
52
|
+
export async function refetchSnippetOnlyMessages(args) {
|
|
53
|
+
const { account, plugin, dispatchWrite } = args;
|
|
54
|
+
// skip: the provider cannot reload content.
|
|
55
|
+
if (!plugin.fetchContent)
|
|
56
|
+
return;
|
|
57
|
+
const ids = await findSnippetOnlyMessageIds(args.db, account, args.windowDays);
|
|
58
|
+
// skip: no snippet-only mail to reload.
|
|
59
|
+
if (ids.length === 0)
|
|
60
|
+
return;
|
|
61
|
+
const result = await plugin.fetchContent(args.providerCtx, account, ids, args.accessToken !== undefined || args.signal !== undefined
|
|
62
|
+
? {
|
|
63
|
+
...(args.accessToken !== undefined && { accessToken: args.accessToken }),
|
|
64
|
+
...(args.signal !== undefined && { signal: args.signal }),
|
|
65
|
+
}
|
|
66
|
+
: undefined);
|
|
67
|
+
const attach = (providerMessageId, content) => dispatchWrite({
|
|
68
|
+
handlerQn: InboundMailFoundationHandlers.attachMessageContent,
|
|
69
|
+
tenantId: account.tenantId,
|
|
70
|
+
payload: { accountId: account.id, providerMessageId, ...content },
|
|
71
|
+
});
|
|
72
|
+
for (const raw of result.messages) {
|
|
73
|
+
const msg = normalizeRawInboundMessage(raw);
|
|
74
|
+
if (msg.bodyText === "" && msg.rawMime == null && msg.bodyHtml === null) {
|
|
75
|
+
// Nothing usable came back: attach would leave the mail at "snippet", i.e. a candidate on
|
|
76
|
+
// every tick. "unavailable" is terminal.
|
|
77
|
+
await attach(msg.providerMessageId, { outcome: "unavailable" });
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
await attach(msg.providerMessageId, {
|
|
81
|
+
outcome: "fetched",
|
|
82
|
+
bodyText: msg.bodyText,
|
|
83
|
+
bodyTextTruncated: msg.bodyTextTruncated,
|
|
84
|
+
...(msg.rawMime != null && { rawMime: msg.rawMime }),
|
|
85
|
+
...(msg.bodyHtml !== null && { bodyHtml: msg.bodyHtml }),
|
|
86
|
+
attachments: msg.attachments,
|
|
87
|
+
skippedAttachments: msg.skippedAttachments,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const gone = [...result.missing, ...result.rejected.map((r) => r.providerMessageId)];
|
|
91
|
+
for (const providerMessageId of gone)
|
|
92
|
+
await attach(providerMessageId, { outcome: "unavailable" });
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function describeError(err: unknown): string;
|
|
@@ -19,9 +19,15 @@ export declare const mailAccountEntity: import("@cosmicdrift/kumiko-types/fields
|
|
|
19
19
|
readonly status: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
20
20
|
required: true;
|
|
21
21
|
};
|
|
22
|
+
readonly lastError: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
23
|
+
required: false;
|
|
24
|
+
};
|
|
22
25
|
readonly watchState: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
23
26
|
required: false;
|
|
24
27
|
};
|
|
28
|
+
readonly trustedAuthservId: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
29
|
+
required: false;
|
|
30
|
+
};
|
|
25
31
|
readonly connectedAt: {
|
|
26
32
|
readonly type: "timestamp";
|
|
27
33
|
readonly description?: string;
|
|
@@ -90,6 +96,26 @@ export declare const inboundMessageEntity: import("@cosmicdrift/kumiko-types/fie
|
|
|
90
96
|
readonly scope: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
91
97
|
required: false;
|
|
92
98
|
};
|
|
99
|
+
readonly bodyText: import("@cosmicdrift/kumiko-types/fields").EntityLongTextFieldDef & {
|
|
100
|
+
required: false;
|
|
101
|
+
};
|
|
102
|
+
readonly bodyTextTruncated: import("@cosmicdrift/kumiko-types/fields").BooleanFieldDef & {
|
|
103
|
+
required: false;
|
|
104
|
+
default: boolean;
|
|
105
|
+
};
|
|
106
|
+
readonly attachmentFileIds: import("@cosmicdrift/kumiko-types/fields").FilesFieldDef;
|
|
107
|
+
readonly skippedAttachments: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
108
|
+
required: false;
|
|
109
|
+
};
|
|
110
|
+
readonly senderAuthentication: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
111
|
+
required: false;
|
|
112
|
+
};
|
|
113
|
+
readonly contentState: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
114
|
+
required: false;
|
|
115
|
+
};
|
|
116
|
+
readonly contentUnavailableReason: import("@cosmicdrift/kumiko-types/fields").EntityTextFieldDef & {
|
|
117
|
+
required: false;
|
|
118
|
+
};
|
|
93
119
|
}, "tenant">;
|
|
94
120
|
/** Thread-Rollup. PK = aggregateId = mailThreadAggregateId(tenantId,
|
|
95
121
|
* threadKey). */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { collectPiiSubjectFields } from "@cosmicdrift/kumiko-framework/crypto";
|
|
2
2
|
import { deriveEntityTableMeta } from "@cosmicdrift/kumiko-framework/db";
|
|
3
|
-
import { access, createEntity, createNumberField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
3
|
+
import { access, createBooleanField, createEntity, createFilesField, createLongTextField, createNumberField, createTextField, createTimestampField, } from "@cosmicdrift/kumiko-framework/engine";
|
|
4
4
|
// ============================================================================
|
|
5
5
|
// Read models for the three event-sourced aggregates
|
|
6
6
|
// ============================================================================
|
|
@@ -56,7 +56,15 @@ export const mailAccountEntity = createEntity({
|
|
|
56
56
|
personal: false,
|
|
57
57
|
reason: "technical_reference",
|
|
58
58
|
}),
|
|
59
|
+
// Code of InboundMailLastErrors, never provider error text. Null on rows from before the column.
|
|
60
|
+
lastError: createTextField({ maxLength: 50, personal: false, reason: "technical_reference" }),
|
|
59
61
|
watchState: createTextField({ maxLength: 100, personal: false, reason: "technical_reference" }),
|
|
62
|
+
// Lower-case authserv-id of the mailbox's own server; null = none set.
|
|
63
|
+
trustedAuthservId: createTextField({
|
|
64
|
+
maxLength: 255,
|
|
65
|
+
personal: false,
|
|
66
|
+
reason: "technical_reference",
|
|
67
|
+
}),
|
|
60
68
|
connectedAt: createTimestampField({ required: true }),
|
|
61
69
|
},
|
|
62
70
|
});
|
|
@@ -73,8 +81,7 @@ export const inboundMessageEntity = createEntity({
|
|
|
73
81
|
reason: "technical_reference",
|
|
74
82
|
}),
|
|
75
83
|
// Scope is inherited from the account at ingest time: messages from a
|
|
76
|
-
// personal mailbox are visible only to the owner
|
|
77
|
-
// without joining read_mail_accounts.
|
|
84
|
+
// personal mailbox are visible only to the owner, without joining read_mail_accounts.
|
|
78
85
|
ownerUserId: createTextField({ maxLength: 36, personal: false, reason: "pseudonymous_fk" }),
|
|
79
86
|
messageIdHeader: createTextField({
|
|
80
87
|
required: true,
|
|
@@ -97,7 +104,40 @@ export const inboundMessageEntity = createEntity({
|
|
|
97
104
|
receivedAt: createTimestampField({ required: true }),
|
|
98
105
|
bodyRef: createTextField({ maxLength: 500, personal: false, reason: "technical_reference" }),
|
|
99
106
|
scope: createTextField({ maxLength: 200, personal: false, reason: "technical_reference" }),
|
|
107
|
+
// Full plaintext, capped at 32_000 characters before encryption (ciphertext is ~2.3x plus envelope).
|
|
108
|
+
// Null on rows from before the column; list-messages never selects it.
|
|
109
|
+
bodyText: createLongTextField({ maxLength: 200_000, personal: "tenant", find: "none" }),
|
|
110
|
+
bodyTextTruncated: createBooleanField(),
|
|
111
|
+
// Bound to the message (entityType = the aggregate type), so the file guard answers with the
|
|
112
|
+
// mail's visibility. The fileRefs are bound at ingest, the projection copies the ids.
|
|
113
|
+
attachmentFileIds: createFilesField({ personal: false, reason: "technical_reference" }),
|
|
114
|
+
// JSON-stringified SkippedInboundAttachment[]: nullable JSON stays a text column
|
|
115
|
+
// (jsonb fields are NOT NULL), like to/cc.
|
|
116
|
+
skippedAttachments: createTextField({
|
|
117
|
+
maxLength: 20_000,
|
|
118
|
+
personal: false,
|
|
119
|
+
reason: "technical_reference",
|
|
120
|
+
}),
|
|
121
|
+
// JSON-stringified SenderAuthentication or "null"; a SQL null (rows from before the column) reads as null.
|
|
122
|
+
senderAuthentication: createTextField({
|
|
123
|
+
maxLength: 4000,
|
|
124
|
+
personal: false,
|
|
125
|
+
reason: "technical_reference",
|
|
126
|
+
}),
|
|
127
|
+
// "complete" | "snippet" | "unavailable"; null counts as "snippet".
|
|
128
|
+
contentState: createTextField({
|
|
129
|
+
maxLength: 20,
|
|
130
|
+
personal: false,
|
|
131
|
+
reason: "technical_reference",
|
|
132
|
+
}),
|
|
133
|
+
// One of INBOUND_CONTENT_UNAVAILABLE_REASONS; null while the content is there or not yet missing.
|
|
134
|
+
contentUnavailableReason: createTextField({
|
|
135
|
+
maxLength: 30,
|
|
136
|
+
personal: false,
|
|
137
|
+
reason: "technical_reference",
|
|
138
|
+
}),
|
|
100
139
|
},
|
|
140
|
+
attachedFileAccess: "record-only",
|
|
101
141
|
});
|
|
102
142
|
/** Thread-Rollup. PK = aggregateId = mailThreadAggregateId(tenantId,
|
|
103
143
|
* threadKey). */
|