@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
@@ -7,10 +7,12 @@ export declare const MAIL_ACCOUNT_UPDATED_EVENT_SHORT: "mail-account-updated";
7
7
  export declare const MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT: "mail-account-disconnected";
8
8
  export declare const INBOUND_MESSAGE_RECEIVED_EVENT_SHORT: "inbound-message-received";
9
9
  export declare const MAIL_THREAD_UPDATED_EVENT_SHORT: "mail-thread-updated";
10
+ export declare const INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_SHORT: "inbound-message-content-fetched";
10
11
  export declare const MAIL_ACCOUNT_CONNECTED_EVENT_QN: "inbound-mail-foundation:event:mail-account-connected";
11
12
  export declare const MAIL_ACCOUNT_UPDATED_EVENT_QN: "inbound-mail-foundation:event:mail-account-updated";
12
13
  export declare const MAIL_ACCOUNT_DISCONNECTED_EVENT_QN: "inbound-mail-foundation:event:mail-account-disconnected";
13
14
  export declare const INBOUND_MESSAGE_RECEIVED_EVENT_QN: "inbound-mail-foundation:event:inbound-message-received";
15
+ export declare const INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_QN: "inbound-mail-foundation:event:inbound-message-content-fetched";
14
16
  export declare const MAIL_THREAD_UPDATED_EVENT_QN: "inbound-mail-foundation:event:mail-thread-updated";
15
17
  export declare const mailAccountEventPayloadSchema: z.ZodObject<{
16
18
  provider: z.ZodString;
@@ -25,9 +27,51 @@ export declare const mailAccountEventPayloadSchema: z.ZodObject<{
25
27
  disconnected: "disconnected";
26
28
  }>;
27
29
  watchState: z.ZodString;
30
+ lastError: z.ZodNullable<z.ZodString>;
31
+ trustedAuthservId: z.ZodNullable<z.ZodString>;
28
32
  }, z.core.$strip>;
29
33
  export type MailAccountEventPayload = z.infer<typeof mailAccountEventPayloadSchema>;
34
+ export declare const INBOUND_CONTENT_STATES: readonly ["complete", "snippet", "unavailable"];
35
+ export type InboundContentState = (typeof INBOUND_CONTENT_STATES)[number];
36
+ /** Why a message has no content: held back by the quarantine (retry possible), no file storage wired, or gone from the server. */
37
+ export declare const INBOUND_CONTENT_UNAVAILABLE_REASONS: readonly ["quarantined", "no_file_storage", "gone_from_server"];
38
+ export type InboundContentUnavailableReason = (typeof INBOUND_CONTENT_UNAVAILABLE_REASONS)[number];
39
+ export declare const skippedAttachmentSchema: z.ZodObject<{
40
+ mimeType: z.ZodString;
41
+ size: z.ZodNumber;
42
+ reason: z.ZodEnum<{
43
+ mail_too_large: "mail_too_large";
44
+ nesting_too_deep: "nesting_too_deep";
45
+ no_file_storage: "no_file_storage";
46
+ rejected: "rejected";
47
+ too_large: "too_large";
48
+ }>;
49
+ }, z.core.$strip>;
30
50
  export declare const inboundMessageEventPayloadSchema: z.ZodObject<{
51
+ bodyText: z.ZodString;
52
+ bodyTextTruncated: z.ZodBoolean;
53
+ attachmentFileIds: z.ZodArray<z.ZodUUID>;
54
+ skippedAttachments: z.ZodArray<z.ZodObject<{
55
+ mimeType: z.ZodString;
56
+ size: z.ZodNumber;
57
+ reason: z.ZodEnum<{
58
+ mail_too_large: "mail_too_large";
59
+ nesting_too_deep: "nesting_too_deep";
60
+ no_file_storage: "no_file_storage";
61
+ rejected: "rejected";
62
+ too_large: "too_large";
63
+ }>;
64
+ }, z.core.$strip>>;
65
+ contentState: z.ZodEnum<{
66
+ complete: "complete";
67
+ snippet: "snippet";
68
+ unavailable: "unavailable";
69
+ }>;
70
+ contentUnavailableReason: z.ZodNullable<z.ZodEnum<{
71
+ gone_from_server: "gone_from_server";
72
+ no_file_storage: "no_file_storage";
73
+ quarantined: "quarantined";
74
+ }>>;
31
75
  accountId: z.ZodUUID;
32
76
  ownerUserId: z.ZodNullable<z.ZodString>;
33
77
  messageIdHeader: z.ZodString;
@@ -40,8 +84,61 @@ export declare const inboundMessageEventPayloadSchema: z.ZodObject<{
40
84
  receivedAtIso: z.ZodString;
41
85
  bodyRef: z.ZodString;
42
86
  scope: z.ZodString;
87
+ senderAuthentication: z.ZodNullable<z.ZodObject<{
88
+ authservId: z.ZodString;
89
+ spf: z.ZodEnum<{
90
+ fail: "fail";
91
+ none: "none";
92
+ pass: "pass";
93
+ unknown: "unknown";
94
+ }>;
95
+ dkim: z.ZodEnum<{
96
+ fail: "fail";
97
+ none: "none";
98
+ pass: "pass";
99
+ unknown: "unknown";
100
+ }>;
101
+ dkimDomains: z.ZodArray<z.ZodString>;
102
+ dmarc: z.ZodEnum<{
103
+ fail: "fail";
104
+ none: "none";
105
+ pass: "pass";
106
+ unknown: "unknown";
107
+ }>;
108
+ fromDomain: z.ZodString;
109
+ }, z.core.$strip>>;
43
110
  }, z.core.$strip>;
44
111
  export type InboundMessageEventPayload = z.infer<typeof inboundMessageEventPayloadSchema>;
112
+ export declare const inboundMessageContentFetchedEventPayloadSchema: z.ZodObject<{
113
+ bodyText: z.ZodString;
114
+ bodyTextTruncated: z.ZodBoolean;
115
+ attachmentFileIds: z.ZodArray<z.ZodUUID>;
116
+ skippedAttachments: z.ZodArray<z.ZodObject<{
117
+ mimeType: z.ZodString;
118
+ size: z.ZodNumber;
119
+ reason: z.ZodEnum<{
120
+ mail_too_large: "mail_too_large";
121
+ nesting_too_deep: "nesting_too_deep";
122
+ no_file_storage: "no_file_storage";
123
+ rejected: "rejected";
124
+ too_large: "too_large";
125
+ }>;
126
+ }, z.core.$strip>>;
127
+ contentState: z.ZodEnum<{
128
+ complete: "complete";
129
+ snippet: "snippet";
130
+ unavailable: "unavailable";
131
+ }>;
132
+ contentUnavailableReason: z.ZodNullable<z.ZodEnum<{
133
+ gone_from_server: "gone_from_server";
134
+ no_file_storage: "no_file_storage";
135
+ quarantined: "quarantined";
136
+ }>>;
137
+ accountId: z.ZodNullable<z.ZodUUID>;
138
+ ownerUserId: z.ZodNullable<z.ZodString>;
139
+ bodyRef: z.ZodString;
140
+ }, z.core.$strip>;
141
+ export type InboundMessageContentFetchedEventPayload = z.infer<typeof inboundMessageContentFetchedEventPayloadSchema>;
45
142
  export declare const mailThreadEventPayloadSchema: z.ZodObject<{
46
143
  threadKey: z.ZodString;
47
144
  subject: z.ZodString;
@@ -21,6 +21,7 @@
21
21
  // (crypto-shredding, the billing-foundation pattern).
22
22
  import * as z from "zod";
23
23
  import { INBOUND_MAIL_FOUNDATION_FEATURE, InboundMailAccountStatuses } from "./constants.js";
24
+ import { senderAuthenticationFieldSchema } from "./sender-auth.js";
24
25
  // Aggregate types for the event store.
25
26
  export const MAIL_ACCOUNT_AGGREGATE_TYPE = "mail-account";
26
27
  export const INBOUND_MESSAGE_AGGREGATE_TYPE = "inbound-message";
@@ -32,10 +33,12 @@ export const MAIL_ACCOUNT_UPDATED_EVENT_SHORT = "mail-account-updated";
32
33
  export const MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT = "mail-account-disconnected";
33
34
  export const INBOUND_MESSAGE_RECEIVED_EVENT_SHORT = "inbound-message-received";
34
35
  export const MAIL_THREAD_UPDATED_EVENT_SHORT = "mail-thread-updated";
36
+ export const INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_SHORT = "inbound-message-content-fetched";
35
37
  export const MAIL_ACCOUNT_CONNECTED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${MAIL_ACCOUNT_CONNECTED_EVENT_SHORT}`;
36
38
  export const MAIL_ACCOUNT_UPDATED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${MAIL_ACCOUNT_UPDATED_EVENT_SHORT}`;
37
39
  export const MAIL_ACCOUNT_DISCONNECTED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT}`;
38
40
  export const INBOUND_MESSAGE_RECEIVED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${INBOUND_MESSAGE_RECEIVED_EVENT_SHORT}`;
41
+ export const INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_SHORT}`;
39
42
  export const MAIL_THREAD_UPDATED_EVENT_QN = `${INBOUND_MAIL_FOUNDATION_FEATURE}:event:${MAIL_THREAD_UPDATED_EVENT_SHORT}`;
40
43
  const accountStatusEnum = z.enum([
41
44
  InboundMailAccountStatuses.active,
@@ -65,7 +68,43 @@ export const mailAccountEventPayloadSchema = z.object({
65
68
  /** Provider-agnostic watch state ("idle", "watching", "backoff:3", ...)
66
69
  * — an operational signal only, not PII. */
67
70
  watchState: z.string().max(100),
71
+ /** Why the mailbox is degraded (InboundMailLastErrors code); null while healthy. A string rather
72
+ * than an enum, like authMethod, so a new code needs no upcaster. */
73
+ lastError: z.string().max(50).nullable(),
74
+ /** authserv-id (lower case) of the mailbox's own server; only an Authentication-Results header
75
+ * with exactly this id is believed (sender-auth.ts). null = not set, no sender verdicts. */
76
+ trustedAuthservId: z.string().max(255).nullable(),
68
77
  });
78
+ export const INBOUND_CONTENT_STATES = ["complete", "snippet", "unavailable"];
79
+ /** Why a message has no content: held back by the quarantine (retry possible), no file storage wired, or gone from the server. */
80
+ export const INBOUND_CONTENT_UNAVAILABLE_REASONS = [
81
+ "quarantined",
82
+ "no_file_storage",
83
+ "gone_from_server",
84
+ ];
85
+ export const skippedAttachmentSchema = z.object({
86
+ mimeType: z.string().max(255),
87
+ size: z.number().int().min(0),
88
+ reason: z.enum([
89
+ "too_large",
90
+ "mail_too_large",
91
+ "rejected",
92
+ "no_file_storage",
93
+ "nesting_too_deep",
94
+ ]),
95
+ });
96
+ // Shared by inbound-message-received (v2+) and inbound-message-content-fetched.
97
+ // bodyText is ciphertext: 32_000 characters become roughly 75 KB, hence the generous max.
98
+ const inboundMessageContentShape = {
99
+ bodyText: z.string().max(200_000),
100
+ bodyTextTruncated: z.boolean(),
101
+ /** file-foundation FileRef ids (plaintext uuids). Attachments outlive the mail: apps turn them
102
+ * into documents, so the retention sweep never deletes them. */
103
+ attachmentFileIds: z.array(z.uuid()).max(50),
104
+ skippedAttachments: z.array(skippedAttachmentSchema).max(200),
105
+ contentState: z.enum(INBOUND_CONTENT_STATES),
106
+ contentUnavailableReason: z.enum(INBOUND_CONTENT_UNAVAILABLE_REASONS).nullable(),
107
+ };
69
108
  // ============================================================================
70
109
  // inbound-message stream — exactly ONE received event per message
71
110
  // ============================================================================
@@ -97,12 +136,28 @@ export const inboundMessageEventPayloadSchema = z.object({
97
136
  /** ISO instant — receipt time reported by the provider (INTERNALDATE or
98
137
  * receivedDateTime), not ingest time. */
99
138
  receivedAtIso: z.string().min(1),
100
- /** file-foundation reference to the raw body (MIME). Empty when the app
101
- * is mounted without body persistence (snippet-only mode). */
139
+ /** file-foundation reference to the original (.eml, or .html for HTML-only mails). Empty for
140
+ * snippet-only mails and when no file storage is available. */
102
141
  bodyRef: z.string().max(500),
103
142
  /** Domain scope hint for downstream business processes — generic
104
143
  * ("inbox", folder name), with NO app-specific semantics. */
105
144
  scope: z.string().max(200),
145
+ /** SPF/DKIM/DMARC as reported by the mailbox's own server; null when there is no trustworthy
146
+ * statement. Not PII. */
147
+ senderAuthentication: senderAuthenticationFieldSchema,
148
+ ...inboundMessageContentShape,
149
+ });
150
+ // ============================================================================
151
+ // Content of a message that was imported as snippet only and re-downloaded later.
152
+ // Same aggregate as the received event; applies as an update of the projection row.
153
+ // ============================================================================
154
+ export const inboundMessageContentFetchedEventPayloadSchema = z.object({
155
+ /** Account and scope of the message, so a subscriber can route the event without loading the
156
+ * stream. Null on events stored before v3: the stream id cannot be reversed to the account. */
157
+ accountId: z.uuid().nullable(),
158
+ ownerUserId: z.string().max(36).nullable(),
159
+ bodyRef: z.string().max(500),
160
+ ...inboundMessageContentShape,
106
161
  });
107
162
  // ============================================================================
108
163
  // mail-thread-Stream — Thread-Rollup pro (tenantId, threadKey)
@@ -1,3 +1,6 @@
1
- export declare function createInboundMailFoundationFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
- readonly exports: void;
1
+ import { type InboundMailRoleOptions } from "./mail-roles.ts";
2
+ export declare function createInboundMailFoundationFeature(options?: InboundMailRoleOptions): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
3
+ readonly exports: {
4
+ roles: import("./mail-roles.ts").InboundMailRoles;
5
+ };
3
6
  };
@@ -1,63 +1,58 @@
1
1
  // kumiko-feature-version: 1
2
- //
3
- // inbound-mail-foundation — Plugin host for inbound e-mail
4
- // (inbox federation). Counterpart to mail-foundation (outbound): separate
5
- // extension points, separate state — architectural model is
6
- // file-foundation (the foundation owns state), not mail-transport.
7
- //
8
- // **Multi-provider from day one** (as with billing-foundation): NO global
9
- // `provider` config key. A tenant can connect IMAP and (later) M365/Gmail
10
- // mailboxes in parallel; the provider is specified per MailAccount.
2
+ // inbound-mail-foundation: plugin host for inbound e-mail (inbox federation), the counterpart to
3
+ // mail-foundation (outbound) with its own extension points and state. Modelled on file-foundation
4
+ // (the foundation owns state), not on mail-transport.
11
5
  //
12
6
  // **What this foundation provides:**
13
- // 1. **Plugin API** for inbound providers via r.extendsRegistrar
14
- // ("inboundMailProvider"): verify/fetch/oauth?/watch? (types.ts).
7
+ // 1. **Plugin API** for providers via r.extendsRegistrar: verify/fetch/oauth?/watch? (types.ts).
15
8
  // 2. **3 event-sourced streams** — mail-account (lifecycle),
16
9
  // inbound-message (exactly ONE received event per message, deterministic
17
10
  // aggregateId ⇒ exactly-once despite at-least-once ingest),
18
- // mail-thread (rollup). Full replayable history for later
19
- // consumers (business processes: ticket, receipt, auto-reply).
20
- // 3. **Inline projections** into read_mail_accounts /
21
- // read_inbound_messages / read_mail_threads (read-your-own-write).
11
+ // mail-thread (rollup), fully replayable for later consumers.
12
+ // 3. **Inline projections** into read_mail_accounts/_inbound_messages/_mail_threads (RYOW).
22
13
  // 4. **Write/query handlers**: connect/update/disconnect-account,
23
14
  // ingest-message (programmatic, SystemAdmin), account:list +
24
- // message:list (PII-decrypted, scope-filtered).
25
- // 5. **createInboundMailConnectRoutes**: OAuth connect + anonymous
26
- // callback (outside /api/*), with HMAC-signed state.
27
- // 6. **createInboundMailSupervisor**: app-wired watch (IDLE)
28
- // supervisor with backoff + reconciliation poll.
15
+ // message:list (PII-decrypted; personal mail only for its owner).
29
16
  //
30
- // **What this foundation does NOT do:**
31
- // - No business semantics (intent, ticket, assignment, read/
32
- // completed) — those belong to the app consumer (for example, via an
33
- // event job on inbound-message-received + its own projection).
34
- // - No body blob in the event store: rawMime → file-foundation via
35
- // the Supervisor-storeBody-Hook; the event carries only bodyRef.
36
- // - No IMAP flag write-back (V1) — inbox status belongs to the consumer.
17
+ // **Not here:** business semantics (intent, ticket, assignment, read/completed) belong to the
18
+ // app consumer, for example an event job on inbound-message-received with its own projection.
37
19
  //
38
- // **PII/GDPR:** address/from/to/cc/subject/snippet are `personal: "tenant"`
39
- // — encrypted BEFORE every event append (the only write path), event log AND
40
- // projections carry ciphertext; tenant-destroy shreds the subject key
41
- // (crypto-shredding, the same pattern as billing-foundation). The destroy
42
- // hook additionally archives all streams + deletes the rows.
20
+ // **PII/GDPR:** address/from/to/cc/subject/snippet are `personal: "tenant"`, encrypted BEFORE every
21
+ // event append (the only write path), so event log AND projections carry ciphertext; tenant-destroy
22
+ // shreds the subject key (crypto-shredding, as in billing-foundation) and its hook additionally
23
+ // archives all streams and deletes the rows.
43
24
  import { defineFeature, EXT_TENANT_DATA } from "@cosmicdrift/kumiko-framework/engine";
44
- import { createFileProviderForTenant, } from "@cosmicdrift/kumiko-framework/files";
45
25
  import { INBOUND_MAIL_FOUNDATION_FEATURE, INBOUND_MAIL_PROVIDER_EXTENSION } from "./constants.js";
46
26
  import { inboundMessageEntity, mailAccountEntity, mailThreadEntity, seenMessageTable, syncCursorTable, } from "./entities.js";
47
- import { INBOUND_MESSAGE_AGGREGATE_TYPE, INBOUND_MESSAGE_RECEIVED_EVENT_QN, INBOUND_MESSAGE_RECEIVED_EVENT_SHORT, inboundMessageEventPayloadSchema, MAIL_ACCOUNT_AGGREGATE_TYPE, MAIL_ACCOUNT_CONNECTED_EVENT_QN, MAIL_ACCOUNT_CONNECTED_EVENT_SHORT, MAIL_ACCOUNT_DISCONNECTED_EVENT_QN, MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT, MAIL_ACCOUNT_UPDATED_EVENT_QN, MAIL_ACCOUNT_UPDATED_EVENT_SHORT, MAIL_THREAD_AGGREGATE_TYPE, MAIL_THREAD_UPDATED_EVENT_QN, MAIL_THREAD_UPDATED_EVENT_SHORT, mailAccountEventPayloadSchema, mailThreadEventPayloadSchema, } from "./events.js";
48
- import { connectAccountHandler } from "./handlers/connect-account.write.js";
49
- import { disconnectAccountHandler } from "./handlers/disconnect-account.write.js";
27
+ import { INBOUND_MESSAGE_AGGREGATE_TYPE, INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_QN, INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_SHORT, INBOUND_MESSAGE_RECEIVED_EVENT_QN, INBOUND_MESSAGE_RECEIVED_EVENT_SHORT, inboundMessageContentFetchedEventPayloadSchema, inboundMessageEventPayloadSchema, MAIL_ACCOUNT_AGGREGATE_TYPE, MAIL_ACCOUNT_CONNECTED_EVENT_QN, MAIL_ACCOUNT_CONNECTED_EVENT_SHORT, MAIL_ACCOUNT_DISCONNECTED_EVENT_QN, MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT, MAIL_ACCOUNT_UPDATED_EVENT_QN, MAIL_ACCOUNT_UPDATED_EVENT_SHORT, MAIL_THREAD_AGGREGATE_TYPE, MAIL_THREAD_UPDATED_EVENT_QN, MAIL_THREAD_UPDATED_EVENT_SHORT, mailAccountEventPayloadSchema, mailThreadEventPayloadSchema, } from "./events.js";
28
+ import { createAcknowledgeQuarantineHandler } from "./handlers/acknowledge-quarantine.write.js";
29
+ import { attachMessageContentHandler } from "./handlers/attach-message-content.write.js";
30
+ import { createConnectAccountHandler } from "./handlers/connect-account.write.js";
31
+ import { createDisconnectAccountHandler } from "./handlers/disconnect-account.write.js";
50
32
  import { ingestMessageHandler } from "./handlers/ingest-message.write.js";
51
- import { listAccountsQuery } from "./handlers/list-accounts.query.js";
52
- import { listMessagesQuery } from "./handlers/list-messages.query.js";
53
- import { updateAccountHandler } from "./handlers/update-account.write.js";
33
+ import { createListAccountsQuery } from "./handlers/list-accounts.query.js";
34
+ import { createListMessagesQuery } from "./handlers/list-messages.query.js";
35
+ import { createListQuarantineQuery } from "./handlers/list-quarantine.query.js";
36
+ import { markCredentialStoredHandler } from "./handlers/mark-credential-stored.write.js";
37
+ import { createMessageContentQuery } from "./handlers/message-content.query.js";
38
+ import { createMessageDetailQuery } from "./handlers/message-detail.query.js";
39
+ import { createReactivateAccountHandler } from "./handlers/reactivate-account.write.js";
40
+ import { createRetryQuarantinedMessageHandler } from "./handlers/retry-quarantined-message.write.js";
41
+ import { createSetTrustedAuthservIdHandler } from "./handlers/set-trusted-authserv-id.write.js";
42
+ import { createUpdateAccountHandler } from "./handlers/update-account.write.js";
54
43
  import { INBOUND_MAIL_FOUNDATION_I18N } from "./i18n.js";
44
+ import { ingestFailureTable } from "./ingest-failures.js";
45
+ import { resolveInboundMailRoles, roleDedupeOptions, } from "./mail-roles.js";
55
46
  import { registerMailboxProbe } from "./probe.js";
56
- import { applyInboundMessageReceived, applyMailAccountConnected, applyMailAccountDisconnected, applyMailAccountUpdated, applyMailThreadUpdated, inboundMessagesProjectionTable, mailAccountsProjectionTable, mailThreadsProjectionTable, } from "./projection.js";
57
- import { runInboundMailRetention } from "./retention-sweep.js";
58
- import { mailAccountEditScreen, mailAccountListScreen } from "./screens.js";
47
+ import { applyInboundMessageContentFetched, applyInboundMessageReceived, applyMailAccountConnected, applyMailAccountDisconnected, applyMailAccountUpdated, applyMailThreadUpdated, inboundMessagesProjectionTable, mailAccountsProjectionTable, mailThreadsProjectionTable, } from "./projection.js";
48
+ import { quarantineTable } from "./quarantine-entities.js";
49
+ import { createMailQuarantineScreen } from "./quarantine-screens.js";
50
+ import { registerInboundMailRetentionJob } from "./retention-job.js";
51
+ import { createMailAccountScreens } from "./screens.js";
59
52
  import { INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON, inboundMessageTenantDestroyHook, mailAccountTenantDestroyHook, mailThreadTenantDestroyHook, } from "./tenant-destroy-hook.js";
60
- export function createInboundMailFoundationFeature() {
53
+ import { registerMailAccountWakeConsumer } from "./wake-consumer.js";
54
+ export function createInboundMailFoundationFeature(options = {}) {
55
+ const roles = resolveInboundMailRoles(options);
61
56
  return defineFeature(INBOUND_MAIL_FOUNDATION_FEATURE, (r) => {
62
57
  r.adoptsBundledLists();
63
58
  r.describe("Plugin host for inbound e-mail (inbox federation) — provider plugins (inbound-provider-imap, later M365 Graph / Gmail REST) register at the `inboundMailProvider` extension point with verify/fetch and optional oauth/watch (live push) and send. `sendMailFromAccount(ctx, { accountId, message })` sends from a connected mailbox through its provider (From = the mailbox address, no fallback to the app sender) and answers typed failures (not configured, login rejected, server unreachable, rejected, invalid message); app write handlers call it, it is no endpoint of its own. The foundation owns three event-sourced streams (mail-account lifecycle, inbound-message with exactly-once ingest via deterministic aggregate ids, mail-thread rollup) and their projections `read_mail_accounts`/`read_inbound_messages`/`read_mail_threads`; PII fields are envelope-encrypted per tenant subject key before every append (crypto-shredding on tenant destroy). Wire `createInboundMailConnectRoutes` (OAuth connect + anonymous callback outside /api) and `createInboundMailSupervisor` (IDLE watch with backoff + reconciliation poll) in bin/server.ts. Consume `inbound-mail-foundation:event:inbound-message-received` from app features to attach business processes.");
@@ -68,27 +63,79 @@ export function createInboundMailFoundationFeature() {
68
63
  });
69
64
  // The EXT_TENANT_DATA hook requires the tenant-lifecycle host.
70
65
  r.requires({ features: ["tenant-lifecycle"] });
71
- // 5 fine-grained domain-events (Payload-Schemas: events.ts).
72
66
  // piiFields: "none" — address/subject/snippet are already ciphertext under the tenant subject key before append (see events.ts).
73
67
  // "displayName" stays plaintext (often the mailbox owner's real name for
74
68
  // personal accounts); encrypting it would break the entity-projection read
75
69
  // path that carries it as `personal: false`.
70
+ // v2: lastError, trustedAuthservId. Defaults are shared references across upcast events, so none of them is mutated.
71
+ const mailAccountMigrations = [
72
+ {
73
+ fromVersion: 1,
74
+ toVersion: 2,
75
+ transform: { default: { lastError: null, trustedAuthservId: null } },
76
+ },
77
+ ];
76
78
  r.defineEvent(MAIL_ACCOUNT_CONNECTED_EVENT_SHORT, mailAccountEventPayloadSchema, {
77
79
  piiFields: "none",
80
+ version: 2,
81
+ migrations: mailAccountMigrations,
78
82
  });
79
83
  r.defineEvent(MAIL_ACCOUNT_UPDATED_EVENT_SHORT, mailAccountEventPayloadSchema, {
80
84
  piiFields: "none",
85
+ version: 2,
86
+ migrations: mailAccountMigrations,
81
87
  });
82
88
  r.defineEvent(MAIL_ACCOUNT_DISCONNECTED_EVENT_SHORT, mailAccountEventPayloadSchema, {
83
89
  piiFields: "none",
90
+ version: 2,
91
+ migrations: mailAccountMigrations,
84
92
  });
93
+ // v1 mails carry the snippet only: bodyText "" and contentState "snippet" let the content
94
+ // refetch find them. v3 adds the reason a message has no content.
85
95
  r.defineEvent(INBOUND_MESSAGE_RECEIVED_EVENT_SHORT, inboundMessageEventPayloadSchema, {
86
96
  piiFields: "none",
97
+ version: 3,
98
+ migrations: [
99
+ {
100
+ fromVersion: 1,
101
+ toVersion: 2,
102
+ transform: {
103
+ default: {
104
+ bodyText: "",
105
+ bodyTextTruncated: false,
106
+ attachmentFileIds: [],
107
+ skippedAttachments: [],
108
+ contentState: "snippet",
109
+ senderAuthentication: null,
110
+ },
111
+ },
112
+ },
113
+ {
114
+ fromVersion: 2,
115
+ toVersion: 3,
116
+ transform: { default: { contentUnavailableReason: null } },
117
+ },
118
+ ],
119
+ });
120
+ r.defineEvent(INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_SHORT, inboundMessageContentFetchedEventPayloadSchema, {
121
+ piiFields: "none",
122
+ version: 3,
123
+ migrations: [
124
+ {
125
+ fromVersion: 1,
126
+ toVersion: 2,
127
+ transform: { default: { contentUnavailableReason: null } },
128
+ },
129
+ {
130
+ fromVersion: 2,
131
+ toVersion: 3,
132
+ transform: { default: { accountId: null, ownerUserId: null } },
133
+ },
134
+ ],
87
135
  });
88
136
  r.defineEvent(MAIL_THREAD_UPDATED_EVENT_SHORT, mailThreadEventPayloadSchema, {
89
137
  piiFields: "none",
90
138
  });
91
- // Inline projections — apply in the same transaction as the append.
92
139
  r.projection({
93
140
  name: "mail-account",
94
141
  source: MAIL_ACCOUNT_AGGREGATE_TYPE,
@@ -107,6 +154,7 @@ export function createInboundMailFoundationFeature() {
107
154
  entity: inboundMessageEntity,
108
155
  apply: {
109
156
  [INBOUND_MESSAGE_RECEIVED_EVENT_QN]: applyInboundMessageReceived,
157
+ [INBOUND_MESSAGE_CONTENT_FETCHED_EVENT_QN]: applyInboundMessageContentFetched,
110
158
  },
111
159
  });
112
160
  r.projection({
@@ -118,6 +166,7 @@ export function createInboundMailFoundationFeature() {
118
166
  [MAIL_THREAD_UPDATED_EVENT_QN]: applyMailThreadUpdated,
119
167
  },
120
168
  });
169
+ registerMailAccountWakeConsumer(r);
121
170
  // Plugin extension point — providers register via
122
171
  // r.useExtension("inboundMailProvider", "<key>", plugin).
123
172
  r.extendsRegistrar(INBOUND_MAIL_PROVIDER_EXTENSION, {
@@ -135,20 +184,32 @@ export function createInboundMailFoundationFeature() {
135
184
  r.storeTable(seenMessageTable, {
136
185
  reason: "read_side.mail_seen_messages_direct_write",
137
186
  });
138
- // Write-Handler:
139
- // - ingest-message: programmatic (Supervisor/Poll, SystemAdmin)
140
- // - connect/update/disconnect-account: Lifecycle
187
+ r.storeTable(quarantineTable, {
188
+ reason: "read_side.mail_quarantine_direct_write",
189
+ });
190
+ r.storeTable(ingestFailureTable, {
191
+ reason: "read_side.mail_ingest_failures_direct_write",
192
+ });
193
+ // ingest-message is programmatic (supervisor/poll, SystemAdmin); the rest is account lifecycle.
141
194
  r.writeHandler(ingestMessageHandler);
142
- r.writeHandler(connectAccountHandler);
143
- r.writeHandler(updateAccountHandler);
144
- r.writeHandler(disconnectAccountHandler);
145
- // List-Queries (PII-decrypted, scope-gefiltert).
146
- r.queryHandler(listAccountsQuery);
147
- r.queryHandler(listMessagesQuery);
148
- // Declarative mailbox admin: list (rename, disconnect) and rename form.
149
- // The app places `mailAccountListScreen` via r.nav in its settings area.
150
- r.screen(mailAccountListScreen);
151
- r.screen(mailAccountEditScreen);
195
+ r.writeHandler(createConnectAccountHandler(roles));
196
+ r.writeHandler(createUpdateAccountHandler(roles));
197
+ r.writeHandler(createDisconnectAccountHandler(roles));
198
+ r.writeHandler(createReactivateAccountHandler(roles));
199
+ r.writeHandler(createSetTrustedAuthservIdHandler(roles));
200
+ r.writeHandler(createAcknowledgeQuarantineHandler(roles));
201
+ r.writeHandler(createRetryQuarantinedMessageHandler(roles));
202
+ r.writeHandler(attachMessageContentHandler);
203
+ r.writeHandler(markCredentialStoredHandler);
204
+ r.queryHandler(createListAccountsQuery(roles));
205
+ r.queryHandler(createListMessagesQuery(roles));
206
+ r.queryHandler(createListQuarantineQuery(roles));
207
+ r.queryHandler(createMessageContentQuery(roles));
208
+ r.queryHandler(createMessageDetailQuery(roles));
209
+ // The app places the mailbox lists via r.nav (admins in settings, users next to their connect flow).
210
+ for (const screen of createMailAccountScreens(roles))
211
+ r.screen(screen);
212
+ r.screen(createMailQuarantineScreen(roles));
152
213
  r.translations({ keys: INBOUND_MAIL_FOUNDATION_I18N });
153
214
  registerMailboxProbe(r);
154
215
  // Entity-specific GDPR destroy hooks — the gdpr-storage boot validator
@@ -165,52 +226,7 @@ export function createInboundMailFoundationFeature() {
165
226
  destroy: mailThreadTenantDestroyHook,
166
227
  escapeHatch: { reason: INBOUND_MAIL_TENANT_DESTROY_ARCHIVE_REASON },
167
228
  });
168
- // Data-Retention — perTenant fan-out (one run per tenant, like
169
- // data-retention:retention-cleanup): runInboundMailRetention's raw query
170
- // helpers need the unfiltered runner, so the handler declares escapeHatch
171
- // and reaches for ctx.db.unsafeRaw(). Without this cron, read_inbound_messages
172
- // + the bodies grow unbounded (GDPR Art. 5).
173
- const INBOUND_MAIL_RETENTION_REASON = "inbound-mail retention runs raw deletes; every statement filters by this run's tenantId";
174
- r.job({
175
- name: "inbound-mail-retention",
176
- trigger: { cron: "0 3 * * *" },
177
- perTenant: true,
178
- concurrency: "skip",
179
- escapeHatch: { reason: INBOUND_MAIL_RETENTION_REASON },
180
- handler: async (_payload, ctx) => {
181
- if (!ctx.registry) {
182
- throw new Error("inbound-mail-retention: ctx.registry required (JobContext incomplete)");
183
- }
184
- const tenantId = ctx.systemUser?.tenantId ?? ctx._tenantId;
185
- if (tenantId === undefined) {
186
- // skip: cron fired without a perTenant fan-out tenant — nothing scoped
187
- return;
188
- }
189
- const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
190
- const retentionDb = ctx.db.unsafeRaw(); // @cast-boundary db-operator — jobs never run inside a DbTx
191
- // Body objects are stored in file-foundation. The provider is lazy and memoized —
192
- // ingest currently writes no bodyRef (the storeBody hook is not wired),
193
- // so the provider is never built. Once storeBody is wired, retention
194
- // also cleans up the bodies.
195
- let providerPromise = null;
196
- const deleteBodyObject = async (bodyRef) => {
197
- if (!providerPromise) {
198
- providerPromise = createFileProviderForTenant({ config: ctx.config, registry: ctx.registry, secrets: ctx.services.secrets }, tenantId);
199
- }
200
- const provider = await providerPromise;
201
- await provider.delete(bodyRef);
202
- };
203
- const report = await runInboundMailRetention({
204
- db: retentionDb,
205
- tenantId,
206
- now: T.Now.instant(),
207
- deleteBodyObject,
208
- });
209
- if (report.bodyObjectErrors > 0) {
210
- // biome-ignore lint/suspicious/noConsole: operator-visibility for failed body deletes
211
- console.warn(`[inbound-mail-foundation:inbound-mail-retention] tenant=${tenantId} bodyObjectErrors=${report.bodyObjectErrors}`);
212
- }
213
- },
214
- });
215
- }, { dedupeOptions: {} });
229
+ registerInboundMailRetentionJob(r);
230
+ return { roles };
231
+ }, { dedupeOptions: roleDedupeOptions(roles) });
216
232
  }
@@ -0,0 +1,8 @@
1
+ import { KumikoError } from "@cosmicdrift/kumiko-framework/errors";
2
+ export declare const FILE_STORAGE_WRITE_FAILED_CODE = "file_storage_write_failed";
3
+ export declare class FileStorageWriteFailedError extends KumikoError {
4
+ readonly code = "file_storage_write_failed";
5
+ readonly httpStatus = 503;
6
+ constructor(cause?: Error);
7
+ }
8
+ export declare function isFileStorageWriteFailure(error: unknown): boolean;
@@ -0,0 +1,19 @@
1
+ import { KumikoError } from "@cosmicdrift/kumiko-framework/errors";
2
+ import { errorCodeOf } from "@cosmicdrift/kumiko-types/type-guards";
3
+ export const FILE_STORAGE_WRITE_FAILED_CODE = "file_storage_write_failed";
4
+ // Own code on purpose: the supervisor treats validation/unprocessable as a poison mail and
5
+ // quarantines it, but a storage outage says nothing about the mail.
6
+ export class FileStorageWriteFailedError extends KumikoError {
7
+ code = FILE_STORAGE_WRITE_FAILED_CODE;
8
+ httpStatus = 503;
9
+ constructor(cause) {
10
+ super({
11
+ message: "inbound mail content could not be written to file storage",
12
+ i18nKey: "errors.internal",
13
+ ...(cause && { cause }),
14
+ });
15
+ }
16
+ }
17
+ export function isFileStorageWriteFailure(error) {
18
+ return errorCodeOf(error) === FILE_STORAGE_WRITE_FAILED_CODE;
19
+ }
@@ -0,0 +1,16 @@
1
+ import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
2
+ export type AddressMatch = {
3
+ readonly id: string;
4
+ readonly provider: string;
5
+ readonly authMethod: string;
6
+ readonly ownerUserId: string | null;
7
+ readonly status: string;
8
+ };
9
+ export declare function normalizeMailAddress(address: string): string;
10
+ export declare function findMailboxByAddress(ctx: Pick<HandlerContext, "db">, tenantId: string, address: string): Promise<AddressMatch | undefined>;
11
+ export type ConnectConflict = "already_connected" | "address_disconnected" | "reopen_in_place";
12
+ export declare function connectConflictOf(existing: AddressMatch, wanted: {
13
+ readonly authMethod: string;
14
+ readonly provider: string;
15
+ readonly ownerUserId: string | null;
16
+ }): ConnectConflict;
@@ -0,0 +1,51 @@
1
+ // Address lookup across the tenant's mailboxes. Addresses are ciphertext in the projection, so the
2
+ // comparison happens in memory after decrypting (a tenant has a handful of mailboxes).
3
+ import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
4
+ import { InboundMailAccountStatuses, InboundMailAuthMethods } from "../constants.js";
5
+ import { MAIL_ACCOUNT_PII_FIELDS } from "../entities.js";
6
+ import { mailAccountsProjectionTable } from "../projection.js";
7
+ export function normalizeMailAddress(address) {
8
+ return address.trim().toLowerCase();
9
+ }
10
+ function textOf(value) {
11
+ return typeof value === "string" ? value : "";
12
+ }
13
+ // A live mailbox wins over a disconnected one: connecting next to a live mailbox is always a duplicate.
14
+ export async function findMailboxByAddress(ctx, tenantId, address) {
15
+ const wanted = normalizeMailAddress(address);
16
+ const rows = await ctx.db.selectMany(mailAccountsProjectionTable, { tenantId });
17
+ const piiKms = configuredPiiSubjectKms();
18
+ const matches = [];
19
+ for (const row of rows) {
20
+ const readable = piiKms
21
+ ? await decryptPiiFieldValues(row, MAIL_ACCOUNT_PII_FIELDS, piiKms, {
22
+ requestId: `inbound-mail-foundation:connect-account:${tenantId}`,
23
+ })
24
+ : row;
25
+ if (normalizeMailAddress(textOf(readable["address"])) !== wanted)
26
+ continue;
27
+ matches.push({
28
+ id: textOf(row["id"]),
29
+ provider: textOf(row["provider"]),
30
+ authMethod: textOf(row["authMethod"]),
31
+ ownerUserId: typeof row["ownerUserId"] === "string" ? row["ownerUserId"] : null,
32
+ status: textOf(row["status"]),
33
+ });
34
+ }
35
+ return matches.find((m) => m.status !== InboundMailAccountStatuses.disconnected) ?? matches[0];
36
+ }
37
+ // A disconnected or sign-in-failed OAuth mailbox of the same provider and owner is reopened (the
38
+ // callback writes the new token into the same slot); everything else must not silently create a second stream for one address.
39
+ export function connectConflictOf(existing, wanted) {
40
+ const disconnected = existing.status === InboundMailAccountStatuses.disconnected;
41
+ // A sign-in error of an OAuth mailbox is healed by signing in again, so it reopens like a disconnect.
42
+ const signInFailed = existing.status === InboundMailAccountStatuses.authError;
43
+ if (!disconnected && !signInFailed)
44
+ return "already_connected";
45
+ const bothOauth = wanted.authMethod === InboundMailAuthMethods.oauth &&
46
+ existing.authMethod === InboundMailAuthMethods.oauth &&
47
+ existing.provider === wanted.provider;
48
+ if (!bothOauth)
49
+ return disconnected ? "address_disconnected" : "already_connected";
50
+ return existing.ownerUserId === wanted.ownerUserId ? "reopen_in_place" : "already_connected";
51
+ }