@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.
Files changed (380) hide show
  1. package/dist/account-security/feature.d.ts +2 -0
  2. package/dist/account-security/feature.js +3 -1
  3. package/dist/audit/event-classification.js +1 -0
  4. package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
  5. package/dist/auth-email-password/handlers/confirm-account-unlock.write.d.ts +1 -1
  6. package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
  7. package/dist/auth-email-password/handlers/invite-accept.write.d.ts +1 -1
  8. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  9. package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
  10. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  11. package/dist/auth-email-password/handlers/logout.write.d.ts +1 -1
  12. package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
  13. package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
  14. package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
  15. package/dist/auth-email-password/handlers/reset-password.write.d.ts +1 -1
  16. package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
  17. package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
  18. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  19. package/dist/auth-email-password/handlers/token-request-handler.d.ts +1 -1
  20. package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
  21. package/dist/auth-email-password/web/auth-client.d.ts +3 -7
  22. package/dist/auth-email-password/web/auth-client.js +3 -24
  23. package/dist/auth-email-password/web/auth-gate.d.ts +2 -4
  24. package/dist/auth-email-password/web/auth-redirect.d.ts +2 -2
  25. package/dist/auth-email-password/web/auth-redirect.js +3 -12
  26. package/dist/auth-email-password/web/index.d.ts +2 -1
  27. package/dist/auth-email-password/web/index.js +1 -0
  28. package/dist/auth-email-password/web/login-failure.d.ts +9 -0
  29. package/dist/auth-email-password/web/login-failure.js +32 -0
  30. package/dist/auth-email-password/web/login-url.d.ts +5 -0
  31. package/dist/auth-email-password/web/login-url.js +13 -0
  32. package/dist/auth-email-password/web/static-login.d.ts +42 -0
  33. package/dist/auth-email-password/web/static-login.js +122 -0
  34. package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
  35. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
  36. package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
  37. package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
  38. package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
  39. package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
  40. package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
  41. package/dist/auth-mfa/web/mfa-client.js +4 -43
  42. package/dist/billing-foundation/checkout-core.d.ts +2 -1
  43. package/dist/billing-foundation/checkout-core.js +2 -11
  44. package/dist/billing-foundation/events.d.ts +1 -0
  45. package/dist/billing-foundation/events.js +2 -0
  46. package/dist/billing-foundation/feature.js +1 -1
  47. package/dist/billing-foundation/handlers/create-checkout-session.write.js +9 -2
  48. package/dist/billing-foundation/handlers/process-payment-event.write.d.ts +1 -0
  49. package/dist/billing-foundation/handlers/process-payment-event.write.js +2 -0
  50. package/dist/billing-foundation/index.d.ts +1 -1
  51. package/dist/billing-foundation/one-off-checkout-gate.d.ts +9 -0
  52. package/dist/billing-foundation/one-off-checkout-gate.js +30 -0
  53. package/dist/billing-foundation/one-off-customer.d.ts +6 -0
  54. package/dist/billing-foundation/one-off-customer.js +12 -0
  55. package/dist/billing-foundation/plan-catalog.js +1 -0
  56. package/dist/billing-foundation/types.d.ts +25 -0
  57. package/dist/billing-foundation/web/billing-plans-panel.js +1 -0
  58. package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +7 -3
  59. package/dist/billing-foundation/web/plan-switch-recurring.d.ts +16 -0
  60. package/dist/billing-foundation/web/plan-switch-recurring.js +10 -0
  61. package/dist/billing-foundation/webhook-handler.js +1 -0
  62. package/dist/cap-overview/handlers/caps-usage.query.js +3 -3
  63. package/dist/cap-overview/types.d.ts +2 -0
  64. package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
  65. package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
  66. package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
  67. package/dist/compliance-profiles/web/compliance-profile-catalog.js +8 -1
  68. package/dist/config/handlers/reset.write.d.ts +1 -1
  69. package/dist/config/handlers/set.write.d.ts +1 -1
  70. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
  71. package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
  72. package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
  73. package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
  74. package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
  75. package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
  76. package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
  77. package/dist/file-foundation/read-file-ref-content.d.ts +2 -0
  78. package/dist/file-foundation/read-file-ref-content.js +9 -3
  79. package/dist/form-draft/handlers/discard.write.d.ts +1 -1
  80. package/dist/form-draft/handlers/save.write.d.ts +1 -1
  81. package/dist/inbound-mail-foundation/account-health.d.ts +17 -0
  82. package/dist/inbound-mail-foundation/account-health.js +101 -0
  83. package/dist/inbound-mail-foundation/account-poll-schedule.d.ts +19 -0
  84. package/dist/inbound-mail-foundation/account-poll-schedule.js +44 -0
  85. package/dist/inbound-mail-foundation/account-poll.d.ts +24 -0
  86. package/dist/inbound-mail-foundation/account-poll.js +157 -0
  87. package/dist/inbound-mail-foundation/account-record.d.ts +1 -0
  88. package/dist/inbound-mail-foundation/account-record.js +1 -0
  89. package/dist/inbound-mail-foundation/account-wake.d.ts +3 -0
  90. package/dist/inbound-mail-foundation/account-wake.js +17 -0
  91. package/dist/inbound-mail-foundation/connect-callback-verify.d.ts +10 -0
  92. package/dist/inbound-mail-foundation/connect-callback-verify.js +31 -0
  93. package/dist/inbound-mail-foundation/connect-route-responses.d.ts +13 -0
  94. package/dist/inbound-mail-foundation/connect-route-responses.js +16 -0
  95. package/dist/inbound-mail-foundation/connect-routes.js +52 -33
  96. package/dist/inbound-mail-foundation/constants.d.ts +50 -2
  97. package/dist/inbound-mail-foundation/constants.js +53 -3
  98. package/dist/inbound-mail-foundation/content-refetch.d.ts +14 -0
  99. package/dist/inbound-mail-foundation/content-refetch.js +93 -0
  100. package/dist/inbound-mail-foundation/describe-error.d.ts +1 -0
  101. package/dist/inbound-mail-foundation/describe-error.js +5 -0
  102. package/dist/inbound-mail-foundation/entities.d.ts +26 -0
  103. package/dist/inbound-mail-foundation/entities.js +43 -3
  104. package/dist/inbound-mail-foundation/events.d.ts +97 -0
  105. package/dist/inbound-mail-foundation/events.js +57 -2
  106. package/dist/inbound-mail-foundation/feature.d.ts +5 -2
  107. package/dist/inbound-mail-foundation/feature.js +122 -106
  108. package/dist/inbound-mail-foundation/file-storage-failure.d.ts +8 -0
  109. package/dist/inbound-mail-foundation/file-storage-failure.js +19 -0
  110. package/dist/inbound-mail-foundation/handlers/account-address.d.ts +16 -0
  111. package/dist/inbound-mail-foundation/handlers/account-address.js +51 -0
  112. package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.d.ts +8 -0
  113. package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.js +39 -0
  114. package/dist/inbound-mail-foundation/handlers/attach-message-content.write.d.ts +60 -0
  115. package/dist/inbound-mail-foundation/handlers/attach-message-content.write.js +128 -0
  116. package/dist/inbound-mail-foundation/handlers/connect-account.write.d.ts +3 -2
  117. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +97 -56
  118. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.d.ts +2 -1
  119. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +55 -42
  120. package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.d.ts +26 -0
  121. package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.js +131 -0
  122. package/dist/inbound-mail-foundation/handlers/ingest-message-schema.d.ts +64 -0
  123. package/dist/inbound-mail-foundation/handlers/ingest-message-schema.js +39 -0
  124. package/dist/inbound-mail-foundation/handlers/ingest-message.write.d.ts +74 -21
  125. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +57 -134
  126. package/dist/inbound-mail-foundation/handlers/list-accounts.query.d.ts +2 -1
  127. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +60 -26
  128. package/dist/inbound-mail-foundation/handlers/list-messages.query.d.ts +2 -1
  129. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +43 -29
  130. package/dist/inbound-mail-foundation/handlers/list-quarantine.query.d.ts +3 -0
  131. package/dist/inbound-mail-foundation/handlers/list-quarantine.query.js +75 -0
  132. package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.d.ts +7 -0
  133. package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.js +38 -0
  134. package/dist/inbound-mail-foundation/handlers/message-content.d.ts +70 -0
  135. package/dist/inbound-mail-foundation/handlers/message-content.js +137 -0
  136. package/dist/inbound-mail-foundation/handlers/message-content.query.d.ts +19 -0
  137. package/dist/inbound-mail-foundation/handlers/message-content.query.js +59 -0
  138. package/dist/inbound-mail-foundation/handlers/message-detail.query.d.ts +3 -0
  139. package/dist/inbound-mail-foundation/handlers/message-detail.query.js +23 -0
  140. package/dist/inbound-mail-foundation/handlers/reactivate-account.write.d.ts +8 -0
  141. package/dist/inbound-mail-foundation/handlers/reactivate-account.write.js +84 -0
  142. package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.d.ts +8 -0
  143. package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.js +34 -0
  144. package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +10 -2
  145. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +27 -8
  146. package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.d.ts +13 -0
  147. package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.js +54 -0
  148. package/dist/inbound-mail-foundation/handlers/thread-rollup.d.ts +24 -0
  149. package/dist/inbound-mail-foundation/handlers/thread-rollup.js +98 -0
  150. package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.d.ts +3 -0
  151. package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.js +3 -0
  152. package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +13 -3
  153. package/dist/inbound-mail-foundation/handlers/update-account.write.js +62 -46
  154. package/dist/inbound-mail-foundation/i18n.js +72 -2
  155. package/dist/inbound-mail-foundation/inbound-oauth-flow.d.ts +43 -0
  156. package/dist/inbound-mail-foundation/inbound-oauth-flow.js +1 -0
  157. package/dist/inbound-mail-foundation/index.d.ts +19 -6
  158. package/dist/inbound-mail-foundation/index.js +17 -6
  159. package/dist/inbound-mail-foundation/ingest-failures.d.ts +77 -0
  160. package/dist/inbound-mail-foundation/ingest-failures.js +79 -0
  161. package/dist/inbound-mail-foundation/ingest-payload.d.ts +7 -0
  162. package/dist/inbound-mail-foundation/ingest-payload.js +34 -0
  163. package/dist/inbound-mail-foundation/mail-roles.d.ts +21 -0
  164. package/dist/inbound-mail-foundation/mail-roles.js +83 -0
  165. package/dist/inbound-mail-foundation/normalize-inbound-message.d.ts +17 -0
  166. package/dist/inbound-mail-foundation/normalize-inbound-message.js +90 -0
  167. package/dist/inbound-mail-foundation/oauth-access-token.d.ts +3 -1
  168. package/dist/inbound-mail-foundation/oauth-access-token.js +13 -2
  169. package/dist/inbound-mail-foundation/outbound-attachment-access.d.ts +5 -0
  170. package/dist/inbound-mail-foundation/outbound-attachment-access.js +16 -0
  171. package/dist/inbound-mail-foundation/outbound-attachments.d.ts +18 -0
  172. package/dist/inbound-mail-foundation/outbound-attachments.js +77 -0
  173. package/dist/inbound-mail-foundation/outbound-mail.d.ts +15 -1
  174. package/dist/inbound-mail-foundation/outbound-mail.js +4 -0
  175. package/dist/inbound-mail-foundation/probe.js +1 -1
  176. package/dist/inbound-mail-foundation/projection.d.ts +28 -0
  177. package/dist/inbound-mail-foundation/projection.js +25 -3
  178. package/dist/inbound-mail-foundation/provider-errors.d.ts +28 -0
  179. package/dist/inbound-mail-foundation/provider-errors.js +66 -0
  180. package/dist/inbound-mail-foundation/quarantine-entities.d.ts +61 -0
  181. package/dist/inbound-mail-foundation/quarantine-entities.js +47 -0
  182. package/dist/inbound-mail-foundation/quarantine-header-import.d.ts +9 -0
  183. package/dist/inbound-mail-foundation/quarantine-header-import.js +53 -0
  184. package/dist/inbound-mail-foundation/quarantine-retry.d.ts +13 -0
  185. package/dist/inbound-mail-foundation/quarantine-retry.js +97 -0
  186. package/dist/inbound-mail-foundation/quarantine-screens.d.ts +4 -0
  187. package/dist/inbound-mail-foundation/quarantine-screens.js +57 -0
  188. package/dist/inbound-mail-foundation/quarantine.d.ts +13 -0
  189. package/dist/inbound-mail-foundation/quarantine.js +46 -0
  190. package/dist/inbound-mail-foundation/retention-job.d.ts +2 -0
  191. package/dist/inbound-mail-foundation/retention-job.js +62 -0
  192. package/dist/inbound-mail-foundation/retention-sweep.d.ts +4 -0
  193. package/dist/inbound-mail-foundation/retention-sweep.js +35 -8
  194. package/dist/inbound-mail-foundation/screens.d.ts +14 -2
  195. package/dist/inbound-mail-foundation/screens.js +217 -79
  196. package/dist/inbound-mail-foundation/send-from-account.d.ts +11 -1
  197. package/dist/inbound-mail-foundation/send-from-account.js +19 -2
  198. package/dist/inbound-mail-foundation/sender-auth.d.ts +63 -0
  199. package/dist/inbound-mail-foundation/sender-auth.js +198 -0
  200. package/dist/inbound-mail-foundation/supervisor-ingest.d.ts +43 -0
  201. package/dist/inbound-mail-foundation/supervisor-ingest.js +195 -0
  202. package/dist/inbound-mail-foundation/sync-account-now.d.ts +22 -0
  203. package/dist/inbound-mail-foundation/sync-account-now.js +29 -0
  204. package/dist/inbound-mail-foundation/sync-cursor-store.d.ts +9 -0
  205. package/dist/inbound-mail-foundation/sync-cursor-store.js +54 -0
  206. package/dist/inbound-mail-foundation/syncable-accounts.d.ts +16 -0
  207. package/dist/inbound-mail-foundation/syncable-accounts.js +79 -0
  208. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +5 -1
  209. package/dist/inbound-mail-foundation/types.d.ts +61 -62
  210. package/dist/inbound-mail-foundation/types.js +0 -54
  211. package/dist/inbound-mail-foundation/wake-consumer.d.ts +2 -0
  212. package/dist/inbound-mail-foundation/wake-consumer.js +30 -0
  213. package/dist/inbound-mail-foundation/watch-catch-up.d.ts +19 -0
  214. package/dist/inbound-mail-foundation/watch-catch-up.js +33 -0
  215. package/dist/inbound-mail-foundation/watch-lease.d.ts +15 -0
  216. package/dist/inbound-mail-foundation/watch-lease.js +81 -0
  217. package/dist/inbound-mail-foundation/watch-supervisor-types.d.ts +83 -0
  218. package/dist/inbound-mail-foundation/watch-supervisor-types.js +1 -0
  219. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +1 -53
  220. package/dist/inbound-mail-foundation/watch-supervisor.js +123 -290
  221. package/dist/inbound-mail-foundation/web/client-plugin.d.ts +14 -0
  222. package/dist/inbound-mail-foundation/web/client-plugin.js +40 -0
  223. package/dist/inbound-mail-foundation/web/constants.d.ts +5 -0
  224. package/dist/inbound-mail-foundation/web/constants.js +6 -0
  225. package/dist/inbound-mail-foundation/web/index.d.ts +1 -0
  226. package/dist/inbound-mail-foundation/web/index.js +1 -0
  227. package/dist/inbound-provider-imap/connect-mailbox.d.ts +28 -5
  228. package/dist/inbound-provider-imap/connect-mailbox.js +91 -41
  229. package/dist/inbound-provider-imap/connect-my-mailbox.d.ts +13 -0
  230. package/dist/inbound-provider-imap/connect-my-mailbox.js +25 -0
  231. package/dist/inbound-provider-imap/constants.d.ts +12 -1
  232. package/dist/inbound-provider-imap/constants.js +12 -1
  233. package/dist/inbound-provider-imap/credential-document.js +2 -2
  234. package/dist/inbound-provider-imap/download-batch.d.ts +6 -0
  235. package/dist/inbound-provider-imap/download-batch.js +24 -0
  236. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  237. package/dist/inbound-provider-imap/feature.js +49 -32
  238. package/dist/inbound-provider-imap/fetch-content.d.ts +4 -0
  239. package/dist/inbound-provider-imap/fetch-content.js +68 -0
  240. package/dist/inbound-provider-imap/i18n.js +18 -2
  241. package/dist/inbound-provider-imap/imap-client.d.ts +27 -23
  242. package/dist/inbound-provider-imap/imap-client.js +30 -68
  243. package/dist/inbound-provider-imap/index.d.ts +2 -1
  244. package/dist/inbound-provider-imap/index.js +2 -1
  245. package/dist/inbound-provider-imap/mime-content.d.ts +11 -0
  246. package/dist/inbound-provider-imap/mime-content.js +66 -0
  247. package/dist/inbound-provider-imap/parse-message.d.ts +35 -0
  248. package/dist/inbound-provider-imap/parse-message.js +113 -0
  249. package/dist/inbound-provider-imap/reconnect-account.d.ts +17 -0
  250. package/dist/inbound-provider-imap/reconnect-account.js +18 -0
  251. package/dist/inbound-provider-imap/reconnect-mailbox.d.ts +14 -0
  252. package/dist/inbound-provider-imap/reconnect-mailbox.js +71 -0
  253. package/dist/inbound-provider-imap/reconnect-prefill.query.d.ts +3 -0
  254. package/dist/inbound-provider-imap/reconnect-prefill.query.js +34 -0
  255. package/dist/inbound-provider-imap/screens.d.ts +6 -1
  256. package/dist/inbound-provider-imap/screens.js +174 -41
  257. package/dist/inbound-provider-imap/send-mail.d.ts +2 -2
  258. package/dist/inbound-provider-imap/send-mail.js +8 -1
  259. package/dist/inbound-provider-imap/sender-auth-headers.d.ts +3 -0
  260. package/dist/inbound-provider-imap/sender-auth-headers.js +18 -0
  261. package/dist/inbound-provider-inmemory/feature.d.ts +15 -0
  262. package/dist/inbound-provider-inmemory/feature.js +57 -2
  263. package/dist/inbound-provider-inmemory/index.d.ts +1 -1
  264. package/dist/inbound-provider-inmemory/index.js +1 -1
  265. package/dist/jobs/handlers/consumer.write.d.ts +4 -4
  266. package/dist/jobs/handlers/retry.write.d.ts +1 -1
  267. package/dist/jobs/handlers/trigger.write.d.ts +1 -1
  268. package/dist/managed-pages/handlers/set.write.d.ts +1 -1
  269. package/dist/managed-pages/web/i18n.js +1 -0
  270. package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
  271. package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
  272. package/dist/readiness/handlers/run-probes.write.d.ts +1 -1
  273. package/dist/secrets/handlers/delete.write.d.ts +1 -1
  274. package/dist/secrets/handlers/set.write.d.ts +1 -1
  275. package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
  276. package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
  277. package/dist/sessions/handlers/revoke.write.d.ts +1 -1
  278. package/dist/subscription-paddle/checkout-config.query.d.ts +3 -0
  279. package/dist/subscription-paddle/checkout-config.query.js +14 -0
  280. package/dist/subscription-paddle/checkout-methods.d.ts +6 -0
  281. package/dist/subscription-paddle/checkout-methods.js +85 -0
  282. package/dist/subscription-paddle/checkout-page.d.ts +19 -0
  283. package/dist/subscription-paddle/checkout-page.js +126 -0
  284. package/dist/subscription-paddle/client.d.ts +24 -0
  285. package/dist/subscription-paddle/client.js +60 -0
  286. package/dist/subscription-paddle/constants.d.ts +16 -0
  287. package/dist/subscription-paddle/constants.js +25 -0
  288. package/dist/subscription-paddle/feature.d.ts +49 -0
  289. package/dist/subscription-paddle/feature.js +192 -0
  290. package/dist/subscription-paddle/index.d.ts +2 -0
  291. package/dist/subscription-paddle/index.js +4 -0
  292. package/dist/subscription-paddle/plan-switch-methods.d.ts +6 -0
  293. package/dist/subscription-paddle/plan-switch-methods.js +114 -0
  294. package/dist/subscription-paddle/price-methods.d.ts +15 -0
  295. package/dist/subscription-paddle/price-methods.js +105 -0
  296. package/dist/subscription-paddle/runtime.d.ts +42 -0
  297. package/dist/subscription-paddle/runtime.js +109 -0
  298. package/dist/subscription-paddle/subscription-state.d.ts +34 -0
  299. package/dist/subscription-paddle/subscription-state.js +48 -0
  300. package/dist/subscription-paddle/tenant-binding.d.ts +8 -0
  301. package/dist/subscription-paddle/tenant-binding.js +26 -0
  302. package/dist/subscription-paddle/verify-webhook.d.ts +4 -0
  303. package/dist/subscription-paddle/verify-webhook.js +55 -0
  304. package/dist/subscription-paddle/webhook-events.d.ts +9 -0
  305. package/dist/subscription-paddle/webhook-events.js +124 -0
  306. package/dist/template-resolver/handlers/collection-item.query.js +2 -2
  307. package/dist/template-resolver/handlers/collection-list.query.js +4 -2
  308. package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
  309. package/dist/template-resolver/handlers/collection-shared.d.ts +11 -0
  310. package/dist/template-resolver/handlers/collection-shared.js +16 -0
  311. package/dist/template-resolver/handlers/copy-locale.write.d.ts +1 -1
  312. package/dist/template-resolver/handlers/discard-draft.write.d.ts +2 -2
  313. package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +1 -1
  314. package/dist/template-resolver/handlers/import-bundle.write.d.ts +1 -1
  315. package/dist/template-resolver/handlers/patch-draft.write.d.ts +1 -1
  316. package/dist/template-resolver/handlers/reset-to-system.write.d.ts +1 -1
  317. package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +1 -1
  318. package/dist/template-resolver/handlers/resource-remove.write.d.ts +1 -1
  319. package/dist/template-resolver/handlers/resource-upload.write.d.ts +1 -1
  320. package/dist/template-resolver/handlers/send-test.write.d.ts +1 -1
  321. package/dist/template-resolver/handlers/set.write.d.ts +1 -1
  322. package/dist/template-resolver/handlers/toggle-status.write.d.ts +4 -4
  323. package/dist/template-resolver/handlers/upsert-system.write.d.ts +1 -1
  324. package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +1 -1
  325. package/dist/template-resolver/web/client-plugin.d.ts +4 -0
  326. package/dist/template-resolver/web/client-plugin.js +134 -52
  327. package/dist/template-resolver/web/i18n.js +1 -1
  328. package/dist/tenant/handlers/add-member.write.d.ts +1 -1
  329. package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
  330. package/dist/tenant/handlers/create.write.d.ts +1 -1
  331. package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
  332. package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
  333. package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
  334. package/dist/tenant/handlers/update.write.d.ts +1 -1
  335. package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
  336. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +1 -1
  337. package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
  338. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
  339. package/dist/user/handlers/create.write.d.ts +1 -1
  340. package/dist/user/handlers/update.write.d.ts +1 -1
  341. package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +1 -1
  342. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
  343. package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
  344. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
  345. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
  346. package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
  347. package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
  348. package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
  349. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +2 -1
  350. package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
  351. package/dist/waitlist/handlers/export-purge.write.d.ts +2 -2
  352. package/dist/waitlist/handlers/invite.write.d.ts +1 -1
  353. package/dist/waitlist/handlers/reject.write.d.ts +1 -1
  354. package/dist/waitlist/handlers/submit.write.d.ts +1 -1
  355. package/package.json +33 -17
  356. package/src/account-security/changes.json +6 -0
  357. package/src/auth-email-password/changes.json +6 -0
  358. package/src/billing-foundation/changes.json +30 -0
  359. package/src/cap-overview/changes.json +6 -0
  360. package/src/files/changes.json +18 -0
  361. package/src/inbound-mail-foundation/changes.json +155 -0
  362. package/src/inbound-provider-imap/changes.json +42 -0
  363. package/src/jobs/changes.json +18 -0
  364. package/src/subscription-paddle/changes.json +15 -0
  365. package/src/template-resolver/changes.json +12 -0
  366. package/dist/subscription-dodo/client.d.ts +0 -17
  367. package/dist/subscription-dodo/client.js +0 -31
  368. package/dist/subscription-dodo/constants.d.ts +0 -12
  369. package/dist/subscription-dodo/constants.js +0 -19
  370. package/dist/subscription-dodo/feature.d.ts +0 -37
  371. package/dist/subscription-dodo/feature.js +0 -144
  372. package/dist/subscription-dodo/index.d.ts +0 -2
  373. package/dist/subscription-dodo/index.js +0 -4
  374. package/dist/subscription-dodo/plugin-methods.d.ts +0 -23
  375. package/dist/subscription-dodo/plugin-methods.js +0 -260
  376. package/dist/subscription-dodo/runtime.d.ts +0 -27
  377. package/dist/subscription-dodo/runtime.js +0 -89
  378. package/dist/subscription-dodo/verify-webhook.d.ts +0 -37
  379. package/dist/subscription-dodo/verify-webhook.js +0 -189
  380. 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 { OutboundMailMessage, OutboundMailSent } from "./outbound-mail.ts";
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 in snippet-only mode. The Foundation persists it through
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<OutboundMailSent>;
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
- readonly onMessages: (msgs: readonly RawInboundMessage[]) => Promise<void>;
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,2 @@
1
+ import type { FeatureRegistrar } from "@cosmicdrift/kumiko-framework/engine";
2
+ export declare function registerMailAccountWakeConsumer(r: FeatureRegistrar<"inbound-mail-foundation">): void;
@@ -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
+ };
@@ -1,54 +1,2 @@
1
- import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
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;