@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
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ConfigAccessor, Registry } from "@cosmicdrift/kumiko-framework/engine";
|
|
2
2
|
import type { MetricsHandle } from "@cosmicdrift/kumiko-framework/observability";
|
|
3
3
|
import { INBOUND_MAIL_PROVIDER_EXTENSION, type InboundMailAccountStatus } from "./constants.ts";
|
|
4
|
-
import type {
|
|
4
|
+
import type { InboundOAuthFlow } from "./inbound-oauth-flow.ts";
|
|
5
|
+
import type { OutboundAttachment, OutboundMailMessage, ProviderSentMail } from "./outbound-mail.ts";
|
|
6
|
+
import type { SenderAuthentication } from "./sender-auth.ts";
|
|
5
7
|
/**
|
|
6
8
|
* Slim context for provider plugins.
|
|
7
9
|
*
|
|
@@ -45,8 +47,22 @@ export type MailAccountRecord = {
|
|
|
45
47
|
/** Postfach-Adresse, Plaintext (decrypted). */
|
|
46
48
|
readonly address: string;
|
|
47
49
|
readonly displayName: string;
|
|
50
|
+
/** The real status; the supervisor syncs active and degraded mailboxes. */
|
|
48
51
|
readonly status: InboundMailAccountStatus;
|
|
49
52
|
readonly watchState: string;
|
|
53
|
+
/** authserv-id of the mailbox's own server for sender verification; absent or null = none set. */
|
|
54
|
+
readonly trustedAuthservId?: string | null;
|
|
55
|
+
};
|
|
56
|
+
export type RawInboundAttachment = {
|
|
57
|
+
readonly fileName: string;
|
|
58
|
+
readonly mimeType: string;
|
|
59
|
+
readonly data: Uint8Array;
|
|
60
|
+
};
|
|
61
|
+
/** An attachment that was not stored. Carries no file name: the reason is shown to operators, not the content. */
|
|
62
|
+
export type SkippedInboundAttachment = {
|
|
63
|
+
readonly mimeType: string;
|
|
64
|
+
readonly size: number;
|
|
65
|
+
readonly reason: "too_large" | "mail_too_large" | "rejected" | "no_file_storage" | "nesting_too_deep";
|
|
50
66
|
};
|
|
51
67
|
/**
|
|
52
68
|
* Normalized incoming mail — provider output and ingest input.
|
|
@@ -74,9 +90,17 @@ export type RawInboundMessage = {
|
|
|
74
90
|
readonly snippet: string;
|
|
75
91
|
/** ISO instant — INTERNALDATE or receivedDateTime, not ingest time. */
|
|
76
92
|
readonly receivedAtIso: string;
|
|
77
|
-
/** Raw MIME; null
|
|
93
|
+
/** Raw MIME; null when the provider has no original to keep. The Foundation persists it through
|
|
78
94
|
* file-foundation and writes bodyRef, so the event store remains blob-free. */
|
|
79
95
|
readonly rawMime: Uint8Array | null;
|
|
96
|
+
/** Full plaintext (derived from the HTML for HTML-only mails). Optional so providers
|
|
97
|
+
* predating the field keep compiling; the supervisor treats absent as empty. */
|
|
98
|
+
readonly text?: string;
|
|
99
|
+
readonly html?: string | null;
|
|
100
|
+
readonly attachments?: readonly RawInboundAttachment[];
|
|
101
|
+
readonly skippedAttachments?: readonly SkippedInboundAttachment[];
|
|
102
|
+
/** What the mailbox's own server verified about the sender. Absent counts as unknown, never as pass. */
|
|
103
|
+
readonly senderAuthentication?: SenderAuthentication | null;
|
|
80
104
|
/** Generic scope hint ("inbox", folder name), with no application semantics. */
|
|
81
105
|
readonly scope: string;
|
|
82
106
|
};
|
|
@@ -84,50 +108,36 @@ export type RawInboundMessage = {
|
|
|
84
108
|
* · Gmail {historyId}. Foundation persisted ihn JSON-stringified in
|
|
85
109
|
* store_mail_sync_cursors, interpretiert ihn nie. */
|
|
86
110
|
export type SyncCursorPayload = Readonly<Record<string, unknown>>;
|
|
111
|
+
/** A message the provider could not turn into a RawInboundMessage; the cursor moves past it. */
|
|
112
|
+
export type RejectedInboundMessage = {
|
|
113
|
+
readonly providerMessageId: string;
|
|
114
|
+
readonly reason: "unparseable";
|
|
115
|
+
/** The original, when the provider has it; kept so the quarantined mail stays visible and retryable. */
|
|
116
|
+
readonly rawMime?: Uint8Array;
|
|
117
|
+
/** Envelope headers the provider could read without parsing the body. */
|
|
118
|
+
readonly headers?: {
|
|
119
|
+
readonly from: string;
|
|
120
|
+
readonly to: readonly string[];
|
|
121
|
+
readonly cc: readonly string[];
|
|
122
|
+
readonly subject: string;
|
|
123
|
+
readonly messageIdHeader: string | null;
|
|
124
|
+
readonly receivedAtIso: string;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
export type InboundContentFetchResult = {
|
|
128
|
+
readonly messages: readonly RawInboundMessage[];
|
|
129
|
+
/** Not on the server (anymore) or from a previous UIDVALIDITY. */
|
|
130
|
+
readonly missing: readonly string[];
|
|
131
|
+
readonly rejected: readonly RejectedInboundMessage[];
|
|
132
|
+
};
|
|
87
133
|
export type InboundFetchResult = {
|
|
88
134
|
readonly messages: readonly RawInboundMessage[];
|
|
135
|
+
readonly rejected?: readonly RejectedInboundMessage[];
|
|
89
136
|
readonly nextCursor: SyncCursorPayload;
|
|
90
137
|
/** true ⇒ the Foundation calls fetch again in the same poll tick
|
|
91
138
|
* (pagination) until false or the maxMessages budget is exhausted. */
|
|
92
139
|
readonly hasMore: boolean;
|
|
93
140
|
};
|
|
94
|
-
export type OAuthTokenSet = {
|
|
95
|
-
readonly accessToken: string;
|
|
96
|
-
/** ISO-Instant. TTL typisch ~1h ⇒ Foundation refresht before-poll. */
|
|
97
|
-
readonly expiresAt: string;
|
|
98
|
-
readonly refreshToken?: string;
|
|
99
|
-
readonly scopesGranted: readonly string[];
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* OAuth portion of the contract — OAuth providers only; imap in password
|
|
103
|
-
* mode omits `oauth`. The Foundation provides the routes
|
|
104
|
-
* (`/inbound-mail/connect`, `/inbound-mail/oauth/callback`) generically;
|
|
105
|
-
* providers MUST NOT register their own routes.
|
|
106
|
-
*/
|
|
107
|
-
export type InboundOAuthFlow = {
|
|
108
|
-
/** Scopes: request receive AND send in a SINGLE consent; re-consent is costly. */
|
|
109
|
-
readonly scopes: {
|
|
110
|
-
readonly receive: readonly string[];
|
|
111
|
-
readonly send?: readonly string[];
|
|
112
|
-
};
|
|
113
|
-
readonly buildAuthorizeUrl: (ctx: InboundMailContext, p: {
|
|
114
|
-
readonly state: string;
|
|
115
|
-
readonly redirectUri: string;
|
|
116
|
-
}) => Promise<string>;
|
|
117
|
-
readonly exchangeCode: (ctx: InboundMailContext, p: {
|
|
118
|
-
readonly code: string;
|
|
119
|
-
readonly redirectUri: string;
|
|
120
|
-
}) => Promise<OAuthTokenSet>;
|
|
121
|
-
readonly refreshAccessToken: (ctx: InboundMailContext, account: MailAccountRecord, refreshToken: string,
|
|
122
|
-
/** The foundation aborts `signal` after a hard timeout while holding a
|
|
123
|
-
* per-account lock (a pool connection is pinned meanwhile). Providers
|
|
124
|
-
* MUST pass it to their token-endpoint fetch; the foundation awaits the
|
|
125
|
-
* provider's result and never drops a late one, because that could lose
|
|
126
|
-
* a rotated refresh token. */
|
|
127
|
-
opts?: {
|
|
128
|
-
readonly signal?: AbortSignal;
|
|
129
|
-
}) => Promise<OAuthTokenSet>;
|
|
130
|
-
};
|
|
131
141
|
/**
|
|
132
142
|
* Inbound-mail provider plugin contract. Each provider feature
|
|
133
143
|
* (inbound-provider-imap, -m365-graph, -gmail-rest) registers an
|
|
@@ -155,19 +165,29 @@ export type InboundMailProviderPlugin = {
|
|
|
155
165
|
* the listing/delta page and download MIME only for the returned ids.
|
|
156
166
|
* Ingest dedup stays the correctness anchor; this only saves downloads. */
|
|
157
167
|
readonly filterUnknownMessageIds?: (providerMessageIds: readonly string[]) => Promise<ReadonlySet<string>>;
|
|
168
|
+
/** Aborted when the supervisor gives up on this account's sync (per-account deadline). A
|
|
169
|
+
* provider that can cancel closes its connection then; one that cannot is abandoned and
|
|
170
|
+
* its late result is dropped. */
|
|
171
|
+
readonly signal?: AbortSignal;
|
|
158
172
|
}) => Promise<InboundFetchResult>;
|
|
173
|
+
/** Re-downloads already imported messages that were stored as snippet only. */
|
|
174
|
+
readonly fetchContent?: (ctx: InboundMailContext, account: MailAccountRecord, providerMessageIds: readonly string[], opts?: {
|
|
175
|
+
readonly accessToken?: string;
|
|
176
|
+
readonly signal?: AbortSignal;
|
|
177
|
+
}) => Promise<InboundContentFetchResult>;
|
|
159
178
|
/** Nur OAuth-Provider. */
|
|
160
179
|
readonly oauth?: InboundOAuthFlow;
|
|
161
180
|
/** Sends from the mailbox address through the customer's own server. Throws
|
|
162
181
|
* MailSendNotConfiguredError, InboundAuthError, InboundTransientError or MailSendRejectedError. */
|
|
163
|
-
readonly send?: (ctx: InboundMailContext, account: MailAccountRecord, message: OutboundMailMessage) => Promise<
|
|
182
|
+
readonly send?: (ctx: InboundMailContext, account: MailAccountRecord, message: OutboundMailMessage, attachments: readonly OutboundAttachment[]) => Promise<ProviderSentMail>;
|
|
164
183
|
/** Optional live push (IMAP IDLE, later Graph/Gmail webhooks).
|
|
165
184
|
* Returns stop(). Polling remains reconciliation: watch optimizes
|
|
166
185
|
* latency but is never the correctness anchor. `onError` reports a dead
|
|
167
186
|
* live connection (drop, auth revocation) to the supervisor, which
|
|
168
187
|
* restarts it with backoff; the provider does NOT reconnect itself. */
|
|
169
188
|
readonly watch?: (ctx: InboundMailContext, account: MailAccountRecord, handlers: {
|
|
170
|
-
|
|
189
|
+
/** `rejected`: mails the provider could not parse, quarantined right away instead of at the next poll. */
|
|
190
|
+
readonly onMessages: (msgs: readonly RawInboundMessage[], rejected?: readonly RejectedInboundMessage[]) => Promise<void>;
|
|
171
191
|
readonly onError: (err: unknown) => void;
|
|
172
192
|
},
|
|
173
193
|
/** Same `accessToken` semantics as `fetch` opts; re-minted on every
|
|
@@ -182,24 +202,3 @@ declare module "@cosmicdrift/kumiko-framework/engine" {
|
|
|
182
202
|
[INBOUND_MAIL_PROVIDER_EXTENSION]: InboundMailProviderPlugin;
|
|
183
203
|
}
|
|
184
204
|
}
|
|
185
|
-
export declare class InboundAuthError extends Error {
|
|
186
|
-
readonly kind: "inbound-auth-error";
|
|
187
|
-
constructor(message: string);
|
|
188
|
-
}
|
|
189
|
-
export declare class InboundRateLimitError extends Error {
|
|
190
|
-
readonly kind: "inbound-rate-limit-error";
|
|
191
|
-
readonly retryAfterMs: number;
|
|
192
|
-
constructor(message: string, retryAfterMs: number);
|
|
193
|
-
}
|
|
194
|
-
export declare class InboundCursorInvalidError extends Error {
|
|
195
|
-
readonly kind: "inbound-cursor-invalid-error";
|
|
196
|
-
constructor(message: string);
|
|
197
|
-
}
|
|
198
|
-
export declare class InboundTransientError extends Error {
|
|
199
|
-
readonly kind: "inbound-transient-error";
|
|
200
|
-
constructor(message: string);
|
|
201
|
-
}
|
|
202
|
-
export declare function isInboundAuthError(e: unknown): e is InboundAuthError;
|
|
203
|
-
export declare function isInboundRateLimitError(e: unknown): e is InboundRateLimitError;
|
|
204
|
-
export declare function isInboundCursorInvalidError(e: unknown): e is InboundCursorInvalidError;
|
|
205
|
-
export declare function isInboundTransientError(e: unknown): e is InboundTransientError;
|
|
@@ -21,57 +21,3 @@ export function isInboundMailProviderPlugin(o) {
|
|
|
21
21
|
"fetch" in o &&
|
|
22
22
|
typeof o.fetch === "function");
|
|
23
23
|
}
|
|
24
|
-
// =============================================================================
|
|
25
|
-
// Typed errors handled uniformly by the Foundation during polling:
|
|
26
|
-
// InboundAuthError → status=auth_error, no retry
|
|
27
|
-
// InboundRateLimitError → abort poll, wait for the next cron tick
|
|
28
|
-
// InboundCursorInvalidError → reset cursor + full resync in the backfill
|
|
29
|
-
// window; deduplication handles duplicates
|
|
30
|
-
// InboundTransientError → job retry (retries: 3, exponential)
|
|
31
|
-
// =============================================================================
|
|
32
|
-
//
|
|
33
|
-
// Use a `kind` discriminant instead of instanceof: plugins and the Foundation
|
|
34
|
-
// may run in separate bundles (dual-package-hazard), and instanceof is
|
|
35
|
-
// unreliable across realm or package-copy boundaries.
|
|
36
|
-
export class InboundAuthError extends Error {
|
|
37
|
-
kind = "inbound-auth-error";
|
|
38
|
-
constructor(message) {
|
|
39
|
-
super(message);
|
|
40
|
-
this.name = "InboundAuthError";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export class InboundRateLimitError extends Error {
|
|
44
|
-
kind = "inbound-rate-limit-error";
|
|
45
|
-
retryAfterMs;
|
|
46
|
-
constructor(message, retryAfterMs) {
|
|
47
|
-
super(message);
|
|
48
|
-
this.name = "InboundRateLimitError";
|
|
49
|
-
this.retryAfterMs = retryAfterMs;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
export class InboundCursorInvalidError extends Error {
|
|
53
|
-
kind = "inbound-cursor-invalid-error";
|
|
54
|
-
constructor(message) {
|
|
55
|
-
super(message);
|
|
56
|
-
this.name = "InboundCursorInvalidError";
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
export class InboundTransientError extends Error {
|
|
60
|
-
kind = "inbound-transient-error";
|
|
61
|
-
constructor(message) {
|
|
62
|
-
super(message);
|
|
63
|
-
this.name = "InboundTransientError";
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
export function isInboundAuthError(e) {
|
|
67
|
-
return e instanceof Error && "kind" in e && e.kind === "inbound-auth-error";
|
|
68
|
-
}
|
|
69
|
-
export function isInboundRateLimitError(e) {
|
|
70
|
-
return e instanceof Error && "kind" in e && e.kind === "inbound-rate-limit-error";
|
|
71
|
-
}
|
|
72
|
-
export function isInboundCursorInvalidError(e) {
|
|
73
|
-
return e instanceof Error && "kind" in e && e.kind === "inbound-cursor-invalid-error";
|
|
74
|
-
}
|
|
75
|
-
export function isInboundTransientError(e) {
|
|
76
|
-
return e instanceof Error && "kind" in e && e.kind === "inbound-transient-error";
|
|
77
|
-
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
|
+
import { wakeMailAccount } from "./account-wake.js";
|
|
3
|
+
import { InboundMailAccountStatuses } from "./constants.js";
|
|
4
|
+
import { MAIL_ACCOUNT_CONNECTED_EVENT_QN, MAIL_ACCOUNT_UPDATED_EVENT_QN } from "./events.js";
|
|
5
|
+
const SUPERVISOR_AUDIT_REASON = "watch_supervisor";
|
|
6
|
+
// Per-instance consumer: every process sees every account event, so the supervisor running in that
|
|
7
|
+
// process syncs a freshly connected, reconnected or re-activated mailbox immediately. Supervisor-made
|
|
8
|
+
// updates (watch state, health) are skipped, otherwise its own bookkeeping would trigger syncs.
|
|
9
|
+
// It only reaches an in-process registry and never writes to the database.
|
|
10
|
+
export function registerMailAccountWakeConsumer(r) {
|
|
11
|
+
const wakeIfActive = (event) => {
|
|
12
|
+
// skip: only an account that is active again needs an immediate sync.
|
|
13
|
+
if (propertyOf(event.payload, "status") !== InboundMailAccountStatuses.active)
|
|
14
|
+
return;
|
|
15
|
+
// skip: the supervisor's own bookkeeping must not trigger another sync.
|
|
16
|
+
if (event.metadata.headers?.["reason"] === SUPERVISOR_AUDIT_REASON)
|
|
17
|
+
return;
|
|
18
|
+
wakeMailAccount(event.tenantId, event.aggregateId);
|
|
19
|
+
};
|
|
20
|
+
r.multiStreamProjection({
|
|
21
|
+
name: "mail-account-wake",
|
|
22
|
+
delivery: "per-instance",
|
|
23
|
+
startFrom: "now",
|
|
24
|
+
runIn: "both",
|
|
25
|
+
apply: {
|
|
26
|
+
[MAIL_ACCOUNT_CONNECTED_EVENT_QN]: async (event) => wakeIfActive(event),
|
|
27
|
+
[MAIL_ACCOUNT_UPDATED_EVENT_QN]: async (event) => wakeIfActive(event),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type InFlightSyncs, type PollAccountOptions, type PollAccountResult } from "./sync-account-now.ts";
|
|
2
|
+
import type { SyncableAccount } from "./syncable-accounts.ts";
|
|
3
|
+
import type { InboundMailProviderPlugin } from "./types.ts";
|
|
4
|
+
export type WatchCatchUp = {
|
|
5
|
+
/** Fire-and-forget; failures are logged and never stop the watch. */
|
|
6
|
+
readonly schedule: (account: SyncableAccount, plugin: InboundMailProviderPlugin) => void;
|
|
7
|
+
readonly settled: () => Promise<unknown>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A watch only sees mail that arrives after its mailbox is open, so mail delivered between a
|
|
11
|
+
* poll's fetch and the watch start would wait for the next tick. One poll that starts after the
|
|
12
|
+
* watch is open closes that gap for every provider.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createWatchCatchUp(deps: {
|
|
15
|
+
readonly inFlight: InFlightSyncs;
|
|
16
|
+
readonly pollAccount: (account: SyncableAccount, plugin: InboundMailProviderPlugin, options: PollAccountOptions) => Promise<PollAccountResult>;
|
|
17
|
+
readonly isRunning: () => boolean;
|
|
18
|
+
readonly log: (line: string) => void;
|
|
19
|
+
}): WatchCatchUp;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describeError } from "./describe-error.js";
|
|
2
|
+
import { runExclusivePerAccount, } from "./sync-account-now.js";
|
|
3
|
+
/**
|
|
4
|
+
* A watch only sees mail that arrives after its mailbox is open, so mail delivered between a
|
|
5
|
+
* poll's fetch and the watch start would wait for the next tick. One poll that starts after the
|
|
6
|
+
* watch is open closes that gap for every provider.
|
|
7
|
+
*/
|
|
8
|
+
export function createWatchCatchUp(deps) {
|
|
9
|
+
const pending = new Set();
|
|
10
|
+
async function catchUp(account, plugin) {
|
|
11
|
+
// A sync running now may have fetched before the mailbox was open, so joining it would not close the gap.
|
|
12
|
+
for (let running = deps.inFlight.get(account.id); running; running = deps.inFlight.get(account.id)) {
|
|
13
|
+
await running.catch(() => { });
|
|
14
|
+
}
|
|
15
|
+
// skip: the supervisor stopped while the sync ran.
|
|
16
|
+
if (!deps.isRunning())
|
|
17
|
+
return;
|
|
18
|
+
await runExclusivePerAccount(deps.inFlight, account.id, async () => {
|
|
19
|
+
await deps.pollAccount(account, plugin, {});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
schedule(account, plugin) {
|
|
24
|
+
const task = catchUp(account, plugin)
|
|
25
|
+
.catch((err) => deps.log(`inbound-mail: watch catch-up for account ${account.id} failed: ${describeError(err)}`))
|
|
26
|
+
.finally(() => {
|
|
27
|
+
pending.delete(task);
|
|
28
|
+
});
|
|
29
|
+
pending.add(task);
|
|
30
|
+
},
|
|
31
|
+
settled: () => Promise.allSettled([...pending]),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DistributedLock } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
2
|
+
import type { MailAccountRecord } from "./types.ts";
|
|
3
|
+
import type { WatcherState, WatchLeaseResult } from "./watch-supervisor-types.ts";
|
|
4
|
+
export type WatchLease = {
|
|
5
|
+
readonly acquire: (account: MailAccountRecord, state: WatcherState) => Promise<WatchLeaseResult>;
|
|
6
|
+
};
|
|
7
|
+
export declare function createWatchLease(deps: {
|
|
8
|
+
readonly lock: DistributedLock | undefined;
|
|
9
|
+
readonly ttlSeconds: number;
|
|
10
|
+
readonly renewIntervalMs: number;
|
|
11
|
+
readonly watchers: ReadonlyMap<string, WatcherState>;
|
|
12
|
+
readonly isRunning: () => boolean;
|
|
13
|
+
readonly stopWatcher: (accountId: string) => Promise<void>;
|
|
14
|
+
readonly log: (line: string) => void;
|
|
15
|
+
}): WatchLease;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describeError } from "./describe-error.js";
|
|
2
|
+
// The cross-worker claim on one account's watch: acquired before plugin.watch(), renewed by a
|
|
3
|
+
// heartbeat for as long as the watcher state exists, and given up locally once it is lost.
|
|
4
|
+
export function createWatchLease(deps) {
|
|
5
|
+
const { lock, ttlSeconds, renewIntervalMs, watchers, isRunning, stopWatcher, log } = deps;
|
|
6
|
+
// Heartbeat for a held watch lease. Independent of the connection's own
|
|
7
|
+
// lifecycle — it keeps renewing across reconnect backoff, not just while
|
|
8
|
+
// `plugin.watch()` is actually connected, so a flaky IMAP link doesn't
|
|
9
|
+
// make this worker lose the account to a peer mid-backoff.
|
|
10
|
+
function scheduleRenew(account, state, generation) {
|
|
11
|
+
state.renewTimer = setTimeout(() => {
|
|
12
|
+
void renewLeaseOnce(account, state, generation);
|
|
13
|
+
}, renewIntervalMs);
|
|
14
|
+
}
|
|
15
|
+
async function tearDownAfterRenewFailures(account, state, reason) {
|
|
16
|
+
log(`inbound-mail: watch lease ${reason} for account ${account.id} — tearing down local watcher`);
|
|
17
|
+
state.lockToken = null;
|
|
18
|
+
await stopWatcher(account.id);
|
|
19
|
+
}
|
|
20
|
+
async function renewLeaseOnce(account, state, generation) {
|
|
21
|
+
state.renewTimer = null;
|
|
22
|
+
// skip: supervisor stopped, generation superseded, or lease already lost — stale timer fire, nothing to renew.
|
|
23
|
+
if (!isRunning() || state.generation !== generation || !state.lockToken || !lock)
|
|
24
|
+
return;
|
|
25
|
+
let renewed;
|
|
26
|
+
try {
|
|
27
|
+
renewed = await lock.renew(account.id, state.lockToken, ttlSeconds);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
log(`inbound-mail: watch lease renew for account ${account.id} failed: ${describeError(err)}`);
|
|
31
|
+
state.renewFailures += 1;
|
|
32
|
+
// After failures spanning a full lease TTL, tear down — otherwise a
|
|
33
|
+
// peer can acquire the expired key while we still hold an IDLE conn.
|
|
34
|
+
if (state.renewFailures * renewIntervalMs >= ttlSeconds * 1000) {
|
|
35
|
+
await tearDownAfterRenewFailures(account, state, "renew failed across TTL");
|
|
36
|
+
// skip: connection torn down, no reschedule
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
rescheduleIfStillHeld(account, state, generation);
|
|
40
|
+
// skip: renew failed but TTL not yet exhausted, retry already scheduled
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
state.renewFailures = 0;
|
|
44
|
+
if (!renewed) {
|
|
45
|
+
await tearDownAfterRenewFailures(account, state, "lost");
|
|
46
|
+
// skip: lease lost and torn down, nothing to reschedule
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
rescheduleIfStillHeld(account, state, generation);
|
|
50
|
+
}
|
|
51
|
+
function rescheduleIfStillHeld(account, state, generation) {
|
|
52
|
+
if (isRunning() && state.generation === generation && state.lockToken) {
|
|
53
|
+
scheduleRenew(account, state, generation);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// kumiko-lint-ignore complexity-budget yield-point stale-map check after acquire is intentional
|
|
57
|
+
async function acquire(account, state) {
|
|
58
|
+
if (!lock || state.lockToken)
|
|
59
|
+
return "acquired";
|
|
60
|
+
// A throwing lock (Redis outage) reads as "not claimed": the next tick retries instead of leaving the start flag set.
|
|
61
|
+
const token = await lock.acquire(account.id, { ttlSeconds: ttlSeconds }).catch((err) => {
|
|
62
|
+
log(`inbound-mail: watch lease acquire for account ${account.id} failed: ${describeError(err)}`);
|
|
63
|
+
return null;
|
|
64
|
+
});
|
|
65
|
+
if (!token)
|
|
66
|
+
return "no-token";
|
|
67
|
+
// The acquire() await is a yield point: a concurrent stopWatcher()
|
|
68
|
+
// (e.g. from a lost-lease renewal on a different generation) may have
|
|
69
|
+
// already retired this exact state and removed it from the map. If so,
|
|
70
|
+
// committing the fresh token onto it would leak the lease — nothing
|
|
71
|
+
// would ever release it, blocking failover for the full TTL.
|
|
72
|
+
if (watchers.get(account.id) !== state) {
|
|
73
|
+
await lock.release(account.id, token);
|
|
74
|
+
return "stale";
|
|
75
|
+
}
|
|
76
|
+
state.lockToken = token;
|
|
77
|
+
scheduleRenew(account, state, state.generation);
|
|
78
|
+
return "acquired";
|
|
79
|
+
}
|
|
80
|
+
return { acquire };
|
|
81
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
|
|
2
|
+
import type { DistributedLock } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
3
|
+
import type { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
4
|
+
import type { OAuthAccessTokenManager } from "./oauth-access-token.ts";
|
|
5
|
+
import type { InboundMailContext, MailAccountRecord, RawInboundMessage } from "./types.ts";
|
|
6
|
+
export type InboundMailSupervisorDeps = {
|
|
7
|
+
/** Slim context for provider calls (`registry` is required; `secrets` is
|
|
8
|
+
* used for provider credential reads). */
|
|
9
|
+
readonly providerCtx: InboundMailContext;
|
|
10
|
+
/** App database — direct reads from read_mail_accounts (account snapshot)
|
|
11
|
+
* and direct writes to store_mail_sync_cursors (unmanaged store). */
|
|
12
|
+
readonly db: DbConnection;
|
|
13
|
+
/** Standard dispatcher with SystemUser — carries ingest-message and
|
|
14
|
+
* update-account. */
|
|
15
|
+
readonly dispatchWrite: (args: {
|
|
16
|
+
readonly handlerQn: string;
|
|
17
|
+
readonly payload: unknown;
|
|
18
|
+
readonly tenantId: string;
|
|
19
|
+
}) => Promise<{
|
|
20
|
+
readonly isSuccess: boolean;
|
|
21
|
+
readonly data?: unknown;
|
|
22
|
+
readonly error?: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
/** Optional override for where the raw MIME original is stored. Without it the ingest handler
|
|
25
|
+
* stores original and attachments itself through the tenant's file provider
|
|
26
|
+
* (bodyRef = "" here lets it pick the deterministic key). */
|
|
27
|
+
readonly storeBody?: (account: MailAccountRecord, msg: RawInboundMessage) => Promise<string>;
|
|
28
|
+
readonly pollIntervalMs?: number;
|
|
29
|
+
/** Clock for the failure-count bucket of a tick; tests inject a fake one. */
|
|
30
|
+
readonly now?: () => Temporal.Instant;
|
|
31
|
+
readonly backfillWindowDays?: number;
|
|
32
|
+
readonly maxMessagesPerPoll?: number;
|
|
33
|
+
/** Accounts synced side by side within one tick. Default 4. */
|
|
34
|
+
readonly pollConcurrency?: number;
|
|
35
|
+
/** Longest a single account's sync may run before the supervisor abandons it as a failed poll.
|
|
36
|
+
* Default 10 minutes. */
|
|
37
|
+
readonly accountPollDeadlineMs?: number;
|
|
38
|
+
readonly watchBackoffInitialMs?: number;
|
|
39
|
+
readonly watchBackoffMaxMs?: number;
|
|
40
|
+
/** Coordinates the IMAP watch (not the poll) across worker processes:
|
|
41
|
+
* before `plugin.watch()`, ensureWatcher claims a TTL lease for the
|
|
42
|
+
* account via `lock.acquire` and renews it via `lock.renew` while the
|
|
43
|
+
* watcher lives. Omit for single-process deployments — every active
|
|
44
|
+
* account is watched locally, same as before. */
|
|
45
|
+
readonly lock?: DistributedLock;
|
|
46
|
+
/** Access-token lifecycle for OAuth accounts. Defaults to a manager built
|
|
47
|
+
* from `db` + `providerCtx.secrets`; pass the instance shared with
|
|
48
|
+
* `createInboundMailConnectRoutes` so a fresh connect primes this cache. */
|
|
49
|
+
readonly oauthTokens?: OAuthAccessTokenManager;
|
|
50
|
+
/** TTL (seconds) for the per-account watch lease. Default 90s, renewed
|
|
51
|
+
* every ttl/3. Only used when `lock` is set. */
|
|
52
|
+
readonly watchLeaseTtlSeconds?: number;
|
|
53
|
+
readonly log?: (line: string) => void;
|
|
54
|
+
};
|
|
55
|
+
export type WatcherState = {
|
|
56
|
+
stop: (() => Promise<void>) | null;
|
|
57
|
+
backoffMs: number;
|
|
58
|
+
restartTimer: ReturnType<typeof setTimeout> | null;
|
|
59
|
+
/** Incremented by stop() to prevent a delayed restart from reviving
|
|
60
|
+
* an already stopped watcher. */
|
|
61
|
+
generation: number;
|
|
62
|
+
/** Token from `deps.lock.acquire` while this worker owns the account's
|
|
63
|
+
* watch lease; null when unclaimed (no `deps.lock`, or claim lost). */
|
|
64
|
+
lockToken: string | null;
|
|
65
|
+
renewTimer: ReturnType<typeof setTimeout> | null;
|
|
66
|
+
/** Consecutive renew() throws — tear down once failures span a full TTL. */
|
|
67
|
+
renewFailures: number;
|
|
68
|
+
/** True while plugin.watch() is in flight (re-entrancy guard). */
|
|
69
|
+
starting: boolean;
|
|
70
|
+
/** The provider reads the account it was handed at watch start; a changed trust setting
|
|
71
|
+
* only reaches it through a fresh watch. */
|
|
72
|
+
trustedAuthservId: string | null;
|
|
73
|
+
};
|
|
74
|
+
export type WatchLeaseResult = "acquired" | "no-token" | "stale";
|
|
75
|
+
export type InboundMailSupervisor = {
|
|
76
|
+
readonly start: () => Promise<void>;
|
|
77
|
+
/** Reconciliation run across all active accounts; also usable standalone
|
|
78
|
+
* for tests and manual operational triggers. */
|
|
79
|
+
readonly pollOnce: () => Promise<void>;
|
|
80
|
+
/** Syncs one account immediately (connect/reconnect wake-up); joins a sync already running for it. */
|
|
81
|
+
readonly syncAccountNow: (accountId: string) => Promise<void>;
|
|
82
|
+
readonly stop: () => Promise<void>;
|
|
83
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,54 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DistributedLock } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
3
|
-
import { type OAuthAccessTokenManager } from "./oauth-access-token.ts";
|
|
4
|
-
import { type InboundMailContext, type MailAccountRecord, type RawInboundMessage } from "./types.ts";
|
|
5
|
-
export type InboundMailSupervisorDeps = {
|
|
6
|
-
/** Slim context for provider calls (`registry` is required; `secrets` is
|
|
7
|
-
* used for provider credential reads). */
|
|
8
|
-
readonly providerCtx: InboundMailContext;
|
|
9
|
-
/** App database — direct reads from read_mail_accounts (account snapshot)
|
|
10
|
-
* and direct writes to store_mail_sync_cursors (unmanaged store). */
|
|
11
|
-
readonly db: DbConnection;
|
|
12
|
-
/** Standard dispatcher with SystemUser — carries ingest-message and
|
|
13
|
-
* update-account. */
|
|
14
|
-
readonly dispatchWrite: (args: {
|
|
15
|
-
readonly handlerQn: string;
|
|
16
|
-
readonly payload: unknown;
|
|
17
|
-
readonly tenantId: string;
|
|
18
|
-
}) => Promise<{
|
|
19
|
-
readonly isSuccess: boolean;
|
|
20
|
-
readonly data?: unknown;
|
|
21
|
-
readonly error?: unknown;
|
|
22
|
-
}>;
|
|
23
|
-
/** Persists the raw MIME body (file-foundation) and returns its bodyRef
|
|
24
|
-
* for the event. Without this hook, runs in snippet-only mode
|
|
25
|
-
* (bodyRef = ""). */
|
|
26
|
-
readonly storeBody?: (account: MailAccountRecord, msg: RawInboundMessage) => Promise<string>;
|
|
27
|
-
readonly pollIntervalMs?: number;
|
|
28
|
-
readonly backfillWindowDays?: number;
|
|
29
|
-
readonly maxMessagesPerPoll?: number;
|
|
30
|
-
readonly watchBackoffInitialMs?: number;
|
|
31
|
-
readonly watchBackoffMaxMs?: number;
|
|
32
|
-
/** Coordinates the IMAP watch (not the poll) across worker processes:
|
|
33
|
-
* before `plugin.watch()`, ensureWatcher claims a TTL lease for the
|
|
34
|
-
* account via `lock.acquire` and renews it via `lock.renew` while the
|
|
35
|
-
* watcher lives. Omit for single-process deployments — every active
|
|
36
|
-
* account is watched locally, same as before. */
|
|
37
|
-
readonly lock?: DistributedLock;
|
|
38
|
-
/** Access-token lifecycle for OAuth accounts. Defaults to a manager built
|
|
39
|
-
* from `db` + `providerCtx.secrets`; pass the instance shared with
|
|
40
|
-
* `createInboundMailConnectRoutes` so a fresh connect primes this cache. */
|
|
41
|
-
readonly oauthTokens?: OAuthAccessTokenManager;
|
|
42
|
-
/** TTL (seconds) for the per-account watch lease. Default 90s, renewed
|
|
43
|
-
* every ttl/3. Only used when `lock` is set. */
|
|
44
|
-
readonly watchLeaseTtlSeconds?: number;
|
|
45
|
-
readonly log?: (line: string) => void;
|
|
46
|
-
};
|
|
47
|
-
export type InboundMailSupervisor = {
|
|
48
|
-
readonly start: () => Promise<void>;
|
|
49
|
-
/** Reconciliation run across all active accounts; also usable standalone
|
|
50
|
-
* for tests and manual operational triggers. */
|
|
51
|
-
readonly pollOnce: () => Promise<void>;
|
|
52
|
-
readonly stop: () => Promise<void>;
|
|
53
|
-
};
|
|
1
|
+
import type { InboundMailSupervisor, InboundMailSupervisorDeps } from "./watch-supervisor-types.ts";
|
|
54
2
|
export declare function createInboundMailSupervisor(deps: InboundMailSupervisorDeps): InboundMailSupervisor;
|