@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.388.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 (643) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/agent-tools/tool-dispatch.d.ts +7 -7
  4. package/dist/agent-tools/tool-dispatch.js +9 -9
  5. package/dist/audit/handlers/audit-events.js +1 -1
  6. package/dist/audit/screens.js +1 -1
  7. package/dist/auth-email-password/feature.js +1 -1
  8. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  9. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  10. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  11. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  12. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  13. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  14. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  15. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  16. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  17. package/dist/auth-email-password/handlers/login.write.js +1 -1
  18. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  19. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  20. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  21. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  22. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  23. package/dist/auth-email-password/index.js +5 -5
  24. package/dist/auth-email-password/lockout-store.js +1 -1
  25. package/dist/auth-email-password/seeding.d.ts +42 -45
  26. package/dist/auth-email-password/seeding.js +51 -53
  27. package/dist/auth-email-password/signup-token-store.js +8 -8
  28. package/dist/auth-email-password/testing.js +3 -3
  29. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  30. package/dist/auth-email-password/web/auth-client.js +36 -37
  31. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  32. package/dist/auth-email-password/web/auth-gate.js +15 -16
  33. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  34. package/dist/auth-email-password/web/client-plugin.js +4 -5
  35. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  36. package/dist/auth-email-password/web/constants.js +3 -3
  37. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  38. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  39. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  40. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  41. package/dist/auth-email-password/web/index.js +5 -5
  42. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  43. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  44. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  45. package/dist/auth-email-password/web/login-screen.js +2 -3
  46. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  47. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  48. package/dist/auth-email-password/web/session.d.ts +10 -9
  49. package/dist/auth-email-password/web/session.js +28 -29
  50. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  51. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  52. package/dist/auth-email-password/web/signup-screen.js +13 -13
  53. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  54. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  55. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  56. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  57. package/dist/auth-email-password/web/user-menu.js +12 -13
  58. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  59. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  60. package/dist/auth-foundation/boot-checks.js +4 -4
  61. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  62. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  63. package/dist/auth-foundation/types.js +2 -2
  64. package/dist/auth-mfa/feature-exports.d.ts +2 -2
  65. package/dist/auth-mfa/feature.js +8 -0
  66. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  67. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  68. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  69. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  70. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  71. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  72. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  73. package/dist/auth-mfa/token-secrets.js +1 -1
  74. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  75. package/dist/auth-mfa/web/client-plugin.js +1 -1
  76. package/dist/auth-mfa/web/i18n.js +8 -4
  77. package/dist/auth-mfa/web/index.js +4 -4
  78. package/dist/auth-mfa/web/mfa-client.js +17 -16
  79. package/dist/auth-mfa/web/mfa-code-or-recovery-field.d.ts +11 -0
  80. package/dist/auth-mfa/web/mfa-code-or-recovery-field.js +12 -0
  81. package/dist/auth-mfa/web/mfa-disable-dialog.js +14 -3
  82. package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +14 -3
  83. package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +10 -5
  84. package/dist/auth-mfa/web/mfa-verify-screen.js +32 -11
  85. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  86. package/dist/billing-foundation/aggregate-id.js +10 -11
  87. package/dist/billing-foundation/checkout-core.d.ts +9 -14
  88. package/dist/billing-foundation/checkout-core.js +24 -39
  89. package/dist/billing-foundation/consumer-protection/confirmation-mail.js +8 -2
  90. package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +1 -0
  91. package/dist/billing-foundation/consumer-protection/consent-gate.js +1 -0
  92. package/dist/billing-foundation/consumer-protection/issue-confirmation.js +9 -3
  93. package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
  94. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +4 -2
  95. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +6 -5
  96. package/dist/billing-foundation/consumer-protection/termination-record.d.ts +5 -1
  97. package/dist/billing-foundation/consumer-protection/termination-record.js +27 -17
  98. package/dist/billing-foundation/consumer-protection/termination-request.js +12 -7
  99. package/dist/billing-foundation/consumer-protection/termination-revoke.js +12 -7
  100. package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
  101. package/dist/billing-foundation/consumer-protection/termination-texts.js +3 -0
  102. package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +5 -2
  103. package/dist/billing-foundation/consumer-protection/withdrawal-period.js +8 -9
  104. package/dist/billing-foundation/entities.js +27 -27
  105. package/dist/billing-foundation/events.d.ts +1 -0
  106. package/dist/billing-foundation/events.js +19 -17
  107. package/dist/billing-foundation/feature.js +45 -44
  108. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  109. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  110. package/dist/billing-foundation/handlers/billing-plans.query.js +35 -5
  111. package/dist/billing-foundation/handlers/create-checkout-session.write.js +19 -17
  112. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  113. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  114. package/dist/billing-foundation/handlers/plan-switch-preview.query.d.ts +13 -0
  115. package/dist/billing-foundation/handlers/plan-switch-preview.query.js +48 -0
  116. package/dist/billing-foundation/handlers/process-event.write.d.ts +6 -0
  117. package/dist/billing-foundation/handlers/process-event.write.js +28 -22
  118. package/dist/billing-foundation/handlers/start-plan-checkout.write.js +32 -5
  119. package/dist/billing-foundation/handlers/switch-plan.write.d.ts +2 -2
  120. package/dist/billing-foundation/handlers/switch-plan.write.js +56 -64
  121. package/dist/billing-foundation/handlers/sync-subscription.write.js +12 -1
  122. package/dist/billing-foundation/i18n.js +22 -0
  123. package/dist/billing-foundation/index.d.ts +1 -1
  124. package/dist/billing-foundation/plan-catalog.d.ts +21 -5
  125. package/dist/billing-foundation/plan-catalog.js +25 -16
  126. package/dist/billing-foundation/plan-switch.d.ts +12 -0
  127. package/dist/billing-foundation/plan-switch.js +60 -0
  128. package/dist/billing-foundation/projection.d.ts +15 -11
  129. package/dist/billing-foundation/projection.js +38 -37
  130. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  131. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  132. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  133. package/dist/billing-foundation/types.d.ts +97 -42
  134. package/dist/billing-foundation/types.js +29 -20
  135. package/dist/billing-foundation/validate-options.js +17 -0
  136. package/dist/billing-foundation/web/billing-plans-panel.js +82 -36
  137. package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +17 -3
  138. package/dist/billing-foundation/web/checkout-consent-dialog.js +14 -10
  139. package/dist/billing-foundation/web/constants.d.ts +4 -0
  140. package/dist/billing-foundation/web/constants.js +4 -0
  141. package/dist/billing-foundation/web/plan-price.d.ts +15 -0
  142. package/dist/billing-foundation/web/plan-price.js +32 -0
  143. package/dist/billing-foundation/web/plan-switch-confirm-dialog.d.ts +15 -0
  144. package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +66 -0
  145. package/dist/cap-counter/aggregate-id.js +8 -9
  146. package/dist/cap-counter/cap-reservation.js +5 -1
  147. package/dist/cap-counter/constants.js +11 -12
  148. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  149. package/dist/cap-counter/enforce-cap.js +49 -49
  150. package/dist/cap-counter/entity.js +29 -29
  151. package/dist/cap-counter/feature.js +34 -35
  152. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  153. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  154. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  155. package/dist/cap-counter/stock-cap-guard.js +8 -2
  156. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  157. package/dist/channel-email/feature.js +1 -1
  158. package/dist/channel-email/smtp-transport.d.ts +18 -17
  159. package/dist/channel-email/smtp-transport.js +24 -21
  160. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  161. package/dist/compliance-profiles/feature.js +4 -4
  162. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  163. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  164. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  165. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  166. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  167. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  168. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  169. package/dist/compliance-profiles/seeding.js +14 -15
  170. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  171. package/dist/compliance-profiles-ops/index.js +2 -2
  172. package/dist/config/handlers/cascade.query.d.ts +5 -0
  173. package/dist/config/handlers/cascade.query.js +4 -3
  174. package/dist/config/handlers/readiness.query.d.ts +4 -4
  175. package/dist/config/handlers/readiness.query.js +1 -1
  176. package/dist/config/handlers/reencrypt.job.js +4 -5
  177. package/dist/config/handlers/set.write.js +4 -4
  178. package/dist/config/handlers/values.query.d.ts +5 -0
  179. package/dist/config/handlers/values.query.js +4 -3
  180. package/dist/config/resolver.js +4 -4
  181. package/dist/config/table.js +10 -10
  182. package/dist/config/write-helpers.d.ts +1 -0
  183. package/dist/config/write-helpers.js +19 -10
  184. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  185. package/dist/crypto-shredding/handlers/forget-subject.write.js +25 -21
  186. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  187. package/dist/custom-fields/aggregate-id.js +16 -17
  188. package/dist/custom-fields/entity.js +49 -47
  189. package/dist/custom-fields/events.js +7 -8
  190. package/dist/custom-fields/feature.d.ts +14 -14
  191. package/dist/custom-fields/feature.js +53 -54
  192. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  193. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  194. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  195. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  196. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  197. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  198. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  199. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  200. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  201. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  202. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  203. package/dist/custom-fields/lib/field-access.js +2 -2
  204. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  205. package/dist/custom-fields/lib/quota.js +1 -1
  206. package/dist/custom-fields/lib/value-schema.js +10 -12
  207. package/dist/custom-fields/run-retention.js +3 -3
  208. package/dist/custom-fields/schemas.js +14 -14
  209. package/dist/custom-fields/web/client-plugin.js +2 -5
  210. package/dist/custom-fields/web/constants.js +2 -2
  211. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  212. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  213. package/dist/custom-fields/wire-for-entity.js +65 -67
  214. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  215. package/dist/data-retention/_internal/parse-override.js +2 -3
  216. package/dist/data-retention/feature.js +11 -18
  217. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  218. package/dist/data-retention/keep-for.d.ts +7 -7
  219. package/dist/data-retention/keep-for.js +15 -15
  220. package/dist/data-retention/override-schema.d.ts +3 -4
  221. package/dist/data-retention/override-schema.js +13 -15
  222. package/dist/data-retention/presets.d.ts +4 -5
  223. package/dist/data-retention/presets.js +18 -23
  224. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  225. package/dist/data-retention/resolver.d.ts +12 -12
  226. package/dist/data-retention/resolver.js +24 -23
  227. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  228. package/dist/data-retention/run-retention-cleanup.js +61 -51
  229. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  230. package/dist/delivery/channel-context.js +6 -3
  231. package/dist/delivery/db/queries/preferences.js +2 -2
  232. package/dist/delivery/delivery-service.js +22 -7
  233. package/dist/delivery/feature.js +2 -2
  234. package/dist/delivery/handlers/log.query.js +1 -1
  235. package/dist/delivery/handlers/preferences.query.d.ts +1 -1
  236. package/dist/delivery/handlers/preferences.query.js +20 -1
  237. package/dist/delivery/handlers/unsubscribe-page-chrome.query.js +1 -1
  238. package/dist/delivery/tables.js +9 -8
  239. package/dist/delivery/unsubscribe-link.d.ts +3 -1
  240. package/dist/delivery/unsubscribe-page-strings.d.ts +1 -0
  241. package/dist/delivery/unsubscribe-page-strings.js +1 -0
  242. package/dist/delivery/unsubscribe-page.d.ts +2 -0
  243. package/dist/delivery/unsubscribe-page.js +5 -0
  244. package/dist/delivery/unsubscribe.js +29 -11
  245. package/dist/document-ingest-foundation/entity.js +4 -4
  246. package/dist/document-ingest-foundation/events.js +2 -2
  247. package/dist/document-ingest-foundation/feature.js +2 -2
  248. package/dist/document-ingest-foundation/pages.js +1 -1
  249. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  250. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  251. package/dist/feature-toggles/feature.js +1 -1
  252. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  253. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  254. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  255. package/dist/feature-toggles/web/constants.js +1 -1
  256. package/dist/file-derivatives/feature.d.ts +1 -1
  257. package/dist/file-derivatives/feature.js +1 -1
  258. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  259. package/dist/file-derivatives/presets.js +1 -1
  260. package/dist/file-foundation/feature.js +6 -6
  261. package/dist/file-foundation/index.d.ts +1 -1
  262. package/dist/file-foundation/index.js +1 -1
  263. package/dist/file-foundation/read-file-ref-content.d.ts +3 -0
  264. package/dist/file-foundation/read-file-ref-content.js +6 -1
  265. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  266. package/dist/file-provider-inmemory/feature.js +16 -16
  267. package/dist/file-provider-s3/env-named-feature.d.ts +0 -2
  268. package/dist/file-provider-s3/feature.js +16 -16
  269. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  270. package/dist/files/feature.js +6 -6
  271. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  272. package/dist/files-tenant-data/hooks.js +24 -26
  273. package/dist/files-tenant-data/index.js +1 -1
  274. package/dist/folders/feature.d.ts +1 -1
  275. package/dist/folders/web/folder-manager.js +2 -2
  276. package/dist/folders/web/tree.js +5 -5
  277. package/dist/form-draft/db/queries/cleanup.js +3 -3
  278. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  279. package/dist/form-draft/decrypt-draft.js +5 -1
  280. package/dist/form-draft/entity.js +3 -3
  281. package/dist/form-draft/feature.js +4 -5
  282. package/dist/form-draft/handlers/discard.write.js +1 -1
  283. package/dist/form-draft/release-file-refs.js +6 -6
  284. package/dist/form-draft/schemas.js +3 -3
  285. package/dist/form-draft/web/constants.js +0 -2
  286. package/dist/host-routing/dispatch.js +11 -20
  287. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  288. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  289. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  290. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  291. package/dist/inbound-mail-foundation/constants.js +30 -33
  292. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  293. package/dist/inbound-mail-foundation/entities.js +47 -48
  294. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  295. package/dist/inbound-mail-foundation/events.js +50 -47
  296. package/dist/inbound-mail-foundation/feature.js +39 -39
  297. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  298. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  299. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  300. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  301. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  302. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  303. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  304. package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +2 -2
  305. package/dist/inbound-mail-foundation/handlers/update-account.write.js +22 -14
  306. package/dist/inbound-mail-foundation/i18n.js +0 -1
  307. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  308. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  309. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  310. package/dist/inbound-mail-foundation/projection.js +31 -29
  311. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  312. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  313. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  314. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  315. package/dist/inbound-mail-foundation/screens.js +0 -3
  316. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  317. package/dist/inbound-mail-foundation/types.d.ts +49 -49
  318. package/dist/inbound-mail-foundation/types.js +21 -21
  319. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  320. package/dist/inbound-mail-foundation/watch-supervisor.js +85 -67
  321. package/dist/inbound-provider-imap/credential-document.js +13 -13
  322. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  323. package/dist/inbound-provider-imap/feature.js +42 -40
  324. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  325. package/dist/inbound-provider-imap/imap-client.js +20 -19
  326. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  327. package/dist/inbound-provider-inmemory/feature.js +19 -19
  328. package/dist/jobs/db/queries/retention.js +2 -2
  329. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  330. package/dist/jobs/events.js +1 -1
  331. package/dist/jobs/feature.d.ts +1 -0
  332. package/dist/jobs/feature.js +13 -10
  333. package/dist/jobs/handlers/detail.query.js +4 -4
  334. package/dist/jobs/handlers/list.query.js +1 -1
  335. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  336. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  337. package/dist/jobs/handlers/retry.write.js +1 -1
  338. package/dist/jobs/handlers/tenant-failures.query.d.ts +1 -1
  339. package/dist/jobs/handlers/tenant-failures.query.js +45 -41
  340. package/dist/jobs/handlers/tenant-runs.query.d.ts +1 -1
  341. package/dist/jobs/handlers/tenant-runs.query.js +54 -50
  342. package/dist/jobs/job-instant.js +1 -1
  343. package/dist/jobs/job-run-logger.js +15 -15
  344. package/dist/jobs/job-run-table.js +3 -3
  345. package/dist/jobs/screens.js +1 -1
  346. package/dist/jobs/tenant-job-failure-table.js +1 -1
  347. package/dist/jobs/tenant-job-run-table.js +1 -1
  348. package/dist/ledger/entity.js +5 -5
  349. package/dist/ledger/feature.js +3 -3
  350. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  351. package/dist/ledger/recurring.js +12 -12
  352. package/dist/ledger/schemas.js +1 -1
  353. package/dist/ledger/web/constants.js +2 -2
  354. package/dist/ledger/web/index.js +7 -7
  355. package/dist/legal-pages/feature.d.ts +4 -4
  356. package/dist/legal-pages/feature.js +25 -26
  357. package/dist/legal-pages/markdown.js +3 -3
  358. package/dist/legal-pages/web/client-plugin.js +23 -24
  359. package/dist/legal-pages/web/index.js +0 -1
  360. package/dist/mail-foundation/feature.d.ts +5 -5
  361. package/dist/mail-foundation/feature.js +27 -25
  362. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  363. package/dist/mail-transport-inmemory/feature.js +27 -28
  364. package/dist/mail-transport-smtp/feature.js +20 -20
  365. package/dist/managed-pages/branding.js +6 -6
  366. package/dist/managed-pages/feature.d.ts +26 -26
  367. package/dist/managed-pages/feature.js +34 -34
  368. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  369. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  370. package/dist/managed-pages/handlers/set.write.js +5 -7
  371. package/dist/managed-pages/screens/page-screens.js +11 -11
  372. package/dist/managed-pages/seeding.js +8 -8
  373. package/dist/managed-pages/table.js +13 -12
  374. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  375. package/dist/managed-pages/web/client-plugin.js +5 -5
  376. package/dist/managed-pages/web/i18n.js +1 -1
  377. package/dist/notes-history/entity.js +4 -4
  378. package/dist/notes-history/feature.d.ts +2 -2
  379. package/dist/notes-history-user-data/hooks.js +1 -1
  380. package/dist/page-render/layout.js +9 -9
  381. package/dist/page-render/markdown.js +11 -11
  382. package/dist/page-render/security-headers.js +7 -6
  383. package/dist/personal-access-tokens/feature.d.ts +1 -1
  384. package/dist/personal-access-tokens/feature.js +9 -5
  385. package/dist/personal-access-tokens/roles.js +2 -2
  386. package/dist/readiness/handlers/status.query.js +3 -3
  387. package/dist/renderer-foundation/api.js +12 -13
  388. package/dist/renderer-foundation/constants.js +2 -2
  389. package/dist/renderer-foundation/feature.js +7 -7
  390. package/dist/renderer-pdf/render-table-pdf.d.ts +1 -1
  391. package/dist/renderer-pdf/render-table-pdf.js +22 -10
  392. package/dist/secrets/feature.js +9 -9
  393. package/dist/secrets/web/constants.js +2 -2
  394. package/dist/seo/feature.js +3 -3
  395. package/dist/sessions/constants.d.ts +1 -1
  396. package/dist/sessions/constants.js +1 -1
  397. package/dist/sessions/feature.d.ts +2 -2
  398. package/dist/sessions/feature.js +12 -8
  399. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  400. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  401. package/dist/sessions/handlers/revoke.write.js +1 -1
  402. package/dist/sessions/schema/user-session.js +4 -4
  403. package/dist/sessions/screens.js +2 -2
  404. package/dist/sessions/session-callbacks.js +2 -2
  405. package/dist/sessions/session-revoked-event.js +2 -2
  406. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  407. package/dist/shared/decrypt-stored-pii.d.ts +1 -0
  408. package/dist/shared/decrypt-stored-pii.js +7 -2
  409. package/dist/shared/encrypt-for-direct-write.js +1 -1
  410. package/dist/shared/index.d.ts +1 -1
  411. package/dist/shared/index.js +1 -1
  412. package/dist/shared/mail-template-body.d.ts +6 -2
  413. package/dist/shared/mail-template-body.js +7 -4
  414. package/dist/shared/map-with-concurrency.js +5 -4
  415. package/dist/shared/parent-visibility.js +2 -2
  416. package/dist/shared/password-hashing.js +1 -1
  417. package/dist/shared/signup-handover.js +1 -2
  418. package/dist/shared/single-use-token-store.js +1 -1
  419. package/dist/step-dispatcher/feature.js +1 -0
  420. package/dist/subscription-dodo/client.d.ts +17 -0
  421. package/dist/subscription-dodo/client.js +31 -0
  422. package/dist/subscription-dodo/constants.d.ts +12 -0
  423. package/dist/subscription-dodo/constants.js +19 -0
  424. package/dist/subscription-dodo/feature.d.ts +37 -0
  425. package/dist/subscription-dodo/feature.js +144 -0
  426. package/dist/subscription-dodo/index.d.ts +2 -0
  427. package/dist/subscription-dodo/index.js +4 -0
  428. package/dist/subscription-dodo/plugin-methods.d.ts +23 -0
  429. package/dist/subscription-dodo/plugin-methods.js +260 -0
  430. package/dist/subscription-dodo/runtime.d.ts +27 -0
  431. package/dist/subscription-dodo/runtime.js +89 -0
  432. package/dist/subscription-dodo/verify-webhook.d.ts +37 -0
  433. package/dist/subscription-dodo/verify-webhook.js +189 -0
  434. package/dist/subscription-mollie/constants.js +15 -17
  435. package/dist/subscription-mollie/feature.d.ts +17 -18
  436. package/dist/subscription-mollie/feature.js +24 -24
  437. package/dist/subscription-mollie/index.js +3 -3
  438. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  439. package/dist/subscription-mollie/plugin-methods.js +15 -14
  440. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  441. package/dist/subscription-mollie/verify-webhook.js +27 -27
  442. package/dist/subscription-stripe/constants.js +4 -6
  443. package/dist/subscription-stripe/feature.d.ts +14 -14
  444. package/dist/subscription-stripe/feature.js +36 -34
  445. package/dist/subscription-stripe/index.js +6 -6
  446. package/dist/subscription-stripe/plugin-methods.js +18 -18
  447. package/dist/subscription-stripe/runtime.d.ts +1 -1
  448. package/dist/subscription-stripe/runtime.js +8 -7
  449. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  450. package/dist/subscription-stripe/verify-webhook.js +59 -61
  451. package/dist/tags/feature.d.ts +3 -3
  452. package/dist/tags/screens.js +1 -1
  453. package/dist/template-resolver/api.d.ts +3 -2
  454. package/dist/template-resolver/api.js +34 -12
  455. package/dist/template-resolver/compile-document-body.js +1 -0
  456. package/dist/template-resolver/feature.js +2 -2
  457. package/dist/template-resolver/handlers/bundle-import.js +3 -3
  458. package/dist/template-resolver/handlers/copy-locale.write.d.ts +5 -1
  459. package/dist/template-resolver/handlers/copy-locale.write.js +22 -7
  460. package/dist/template-resolver/handlers/diff-to-system.query.js +3 -2
  461. package/dist/template-resolver/handlers/document-base.js +3 -2
  462. package/dist/template-resolver/handlers/find-by-id.query.js +8 -7
  463. package/dist/template-resolver/handlers/list.query.js +6 -7
  464. package/dist/template-resolver/handlers/overview.query.d.ts +3 -0
  465. package/dist/template-resolver/handlers/overview.query.js +6 -3
  466. package/dist/template-resolver/handlers/shared.js +2 -2
  467. package/dist/template-resolver/handlers/template-write.js +3 -3
  468. package/dist/template-resolver/handlers/tenant-override-counts.query.js +1 -3
  469. package/dist/template-resolver/handlers/tenant-override-selection.d.ts +2 -1
  470. package/dist/template-resolver/handlers/tenant-overrides.query.js +28 -5
  471. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  472. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  473. package/dist/template-resolver/handlers/usage.query.d.ts +2 -1
  474. package/dist/template-resolver/handlers/usage.query.js +26 -16
  475. package/dist/template-resolver/handlers/validate.query.js +7 -2
  476. package/dist/template-resolver/seeding.js +30 -14
  477. package/dist/template-resolver/store-template-resource.d.ts +1 -0
  478. package/dist/template-resolver/store-template-resource.js +19 -4
  479. package/dist/template-resolver/table.js +10 -11
  480. package/dist/template-resolver/template-delivery-policy.d.ts +0 -5
  481. package/dist/template-resolver/template-delivery-policy.js +0 -6
  482. package/dist/template-resolver/template-meta.js +7 -4
  483. package/dist/template-resolver/template-preview.js +4 -3
  484. package/dist/template-resolver/web/client-plugin.js +2 -2
  485. package/dist/template-resolver/web/constants.d.ts +2 -2
  486. package/dist/template-resolver/web/constants.js +3 -3
  487. package/dist/template-resolver/web/index.d.ts +1 -0
  488. package/dist/template-resolver/web/index.js +1 -0
  489. package/dist/template-resolver/web/mail-layout-constants.d.ts +5 -0
  490. package/dist/template-resolver/web/mail-layout-constants.js +7 -0
  491. package/dist/tenant/feature.js +7 -7
  492. package/dist/tenant/handlers/member-directory.query.d.ts +1 -0
  493. package/dist/tenant/handlers/member-directory.query.js +11 -4
  494. package/dist/tenant/handlers/members.query.js +1 -1
  495. package/dist/tenant/handlers/team-list.query.js +1 -1
  496. package/dist/tenant/handlers/tenant-directory.query.d.ts +1 -0
  497. package/dist/tenant/handlers/tenant-directory.query.js +9 -5
  498. package/dist/tenant/invitation-table.js +37 -40
  499. package/dist/tenant/membership-table.js +3 -3
  500. package/dist/tenant/schema/tenant.js +7 -9
  501. package/dist/tenant/screens.js +1 -1
  502. package/dist/tenant/seeding.d.ts +6 -5
  503. package/dist/tenant/seeding.js +12 -12
  504. package/dist/tenant/testing.js +5 -6
  505. package/dist/tenant/web/constants.js +2 -2
  506. package/dist/tenant-handover/events.js +5 -7
  507. package/dist/tenant-handover/feature.js +1 -1
  508. package/dist/tenant-handover/grant.js +1 -1
  509. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  510. package/dist/tenant-handover/move-entity-graph.js +8 -9
  511. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  512. package/dist/tenant-handover/transfer-graph.js +4 -5
  513. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  514. package/dist/tenant-lifecycle/constants.d.ts +1 -0
  515. package/dist/tenant-lifecycle/constants.js +4 -0
  516. package/dist/tenant-lifecycle/feature.js +1 -1
  517. package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -2
  518. package/dist/tenant-settings/constants.js +1 -1
  519. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  520. package/dist/tenant-settings/tenant-defaults.js +9 -2
  521. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  522. package/dist/tier-engine/aggregate-id.js +15 -16
  523. package/dist/tier-engine/compose-app.d.ts +14 -14
  524. package/dist/tier-engine/compose-app.js +1 -1
  525. package/dist/tier-engine/entity.js +18 -19
  526. package/dist/tier-engine/feature.d.ts +19 -17
  527. package/dist/tier-engine/feature.js +68 -69
  528. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  529. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  530. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +7 -8
  531. package/dist/tier-engine/handlers/set-tenant-tier.write.js +7 -4
  532. package/dist/tier-engine/tier-resolver.js +2 -2
  533. package/dist/tier-engine/trial.js +8 -8
  534. package/dist/tier-engine/web/constants.js +2 -2
  535. package/dist/tier-engine/web/index.js +4 -4
  536. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  537. package/dist/user/handlers/create.write.js +4 -4
  538. package/dist/user/schema/user.d.ts +11 -11
  539. package/dist/user/schema/user.js +45 -44
  540. package/dist/user/seeding.d.ts +15 -15
  541. package/dist/user/seeding.js +28 -28
  542. package/dist/user/testing.js +3 -3
  543. package/dist/user-data-rights/audit-download.d.ts +8 -8
  544. package/dist/user-data-rights/audit-download.js +19 -20
  545. package/dist/user-data-rights/boot-checks.js +1 -1
  546. package/dist/user-data-rights/deletion-token.js +1 -1
  547. package/dist/user-data-rights/feature.d.ts +49 -50
  548. package/dist/user-data-rights/feature.js +54 -53
  549. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  550. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  551. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  552. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  553. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  554. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  555. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  556. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  557. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  558. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  559. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  560. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  561. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  562. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  563. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  564. package/dist/user-data-rights/index.js +8 -10
  565. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  566. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  567. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  568. package/dist/user-data-rights/run-export-jobs.js +130 -237
  569. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  570. package/dist/user-data-rights/run-forget-cleanup.js +65 -83
  571. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  572. package/dist/user-data-rights/run-user-export.js +55 -57
  573. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  574. package/dist/user-data-rights/schema/download-token.js +37 -41
  575. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  576. package/dist/user-data-rights/schema/export-job.js +65 -67
  577. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  578. package/dist/user-data-rights/token-helpers.js +21 -25
  579. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  580. package/dist/user-data-rights/web/client-plugin.js +1 -1
  581. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  582. package/dist/user-data-rights/web/constants.js +1 -1
  583. package/dist/user-data-rights/web/index.js +5 -5
  584. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  585. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  586. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  587. package/dist/user-data-rights/zip-path.d.ts +15 -15
  588. package/dist/user-data-rights/zip-path.js +41 -40
  589. package/dist/user-data-rights-defaults/feature.js +15 -15
  590. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  591. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  592. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  593. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  594. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  595. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  596. package/dist/user-profile/handlers/change-email.write.js +13 -13
  597. package/dist/user-profile/index.js +3 -3
  598. package/dist/user-profile/web/client-plugin.js +1 -1
  599. package/dist/user-profile/web/constants.js +1 -1
  600. package/dist/user-profile/web/profile-screen.js +1 -1
  601. package/dist/waitlist/handlers/export-purge.write.js +2 -1
  602. package/dist/waitlist/handlers/submit.write.js +5 -5
  603. package/dist/waitlist/import.d.ts +1 -0
  604. package/dist/waitlist/import.js +4 -0
  605. package/dist/waitlist/legacy-migrate.js +17 -6
  606. package/dist/waitlist/link-on-signup.js +18 -6
  607. package/dist/waitlist/options.d.ts +3 -0
  608. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  609. package/dist/workflow-runner/aggregate-id.js +1 -1
  610. package/dist/workflow-runner/event-subscriber.js +4 -5
  611. package/dist/workflow-runner/event-trigger.js +4 -17
  612. package/dist/workflow-runner/feature.js +2 -2
  613. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  614. package/dist/workflow-runner/pending-projection.js +6 -7
  615. package/dist/workflow-runner/runner.js +6 -6
  616. package/dist/workflow-runner/tables.js +6 -6
  617. package/dist/workflow-runner/workflow-registry.js +1 -1
  618. package/package.json +20 -10
  619. package/src/agent-tools/changes.json +6 -0
  620. package/src/audit/changes.json +12 -0
  621. package/src/auth-mfa/changes.json +6 -0
  622. package/src/billing-foundation/changes.json +55 -0
  623. package/src/cap-counter/changes.json +18 -0
  624. package/src/channel-email/changes.json +6 -0
  625. package/src/config/changes.json +12 -0
  626. package/src/crypto-shredding/changes.json +6 -0
  627. package/src/delivery/changes.json +30 -0
  628. package/src/form-draft/changes.json +6 -0
  629. package/src/host-routing/changes.json +6 -0
  630. package/src/inbound-mail-foundation/changes.json +18 -0
  631. package/src/jobs/changes.json +13 -0
  632. package/src/mail-foundation/changes.json +6 -0
  633. package/src/renderer-pdf/changes.json +6 -0
  634. package/src/step-dispatcher/changes.json +6 -0
  635. package/src/subscription-dodo/changes.json +14 -0
  636. package/src/subscription-stripe/changes.json +12 -0
  637. package/src/template-resolver/changes.json +48 -0
  638. package/src/tenant/changes.json +6 -0
  639. package/src/tenant-lifecycle/changes.json +6 -0
  640. package/src/tier-engine/changes.json +6 -0
  641. package/src/waitlist/changes.json +18 -0
  642. package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +0 -1
  643. package/dist/billing-foundation/consumer-protection/stored-user-email.js +0 -8
@@ -1,17 +1,16 @@
1
- // createInboundMailSupervisor — der langlebige Sync-Prozess der
2
- // Foundation: startet pro aktivem Account `plugin.watch()` (IMAP IDLE,
3
- // Push in Sekunden) mit Reconnect-Backoff und fährt zusätzlich den
4
- // periodischen Reconciliation-Poll (Default 5 min) über `plugin.fetch()`.
5
- // Dedup im ingest-Handler macht Watch/Poll-Überschneidung idempotent —
6
- // der Poll ist Korrektheits-Anker, watch nur Latenz-Optimierung.
1
+ // createInboundMailSupervisor — the long-lived Foundation sync process:
2
+ // starts `plugin.watch()` (IMAP IDLE, seconds-level push) for each active
3
+ // account with reconnect backoff, and also runs the periodic reconciliation
4
+ // poll (default: 5 min) through `plugin.fetch()`.
5
+ // Deduplication in the ingest handler makes watch/poll overlap idempotent:
6
+ // the poll is the correctness anchor, while watch only reduces latency.
7
7
  //
8
- // **Plan deviation (documented):** the plan had the poll as an `r.job`
9
- // cron trigger. At the time this was written, JobContext had no
10
- // dispatcher (verified against run-export-jobs.ts). It now does
11
- // (`ctx.write`/`ctx.queryAs`, job-runner.ts) — but converting the poll to
12
- // a cron job is a separate migration (job concurrency instead of this
13
- // dispatcher contract), not part of #1719, and stays untouched here. The
14
- // app owner still wires the supervisor in bin/server.ts:
8
+ // **Documented deviation:** the poll was originally intended as an `r.job`
9
+ // cron trigger. JobContext previously had no dispatcher (see
10
+ // run-export-jobs.ts), but now has one (`ctx.write`/`ctx.queryAs`,
11
+ // job-runner.ts). Converting the poll to a cron job is a separate migration
12
+ // because it changes the concurrency model, so this dispatcher contract
13
+ // remains in place. The app owner wires the supervisor in bin/server.ts:
15
14
  //
16
15
  // const supervisor = createInboundMailSupervisor({
17
16
  // providerCtx: { registry: deps.registry, secrets, metricsFor: deps.metricsFor },
@@ -20,29 +19,29 @@
20
19
  // deps.dispatchSystemWrite({ handlerQn, payload, tenantId: tenantId as TenantId }),
21
20
  // // Multi-worker deployments: share one DistributedLock (same Redis,
22
21
  // // same key prefix) across every worker process so only one of them
23
- // // holds the IMAP IDLE connection per account (#1719). Omit `lock`
22
+ // // holds the IMAP IDLE connection per account. Omit `lock`
24
23
  // // for a single-process deployment — every active account gets
25
- // // watched locally, same as before.
24
+ // // watched locally, as before.
26
25
  // lock: createDistributedLock(redis, `${RedisKeys.lock}inbound-mail:watch:`),
27
26
  // });
28
27
  // await supervisor.start();
29
28
  // // shutdown-hook: await supervisor.stop();
30
29
  //
31
- // **IDLE operational risk (plan §7.3):** long-lived sockets in-process.
32
- // Mitigated here via backoff-restart on onError, a clean stop() of every
33
- // watcher on shutdown, and the poll covering every gap.
30
+ // **IDLE operational risk:** long-lived sockets run in-process.
31
+ // Backoff restart on onError, clean shutdown of every watcher, and the poll
32
+ // covering every gap mitigate this risk.
34
33
  //
35
- // **Multi-worker coordination (#1719):** the reconciliation poll stays
36
- // deliberately N-fold — every worker polls every active account, which
37
- // is idempotent and cheap. Only `plugin.watch()` holds a long-lived
38
- // connection, and only one worker may hold it per account. With
39
- // `deps.lock`, `ensureWatcher` claims a TTL lease (`lock.acquire`) for
40
- // the account before connecting; a worker that doesn't get it leaves the
41
- // account to its current holder — the poll still covers it. The holder
42
- // renews the claim via heartbeat (`lock.renew`, every ttl/3) for as long
43
- // as the watcher state lives, including across reconnect backoff, not
44
- // only while the connection is open. Losing the claim (Redis outage, TTL
45
- // exceeded) tears down the local watcher instead of racing a new holder.
34
+ // **Multi-worker coordination:** the reconciliation poll remains deliberately
35
+ // N-fold: every worker polls every active account, which is idempotent and
36
+ // cheap. Only `plugin.watch()` holds a long-lived connection, and only one
37
+ // worker may hold it per account. With `deps.lock`, `ensureWatcher` claims a
38
+ // TTL lease (`lock.acquire`) before connecting; a worker that fails to claim
39
+ // it leaves the account to its current holder, while the poll still covers
40
+ // it. The holder renews the lease via heartbeat (`lock.renew`, every ttl/3)
41
+ // for as long as the watcher state exists, including reconnect backoff, not
42
+ // only while the connection is open. Losing the claim (for example through
43
+ // a Redis outage or expired TTL) tears down the local watcher instead of
44
+ // racing a new holder.
46
45
  import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
47
46
  import { fetchOne, insertOne, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/db";
48
47
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
@@ -64,9 +63,10 @@ const DEFAULT_MAX_MESSAGES_PER_POLL = 200;
64
63
  const DEFAULT_WATCH_BACKOFF_INITIAL_MS = 5_000;
65
64
  const DEFAULT_WATCH_BACKOFF_MAX_MS = 5 * 60 * 1000;
66
65
  const DEFAULT_WATCH_LEASE_TTL_SECONDS = 90;
67
- /** V1: ein Cursor pro Account (eine Mailbox-Inbox). Multi-Folder später
68
- * über weitere scopes ohne Schema-Änderung. */
66
+ /** One cursor per account (one mailbox inbox) for now; multi-folder support
67
+ * can add further scopes later without a schema change. */
69
68
  const CURSOR_SCOPE = "default";
69
+ const SEEN_LOOKUP_CHUNK_SIZE = 1000;
70
70
  export function createInboundMailSupervisor(deps) {
71
71
  const pollIntervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
72
72
  const backfillWindowDays = deps.backfillWindowDays ?? DEFAULT_BACKFILL_WINDOW_DAYS;
@@ -103,8 +103,8 @@ export function createInboundMailSupervisor(deps) {
103
103
  let pollInFlight = null;
104
104
  const watchers = new Map();
105
105
  // ---------------------------------------------------------------
106
- // Account-Snapshot: aktive Accounts aller Tenants, address decrypted
107
- // (Provider arbeiten nie mit Ciphertext).
106
+ // Account snapshot: active accounts of all tenants with the address
107
+ // decrypted (providers never work with ciphertext).
108
108
  // ---------------------------------------------------------------
109
109
  async function listActiveAccounts() {
110
110
  const rows = await selectMany(deps.db, mailAccountsProjectionTable, {
@@ -113,11 +113,20 @@ export function createInboundMailSupervisor(deps) {
113
113
  const piiKms = configuredPiiSubjectKms();
114
114
  const records = [];
115
115
  for (const row of rows) {
116
- const decrypted = piiKms
117
- ? await decryptPiiFieldValues(row, MAIL_ACCOUNT_PII_FIELDS, piiKms, {
118
- requestId: "inbound-mail-foundation:supervisor:list-accounts",
119
- })
120
- : row;
116
+ let decrypted;
117
+ try {
118
+ decrypted = piiKms
119
+ ? await decryptPiiFieldValues(row, MAIL_ACCOUNT_PII_FIELDS, piiKms, {
120
+ requestId: "inbound-mail-foundation:supervisor:list-accounts",
121
+ })
122
+ : row;
123
+ }
124
+ catch (error) {
125
+ // Class name only: the message may carry ciphertext or key details.
126
+ const errorName = error instanceof Error ? error.name : "unknown error";
127
+ log(`inbound-mail: account ${row.id} skipped — address did not decrypt (${errorName})`);
128
+ continue;
129
+ }
121
130
  const decryptedAddress = decrypted["address"];
122
131
  // Falling back to row.address would hand the ciphertext to a provider.
123
132
  // One undecryptable account must not stop polling of every other tenant's accounts.
@@ -154,7 +163,7 @@ export function createInboundMailSupervisor(deps) {
154
163
  return isPlainObject(parsed) ? parsed : null;
155
164
  }
156
165
  catch {
157
- return null; // korrupter Cursor = wie kein Cursor → Backfill, Dedup fängt Dubletten
166
+ return null; // a corrupt cursor counts as none → backfill; dedup catches duplicates
158
167
  }
159
168
  }
160
169
  async function saveCursor(account, cursor) {
@@ -167,7 +176,7 @@ export function createInboundMailSupervisor(deps) {
167
176
  });
168
177
  if (existing) {
169
178
  await updateMany(deps.db, syncCursorTable, { cursor: serialized, updatedAt: now }, { accountId, scope: CURSOR_SCOPE });
170
- // skip: update-Pfad fertig — nicht in den insert-Zweig durchfallen.
179
+ // skip: the update path is complete; do not fall through to the insert branch.
171
180
  return;
172
181
  }
173
182
  await insertOne(deps.db, syncCursorTable, {
@@ -181,12 +190,12 @@ export function createInboundMailSupervisor(deps) {
181
190
  });
182
191
  }
183
192
  async function resetCursor(accountId) {
184
- // Kein deleteMany-Import nötig: leerer Cursor-String parsed zu null
185
- // → nächster fetch läuft als Backfill.
193
+ // No deleteMany import is needed: an empty cursor parses to null, so the
194
+ // next fetch runs as a backfill.
186
195
  await updateMany(deps.db, syncCursorTable, { cursor: "", updatedAt: Temporal.Now.instant().toString() }, { accountId, scope: CURSOR_SCOPE });
187
196
  }
188
197
  // ---------------------------------------------------------------
189
- // Ingest — jede Message durch den Standard-Write-Handler.
198
+ // Ingest: every message goes through the standard write handler.
190
199
  // ---------------------------------------------------------------
191
200
  async function ingestBatch(account, msgs, cursorSnapshot) {
192
201
  for (const msg of msgs) {
@@ -214,9 +223,9 @@ export function createInboundMailSupervisor(deps) {
214
223
  },
215
224
  });
216
225
  if (!result.isSuccess) {
217
- // Einzel-Message-Fehler bricht den Batch: Cursor wird NICHT
218
- // persistiert → nächster Tick re-fetcht ab altem Cursor, Dedup
219
- // überspringt die bereits verarbeiteten.
226
+ // A single-message failure aborts the batch without persisting the cursor.
227
+ // The next tick refetches from the old cursor, and deduplication skips
228
+ // messages that were already processed.
220
229
  throw new Error(`ingest-message failed for account ${account.id}: ${JSON.stringify(result.error ?? {})}`);
221
230
  }
222
231
  }
@@ -229,8 +238,8 @@ export function createInboundMailSupervisor(deps) {
229
238
  });
230
239
  }
231
240
  // ---------------------------------------------------------------
232
- // Fehler-Semantik (Plan §2-Tabelle) — geteilt von Poll und Watch.
233
- // Liefert true wenn der Account weiterlaufen darf.
241
+ // Error semantics, shared by poll and watch. Returns true when the
242
+ // account may keep running.
234
243
  // ---------------------------------------------------------------
235
244
  async function handleSyncError(account, err) {
236
245
  if (isInboundAuthError(err)) {
@@ -241,14 +250,14 @@ export function createInboundMailSupervisor(deps) {
241
250
  }
242
251
  if (isInboundRateLimitError(err)) {
243
252
  log(`inbound-mail: account ${account.id} rate-limited (retryAfter ${err.retryAfterMs}ms)`);
244
- return true; // nächster Tick versucht es erneut
253
+ return true; // The next tick retries it
245
254
  }
246
255
  if (isInboundCursorInvalidError(err)) {
247
256
  log(`inbound-mail: account ${account.id} cursor invalid — full resync in backfill window`);
248
257
  await resetCursor(account.id);
249
258
  return true;
250
259
  }
251
- // Transient/unbekannt: loggen, nächster Tick retried.
260
+ // Transient or unknown error: log it and retry on the next tick.
252
261
  log(`inbound-mail: account ${account.id} sync error: ${describeError(err)}`);
253
262
  return true;
254
263
  }
@@ -259,12 +268,19 @@ export function createInboundMailSupervisor(deps) {
259
268
  return async (providerMessageIds) => {
260
269
  if (providerMessageIds.length === 0)
261
270
  return new Set();
262
- const seen = await selectMany(deps.db, seenMessageTable, {
263
- tenantId: account.tenantId,
264
- accountId: account.id,
265
- providerMessageId: { in: providerMessageIds },
266
- }, { fields: ["providerMessageId"] });
267
- const seenIds = new Set(seen.map((row) => row.providerMessageId));
271
+ // One bind parameter per id: a full-mailbox listing would exceed Postgres' 65535 limit.
272
+ const seenIds = new Set();
273
+ for (let start = 0; start < providerMessageIds.length; start += SEEN_LOOKUP_CHUNK_SIZE) {
274
+ const seen = await selectMany(deps.db, seenMessageTable, {
275
+ tenantId: account.tenantId,
276
+ accountId: account.id,
277
+ providerMessageId: {
278
+ in: providerMessageIds.slice(start, start + SEEN_LOOKUP_CHUNK_SIZE),
279
+ },
280
+ }, { fields: ["providerMessageId"] });
281
+ for (const row of seen)
282
+ seenIds.add(row.providerMessageId);
283
+ }
268
284
  return new Set(providerMessageIds.filter((id) => !seenIds.has(id)));
269
285
  };
270
286
  }
@@ -272,7 +288,8 @@ export function createInboundMailSupervisor(deps) {
272
288
  let cursor = await loadCursor(account.id);
273
289
  let budget = maxMessagesPerPoll;
274
290
  try {
275
- // hasMore-Schleife: Pagination innerhalb eines Ticks bis Budget.
291
+ // hasMore loop: paginate within this tick until the message budget is
292
+ // exhausted.
276
293
  for (;;) {
277
294
  const accessToken = await resolveAccessToken(account, plugin);
278
295
  const result = await plugin.fetch(deps.providerCtx, account, cursor, {
@@ -308,7 +325,7 @@ export function createInboundMailSupervisor(deps) {
308
325
  if (running)
309
326
  await ensureWatcher(account, plugin);
310
327
  }
311
- // Accounts die nicht mehr aktiv sind: Watcher abbauen.
328
+ // Remove watchers for accounts that are no longer active.
312
329
  const activeIds = new Set(accounts.map((a) => a.id));
313
330
  for (const accountId of watchers.keys()) {
314
331
  if (!activeIds.has(accountId))
@@ -316,7 +333,7 @@ export function createInboundMailSupervisor(deps) {
316
333
  }
317
334
  }
318
335
  // ---------------------------------------------------------------
319
- // Watch-Lifecycle mit Backoff-Restart.
336
+ // Watch lifecycle with backoff restart.
320
337
  // ---------------------------------------------------------------
321
338
  // Heartbeat for a held watch lease. Independent of the connection's own
322
339
  // lifecycle — it keeps renewing across reconnect backoff, not just while
@@ -368,7 +385,7 @@ export function createInboundMailSupervisor(deps) {
368
385
  scheduleRenew(account, state, generation);
369
386
  }
370
387
  }
371
- // kumiko-lint-ignore complexity-budget yield-point stale-map check after acquire is intentional (#2460)
388
+ // kumiko-lint-ignore complexity-budget yield-point stale-map check after acquire is intentional
372
389
  async function acquireWatchLease(account, state) {
373
390
  if (!deps.lock || state.lockToken)
374
391
  return "acquired";
@@ -390,11 +407,11 @@ export function createInboundMailSupervisor(deps) {
390
407
  }
391
408
  // kumiko-lint-ignore complexity-budget watch lifecycle (start/stop/restart) stays cohesive
392
409
  async function ensureWatcher(account, plugin) {
393
- // skip: Provider ohne Live-Push — der Reconciliation-Poll deckt den Account ab.
410
+ // skip: provider without live push; the reconciliation poll covers the account.
394
411
  if (!plugin.watch)
395
412
  return;
396
413
  const existing = watchers.get(account.id);
397
- // skip: Watcher läuft bereits, startet gerade, oder Restart ist geplant.
414
+ // skip: the watcher is already running, starting, or scheduled for restart.
398
415
  if (existing?.stop || existing?.restartTimer || existing?.starting)
399
416
  return;
400
417
  const state = existing ?? {
@@ -425,7 +442,8 @@ export function createInboundMailSupervisor(deps) {
425
442
  }
426
443
  const generation = state.generation;
427
444
  const scheduleRestart = (err) => {
428
- // skip: Supervisor gestoppt oder Watcher-Generation gewechselt — Restart wäre ein Zombie.
445
+ // skip: the supervisor stopped or the watcher generation changed; a restart
446
+ // would create a zombie watcher.
429
447
  if (!running || state.generation !== generation)
430
448
  return;
431
449
  state.stop = null;
@@ -464,7 +482,7 @@ export function createInboundMailSupervisor(deps) {
464
482
  }, accessToken !== undefined ? { accessToken } : undefined);
465
483
  if (state.generation !== generation || !running) {
466
484
  await stop();
467
- // skip: stop() kam während des Connects — Watcher wurde sofort wieder abgebaut.
485
+ // skip: stop() ran while connecting; the watcher was torn down right away.
468
486
  return;
469
487
  }
470
488
  state.stop = stop;
@@ -492,7 +510,7 @@ export function createInboundMailSupervisor(deps) {
492
510
  }
493
511
  async function stopWatcher(accountId) {
494
512
  const state = watchers.get(accountId);
495
- // skip: kein Watcher-State für diesen Account — bereits abgebaut.
513
+ // skip: no watcher state for this account; it is already torn down.
496
514
  if (!state)
497
515
  return;
498
516
  state.generation += 1;
@@ -533,7 +551,7 @@ export function createInboundMailSupervisor(deps) {
533
551
  // Lifecycle.
534
552
  // ---------------------------------------------------------------
535
553
  function scheduleNextPoll() {
536
- // skip: Supervisor gestoppt — keinen weiteren Poll-Tick planen.
554
+ // skip: the supervisor is stopped; do not schedule another poll tick.
537
555
  if (!running)
538
556
  return;
539
557
  pollTimer = setTimeout(() => {
@@ -548,7 +566,7 @@ export function createInboundMailSupervisor(deps) {
548
566
  }
549
567
  return {
550
568
  async start() {
551
- // skip: bereits gestartet — start() ist idempotent.
569
+ // skip: already started; start() is idempotent.
552
570
  if (running)
553
571
  return;
554
572
  running = true;
@@ -1,19 +1,19 @@
1
- // Connection-Dokument im per-Account-Secret-Slot
2
- // (inboundCredentialSecretKey(accountId), Plan §4).
1
+ // Connection document stored in the per-account secret slot
2
+ // (inboundCredentialSecretKey(accountId)).
3
3
  //
4
- // **Warum JSON im Secret statt Tenant-Config-Keys:** anders als
5
- // mail-transport-smtp (EIN SMTP pro Tenant) hat Inbound MEHRERE
6
- // Accounts pro Tenant mit verschiedenen Hosts — per-Tenant-Config-Keys
7
- // können das nicht tragen. Host/Port/User sind zusammen mit dem
8
- // Passwort ein zusammengehöriges Verbindungs-Dokument; der Slot ist
9
- // ohnehin encrypted-at-rest.
4
+ // **Why JSON in the secret instead of tenant config keys:** unlike
5
+ // mail-transport-smtp (one SMTP configuration per tenant), inbound mail
6
+ // supports multiple accounts per tenant with different hosts, which
7
+ // per-tenant config keys cannot represent. Host, port, and user belong
8
+ // with the password in one connection document; the slot is encrypted
9
+ // at rest.
10
10
  //
11
- // authMethod des Accounts bestimmt die Interpretation:
11
+ // The account's authMethod determines the interpretation:
12
12
  // password → { host, port, secure, user, password }
13
- // xoauth2 → { host, port, secure, user, accessToken } — V1-Fallback:
14
- // Token-Beschaffung/-Refresh gehört den OAuth-Providern
15
- // (M365/Gmail, Phase 4/5); der imap-Provider konsumiert
16
- // nur einen gültigen Access-Token aus dem Slot.
13
+ // xoauth2 → { host, port, secure, user, accessToken } — V1 fallback:
14
+ // OAuth providers (M365/Gmail) handle token acquisition and
15
+ // refresh; the imap provider only consumes a valid access
16
+ // token from the slot.
17
17
  import * as z from "zod";
18
18
  export const imapCredentialDocumentSchema = z.object({
19
19
  host: z.string().min(1).max(255),
@@ -1,8 +1,8 @@
1
1
  import { type InboundMailProviderPlugin } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
2
2
  export declare const IMAP_PROVIDER_KEY = "imap";
3
3
  export { setImapMailHostLookup } from "./imap-client.ts";
4
- /** Exportiert für den Live-Test (imap-live.integration.test.ts) —
5
- * Apps nutzen das Feature, nie das Plugin direkt. */
4
+ /** Exported for the live test (imap-live.integration.test.ts) —
5
+ * applications use the feature, never the plugin directly. */
6
6
  export declare const imapInboundMailPlugin: InboundMailProviderPlugin;
7
7
  export declare function createInboundProviderImapFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
8
8
  readonly exports: void;
@@ -1,27 +1,27 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // inbound-provider-imap — IMAP-Implementierung der inbound-mail-
4
- // foundation Plugin-API. Deckt den DACH-Long-Tail (IONOS, Telekom,
5
- // Strato, GMX/Web.de, mailbox.org, Hetzner, all-inkl) via Passwort/
6
- // App-Passwort ab — komplett OHNE OAuth. XOAUTH2 als Fallback für
7
- // M365-/Gmail-Konten (Access-Token aus dem Secret-Slot; Token-Refresh
8
- // gehört den OAuth-Providern, Phase 4/5).
3
+ // inbound-provider-imap — IMAP implementation of the inbound-mail-
4
+ // foundation plugin API. Covers the DACH long tail (IONOS, Telekom,
5
+ // Strato, GMX/Web.de, mailbox.org, Hetzner, all-inkl) via password/
6
+ // app-password authentication, without OAuth. XOAUTH2 is available as
7
+ // a fallback for M365/Gmail accounts (access token from the secret slot;
8
+ // token refresh is handled by the OAuth providers).
9
9
  //
10
- // **Was diese Feature liefert:**
11
- // 1. Plugin-Registration via r.useExtension("inboundMailProvider",
10
+ // **What this feature provides:**
11
+ // 1. Plugin registration via r.useExtension("inboundMailProvider",
12
12
  // "imap", { verify, fetch, watch }).
13
- // 2. verify: connect+logout mit typisiertem Fehler-Mapping.
14
- // 3. fetch: inkrementeller Sync über UIDVALIDITY:lastUid-Cursor —
15
- // UIDVALIDITY-Wechsel wirft InboundCursorInvalidError (Foundation
16
- // resettet + resynct im Backfill-Fenster). Erst-Befüllung via
17
- // SEARCH since=backfillWindowDays.
18
- // 4. watch: IMAP IDLE via imapflow — 'exists'-Event → neue UIDs
19
- // fetchen → onMessages; Verbindungs-Tod → onError (Supervisor
20
- // restartet mit Backoff, der Provider reconnected NICHT selbst).
13
+ // 2. verify: connect+logout with typed error mapping.
14
+ // 3. fetch: incremental sync using a UIDVALIDITY:lastUid cursor —
15
+ // a UIDVALIDITY change throws InboundCursorInvalidError (the
16
+ // foundation resets and resyncs within the backfill window). Initial
17
+ // population uses SEARCH since=backfillWindowDays.
18
+ // 4. watch: IMAP IDLE via imapflow — the 'exists' event triggers fetching
19
+ // new UIDs and then onMessages; connection loss triggers onError (the
20
+ // supervisor restarts with backoff; the provider does not reconnect).
21
21
  //
22
- // Credentials: JSON-Dokument im per-Account-Secret-Slot
23
- // (credential-document.ts) — kein Tenant-Config, weil mehrere Accounts
24
- // pro Tenant verschiedene Hosts haben.
22
+ // Credentials: JSON document in the per-account secret slot
23
+ // (credential-document.ts), not tenant configuration, because one tenant
24
+ // can have multiple accounts with different hosts.
25
25
  import { mailAllowedPrivateHostsEnvSchema } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
26
26
  import { INBOUND_MAIL_PROVIDER_EXTENSION, InboundAuthError, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
27
27
  import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
@@ -63,18 +63,18 @@ async function fetchMessages(ctx, account, cursor, opts) {
63
63
  const serverUidValidity = String(mailbox.uidValidity);
64
64
  const parsedCursor = parseImapCursor(cursor);
65
65
  assertUidValidity(parsedCursor, serverUidValidity);
66
- // UID-Menge bestimmen: inkrementell ab lastUid+1, sonst Backfill
67
- // über SEARCH since (Fenster begrenzt die Erst-Befüllung).
66
+ // Determine the UID set: incrementally from lastUid+1, or use a backfill
67
+ // via SEARCH since (the window limits the initial population).
68
68
  let uids;
69
69
  if (parsedCursor) {
70
70
  const found = await client.search({ uid: `${parsedCursor.lastUid + 1}:*` }, { uid: true });
71
- // `N:*`-Gotcha: liegt N über der höchsten UID, liefert IMAP
72
- // trotzdem die letzte Message — rausfiltern.
71
+ // `N:*` gotcha: when N exceeds the highest UID, IMAP still returns the
72
+ // last message, so filter it out.
73
73
  uids = (found || []).filter((uid) => uid > parsedCursor.lastUid);
74
74
  }
75
75
  else {
76
76
  const since = Temporal.Now.instant().subtract({ hours: opts.backfillWindowDays * 24 });
77
- // imapflow-API-Boundary: search() verlangt ein JS-Date.
77
+ // imapflow API boundary: search() requires a JS Date.
78
78
  uids = (await client.search({ since: instantToLegacyDate(since) }, { uid: true })) || [];
79
79
  }
80
80
  uids.sort((a, b) => a - b);
@@ -111,8 +111,8 @@ async function fetchMessages(ctx, account, cursor, opts) {
111
111
  }
112
112
  }
113
113
  // =============================================================================
114
- // watch — IMAP IDLE (imapflow idlet automatisch bei offener Mailbox und
115
- // emittet 'exists' bei neuen Messages).
114
+ // watch — IMAP IDLE (imapflow idles automatically while the mailbox is open
115
+ // and emits 'exists' for new messages).
116
116
  // =============================================================================
117
117
  async function watchMailbox(ctx, account, handlers) {
118
118
  const doc = await readCredentialDocument(ctx, account);
@@ -122,13 +122,14 @@ async function watchMailbox(ctx, account, handlers) {
122
122
  await client.connect();
123
123
  const mailbox = (await client.mailboxOpen(IMAP_MAILBOX));
124
124
  const uidValidity = String(mailbox.uidValidity);
125
- // uidNext = nächste zu vergebende UID — alles ab hier ist "neu".
125
+ // uidNext is the next UID to be assigned, so everything from here is
126
+ // "new".
126
127
  let nextUid = Number(mailbox.uidNext ?? 1);
127
128
  const drainNew = async () => {
128
129
  const messages = [];
129
130
  let maxSeen = nextUid - 1;
130
131
  for await (const msg of client.fetch(`${nextUid}:*`, { uid: true, internalDate: true, source: true }, { uid: true })) {
131
- // `N:*`-Gotcha (siehe fetch): alte letzte Message rausfiltern.
132
+ // `N:*` gotcha (see fetch): filter out the previous last message.
132
133
  if (msg.uid < nextUid || !msg.source)
133
134
  continue;
134
135
  messages.push(await toRawInboundMessage({
@@ -145,7 +146,7 @@ async function watchMailbox(ctx, account, handlers) {
145
146
  await handlers.onMessages(messages);
146
147
  };
147
148
  client.on("exists", () => {
148
- // skip: Watcher gestoppt — exists-Nachzügler ignorieren.
149
+ // skip: ignore delayed exists events after the watcher has stopped.
149
150
  if (stopped)
150
151
  return;
151
152
  void drainNew().catch((err) => {
@@ -154,7 +155,7 @@ async function watchMailbox(ctx, account, handlers) {
154
155
  });
155
156
  });
156
157
  const die = (err) => {
157
- // skip: bereits gestoppt/gestorben — onError nur einmal feuern.
158
+ // skip: already stopped or terminated; fire onError only once.
158
159
  if (stopped)
159
160
  return;
160
161
  stopped = true;
@@ -162,10 +163,10 @@ async function watchMailbox(ctx, account, handlers) {
162
163
  };
163
164
  client.on("error", die);
164
165
  client.on("close", () => die(new Error("connection closed")));
165
- // IDLE-Loop: 'exists' feuert NUR während client.idle() läuft
166
- // (empirisch gegen greenmail verifiziert). Jedes zwischengeschobene
167
- // Kommando (drainNew-fetch) beendet idle() — die Loop re-idlet,
168
- // bis stop() die Verbindung schließt.
166
+ // IDLE loop: 'exists' fires ONLY while client.idle() is running
167
+ // (verified empirically against greenmail). Each intervening command
168
+ // (drainNew-fetch) ends idle(), so the loop re-enters idle() until
169
+ // stop() closes the connection.
169
170
  void (async () => {
170
171
  while (!stopped) {
171
172
  try {
@@ -174,7 +175,8 @@ async function watchMailbox(ctx, account, handlers) {
174
175
  catch (err) {
175
176
  if (!stopped)
176
177
  die(err);
177
- // skip: idle-Loop endet — die() hat den Supervisor informiert (bzw. stop() war die Ursache).
178
+ // skip: the idle loop ends; die() has informed the supervisor (or stop()
179
+ // was the cause).
178
180
  return;
179
181
  }
180
182
  }
@@ -195,8 +197,8 @@ async function watchMailbox(ctx, account, handlers) {
195
197
  // =============================================================================
196
198
  // Plugin + Feature-definition
197
199
  // =============================================================================
198
- /** Exportiert für den Live-Test (imap-live.integration.test.ts) —
199
- * Apps nutzen das Feature, nie das Plugin direkt. */
200
+ /** Exported for the live test (imap-live.integration.test.ts) —
201
+ * applications use the feature, never the plugin directly. */
200
202
  export const imapInboundMailPlugin = {
201
203
  verify: async (ctx, account) => {
202
204
  const doc = await readCredentialDocument(ctx, account);
@@ -213,9 +215,9 @@ export const imapInboundMailPlugin = {
213
215
  },
214
216
  fetch: fetchMessages,
215
217
  watch: watchMailbox,
216
- // Kein oauth-Block: Passwort-Connect läuft über das Credential-
217
- // Formular (connect-account + Secret-Write); XOAUTH2-Token-Flows
218
- // gehören den OAuth-Providern (M365/Gmail).
218
+ // No oauth block: password authentication runs through the credential
219
+ // form (connect-account + Secret-Write); XOAUTH2 token flows belong to
220
+ // the OAuth providers (M365/Gmail).
219
221
  };
220
222
  export function createInboundProviderImapFeature() {
221
223
  return defineFeature(FEATURE_NAME, (r) => {
@@ -13,23 +13,24 @@ export type ImapCursor = {
13
13
  readonly lastUid: number;
14
14
  };
15
15
  export declare function parseImapCursor(cursor: SyncCursorPayload | null): ImapCursor | null;
16
- /** Wirft InboundCursorInvalidError bei UIDVALIDITY-Wechsel — die
17
- * Foundation resettet den Cursor und macht einen Voll-Resync im
18
- * Backfill-Fenster (Dedup fängt Dubletten). */
16
+ /** Throws InboundCursorInvalidError when UIDVALIDITY changes; the
17
+ * foundation resets the cursor and performs a full resync within the
18
+ * backfill window (deduplication catches duplicates). */
19
19
  export declare function assertUidValidity(cursor: ImapCursor | null, serverUidValidity: string): void;
20
- /** References-Chain normalisieren: mailparser liefert string | string[]
21
- * | undefined; fehlt References, trägt In-Reply-To den Thread-Anker. */
20
+ /** Normalizes the References chain: mailparser returns string | string[]
21
+ * | undefined; when References is missing, In-Reply-To provides the thread
22
+ * anchor. */
22
23
  export declare function normalizeReferences(parsed: {
23
24
  references?: string | string[];
24
25
  inReplyTo?: string;
25
26
  }): string[];
26
- /** imapflow liefert internalDate je nach Codepfad als Date ODER string.
27
- * String-Form verwerfen wir bewusst (kein Date-Parsing im Feature-Code,
28
- * no-date-api) — toRawInboundMessage fällt dann auf mailparsers
29
- * Date-Header zurück, der immer als echtes Date kommt. */
27
+ /** imapflow provides internalDate as either a Date or string depending on
28
+ * the code path. The string form is deliberately discarded (no date parsing
29
+ * in feature code, no-date-api); toRawInboundMessage then falls back to the
30
+ * mailparser Date header, which is always a real Date. */
30
31
  export declare function coerceDate(d: Date | string | undefined): Date | undefined;
31
- /** providerMessageId: UID ist nur innerhalb einer UIDVALIDITY eindeutig
32
- * — beides zusammen ist der stabile Idempotency-Anchor. */
32
+ /** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
33
+ * they form the stable idempotency anchor. */
33
34
  export declare function buildProviderMessageId(uidValidity: string, uid: number): string;
34
35
  export declare function toRawInboundMessage(args: {
35
36
  readonly source: Uint8Array;