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