@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,6 +1,6 @@
1
- // imapflow-Wiring + pure Helpers des IMAP-Providers.
2
- // Referenz-Impl: /Users/marc/code/doc-o-mat (HEINZ) — aber inkrementeller
3
- // UIDVALIDITY:lastUid-Cursor statt '1:*'-Vollscan.
1
+ // imapflow wiring and pure helpers for IMAP providers.
2
+ // Reference implementation: /Users/marc/code/doc-o-mat (HEINZ), but uses an
3
+ // incremental UIDVALIDITY:lastUid cursor instead of a '1:*' full scan.
4
4
  import { BlockedHostError, readAllowedPrivateMailHostsFromEnv, resolveMailConnectTarget, } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
5
5
  import { InboundAuthError, InboundCursorInvalidError, InboundTransientError, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
6
6
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
@@ -71,9 +71,9 @@ export async function createImapClient(doc, hostGuard = {}) {
71
71
  }
72
72
  /** Server-Fehler → typisierte Foundation-Fehlerklassen (Plan §2). */
73
73
  export function mapImapError(err, host) {
74
- // imapflow-Fehler tragen die Server-Antwort in responseText, die
75
- // message ist nur "Command failed" — beides in den Match einbeziehen;
76
- // authenticationFailed ist das verlässliche Flag.
74
+ // imapflow errors carry the server response in responseText; the
75
+ // message is only "Command failed", so both are included in the match;
76
+ // authenticationFailed is the reliable flag.
77
77
  const carrier = isPlainObject(err) ? err : undefined;
78
78
  const responseText = typeof carrier?.["responseText"] === "string" ? carrier["responseText"] : "";
79
79
  const msg = `${err instanceof Error ? err.message : String(err)} ${responseText}`.trim();
@@ -95,9 +95,9 @@ export function parseImapCursor(cursor) {
95
95
  return null;
96
96
  return { uidValidity, lastUid };
97
97
  }
98
- /** Wirft InboundCursorInvalidError bei UIDVALIDITY-Wechsel — die
99
- * Foundation resettet den Cursor und macht einen Voll-Resync im
100
- * Backfill-Fenster (Dedup fängt Dubletten). */
98
+ /** Throws InboundCursorInvalidError when UIDVALIDITY changes; the
99
+ * foundation resets the cursor and performs a full resync within the
100
+ * backfill window (deduplication catches duplicates). */
101
101
  export function assertUidValidity(cursor, serverUidValidity) {
102
102
  if (cursor && cursor.uidValidity !== serverUidValidity) {
103
103
  throw new InboundCursorInvalidError(`UIDVALIDITY changed (${cursor.uidValidity} → ${serverUidValidity}) — full resync required`);
@@ -109,8 +109,9 @@ export function assertUidValidity(cursor, serverUidValidity) {
109
109
  function stripAngles(id) {
110
110
  return id.replace(/^<|>$/g, "").trim();
111
111
  }
112
- /** References-Chain normalisieren: mailparser liefert string | string[]
113
- * | undefined; fehlt References, trägt In-Reply-To den Thread-Anker. */
112
+ /** Normalizes the References chain: mailparser returns string | string[]
113
+ * | undefined; when References is missing, In-Reply-To provides the thread
114
+ * anchor. */
114
115
  export function normalizeReferences(parsed) {
115
116
  const raw = parsed.references;
116
117
  const list = raw === undefined ? [] : Array.isArray(raw) ? raw : raw.split(/\s+/);
@@ -128,15 +129,15 @@ function addressList(a) {
128
129
  const arr = Array.isArray(a) ? a : [a];
129
130
  return arr.map((x) => x.text).filter((t) => Boolean(t));
130
131
  }
131
- /** imapflow liefert internalDate je nach Codepfad als Date ODER string.
132
- * String-Form verwerfen wir bewusst (kein Date-Parsing im Feature-Code,
133
- * no-date-api) — toRawInboundMessage fällt dann auf mailparsers
134
- * Date-Header zurück, der immer als echtes Date kommt. */
132
+ /** imapflow provides internalDate as either a Date or string depending on
133
+ * the code path. The string form is deliberately discarded (no date parsing
134
+ * in feature code, no-date-api); toRawInboundMessage then falls back to the
135
+ * mailparser Date header, which is always a real Date. */
135
136
  export function coerceDate(d) {
136
137
  return d instanceof Date ? d : undefined;
137
138
  }
138
- /** providerMessageId: UID ist nur innerhalb einer UIDVALIDITY eindeutig
139
- * — beides zusammen ist der stabile Idempotency-Anchor. */
139
+ /** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
140
+ * they form the stable idempotency anchor. */
140
141
  export function buildProviderMessageId(uidValidity, uid) {
141
142
  return `${uidValidity}:${uid}`;
142
143
  }
@@ -155,8 +156,8 @@ export async function toRawInboundMessage(args) {
155
156
  cc: addressList(parsed.cc),
156
157
  subject: parsed.subject ?? "",
157
158
  snippet: text.slice(0, SNIPPET_MAX),
158
- // Lib-Boundary-Bridge (Date von imapflow/mailparser) → Temporal;
159
- // fehlt jedes Datum, ist Epoch der ehrliche Marker.
159
+ // Lib-boundary bridge (Date from imapflow/mailparser) → Temporal;
160
+ // when no date exists, Epoch is the honest marker.
160
161
  receivedAtIso: (receivedAt
161
162
  ? legacyDateToInstant(receivedAt)
162
163
  : Temporal.Instant.fromEpochMilliseconds(0)).toString(),
@@ -1,18 +1,18 @@
1
1
  import type { InboundMailProviderPlugin, RawInboundMessage } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
2
2
  export declare const INMEMORY_PROVIDER_KEY = "inmemory";
3
- /** Test-Helper: Message ins Postfach legen. Läuft ein watch, wird sie
4
- * sofort gepusht (IDLE-Simulation); der nächste fetch liefert sie
5
- * cursor-basiert ebenfalls — Dedup der Foundation macht das idempotent. */
3
+ /** Test helper: adds a message to the mailbox. If a watch is active, it is
4
+ * pushed immediately (IDLE simulation); the next fetch also returns it by
5
+ * cursor — the foundation's deduplication makes this idempotent. */
6
6
  export declare function seedInboundMessage(accountId: string, msg: RawInboundMessage): Promise<void>;
7
- /** Test-Helper: One-Shot-Fehler für den nächsten fetch (z.B.
8
- * InboundAuthError, InboundCursorInvalidError). */
7
+ /** Test helper: injects a one-shot error into the next fetch (e.g.
8
+ * InboundAuthError or InboundCursorInvalidError). */
9
9
  export declare function failNextFetchWith(accountId: string, err: unknown): void;
10
- /** Test-Helper: One-Shot-Fehler für das nächste verify. */
10
+ /** Test helper: injects a one-shot error into the next verify. */
11
11
  export declare function failNextVerifyWith(accountId: string, err: unknown): void;
12
- /** Test-Helper: Tod der Live-Verbindung simulieren (Supervisor muss
13
- * mit Backoff neu starten). */
12
+ /** Test helper: simulates the live connection terminating (the supervisor
13
+ * must restart with backoff). */
14
14
  export declare function emitWatchError(accountId: string, err: unknown): void;
15
- /** Test-Helper: läuft gerade ein watch für den Account? */
15
+ /** Test helper: reports whether an account currently has an active watch. */
16
16
  export declare function isWatching(accountId: string): boolean;
17
17
  /** Test-Helper: kompletter State-Reset (Test-Isolation — Mock-States
18
18
  * nie zwischen Tests teilen). */
@@ -1,15 +1,15 @@
1
1
  // kumiko-feature-version: 1
2
2
  //
3
- // inbound-provider-inmemory — scriptbarer In-Memory-Provider für die
4
- // inbound-mail-foundation Plugin-API. Für Tests, Demos und Sample-Apps:
5
- // Messages werden per `seedInboundMessage()` eingespeist statt von einem
6
- // echten Postfach gefetcht; `watch()` pusht geseedete Messages sofort
7
- // (IDLE-Simulation), `fetch()` liefert sie cursor-basiert nach
8
- // (Reconciliation-Pfad) — beide Pfade zusammen exercisen exakt die
9
- // Dedup-Garantie der Foundation.
3
+ // inbound-provider-inmemory — scriptable in-memory provider for the
4
+ // inbound-mail-foundation plugin API. For tests, demos, and sample apps:
5
+ // messages are supplied via `seedInboundMessage()` instead of being fetched
6
+ // from a real mailbox; `watch()` immediately pushes seeded messages
7
+ // (IDLE simulation), while `fetch()` returns them by cursor
8
+ // (reconciliation path). Together, both paths exercise the foundation's
9
+ // deduplication guarantee exactly.
10
10
  //
11
- // **Pattern-Vorbild:** mail-transport-inmemory (module-level State +
12
- // Test-Helper-Exports). NICHT für Production.
11
+ // **Pattern basis:** mail-transport-inmemory (module-level state +
12
+ // test-helper exports). Not for production.
13
13
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
14
14
  const FEATURE_NAME = "inbound-provider-inmemory";
15
15
  export const INMEMORY_PROVIDER_KEY = "inmemory";
@@ -22,26 +22,26 @@ function stateFor(accountId) {
22
22
  }
23
23
  return state;
24
24
  }
25
- /** Test-Helper: Message ins Postfach legen. Läuft ein watch, wird sie
26
- * sofort gepusht (IDLE-Simulation); der nächste fetch liefert sie
27
- * cursor-basiert ebenfalls — Dedup der Foundation macht das idempotent. */
25
+ /** Test helper: adds a message to the mailbox. If a watch is active, it is
26
+ * pushed immediately (IDLE simulation); the next fetch also returns it by
27
+ * cursor — the foundation's deduplication makes this idempotent. */
28
28
  export async function seedInboundMessage(accountId, msg) {
29
29
  const state = stateFor(accountId);
30
30
  state.log.push(msg);
31
31
  if (state.watch)
32
32
  await state.watch.onMessages([msg]);
33
33
  }
34
- /** Test-Helper: One-Shot-Fehler für den nächsten fetch (z.B.
35
- * InboundAuthError, InboundCursorInvalidError). */
34
+ /** Test helper: injects a one-shot error into the next fetch (e.g.
35
+ * InboundAuthError or InboundCursorInvalidError). */
36
36
  export function failNextFetchWith(accountId, err) {
37
37
  stateFor(accountId).nextFetchError = err;
38
38
  }
39
- /** Test-Helper: One-Shot-Fehler für das nächste verify. */
39
+ /** Test helper: injects a one-shot error into the next verify. */
40
40
  export function failNextVerifyWith(accountId, err) {
41
41
  stateFor(accountId).nextVerifyError = err;
42
42
  }
43
- /** Test-Helper: Tod der Live-Verbindung simulieren (Supervisor muss
44
- * mit Backoff neu starten). */
43
+ /** Test helper: simulates the live connection terminating (the supervisor
44
+ * must restart with backoff). */
45
45
  export function emitWatchError(accountId, err) {
46
46
  const state = accounts.get(accountId);
47
47
  if (state?.watch) {
@@ -50,7 +50,7 @@ export function emitWatchError(accountId, err) {
50
50
  handlers.onError(err);
51
51
  }
52
52
  }
53
- /** Test-Helper: läuft gerade ein watch für den Account? */
53
+ /** Test helper: reports whether an account currently has an active watch. */
54
54
  export function isWatching(accountId) {
55
55
  return accounts.get(accountId)?.watch != null;
56
56
  }
@@ -60,7 +60,7 @@ export function resetInboundInMemory() {
60
60
  accounts.clear();
61
61
  }
62
62
  // =============================================================================
63
- // Plugin — cursor = { offset: number } über das append-only-Log.
63
+ // Plugin — cursor = { offset: number } over the append-only log.
64
64
  // =============================================================================
65
65
  function offsetOf(cursor) {
66
66
  const raw = cursor?.["offset"];
@@ -1,4 +1,4 @@
1
- // Job-run retention (#2243): store_job_runs/store_job_run_logs are
1
+ // Job-run retention: store_job_runs/store_job_run_logs are
2
2
  // direct-write stores now, not event-sourced projections — nothing else
3
3
  // purges them, so without this query they grow forever with the run count
4
4
  // instead of the runtime. Not the retention-cleanup executor: that executor
@@ -18,7 +18,7 @@ export async function deleteStaleJobRuns(db, retentionDays) {
18
18
  const cutoff = Temporal.Now.instant().subtract({ hours: retentionDays * 24 });
19
19
  const logsResult = await deleteManyBatched(db, jobRunLogsTable, { timestamp: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
20
20
  const runsResult = await deleteManyBatched(db, jobRunsTable, { insertedAt: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
21
- // Same window for the tenant-visible failure records (fw#3079): the run
21
+ // Same window for the tenant-visible failure records: the run
22
22
  // they point at is gone by now, and a job whose subject never ran again
23
23
  // would otherwise keep its record forever.
24
24
  const tenantFailuresResult = await deleteManyBatched(db, tenantJobFailuresTable, { failedAt: { lt: cutoff } }, { limit: RETENTION_DELETE_BATCH_SIZE });
@@ -1,5 +1,5 @@
1
- // Stale job-run sweep (#2246): store_job_runs is a direct-write store
2
- // (#2243) — status is set to "running" once at onJobStart and only ever
1
+ // Stale job-run sweep: store_job_runs is a direct-write store
2
+ // Status is set to "running" once at onJobStart and only ever
3
3
  // flipped to "completed"/"failed" by onJobComplete/onJobFailed. If the
4
4
  // process dies mid-run (crash, OOM, kill -9), those callbacks never fire and
5
5
  // the row is stuck on "running" forever — nothing else on the read side
@@ -31,7 +31,7 @@ export async function markStaleJobRunsFailed(db, timeoutHours, queuedRetentionDa
31
31
  // user subject annotation as job-run-logger.ts's onJobFailed path
32
32
  // (personal: { of: "triggeredById" } on job-run-table.ts), so it is encrypted
33
33
  // under the triggering user's DEK, or the system tenant key when
34
- // triggeredById is null (whenAbsent: "tenant", fw#3654). Runs are grouped by
34
+ // triggeredById is null (whenAbsent: "tenant"). Runs are grouped by
35
35
  // that subject: one encrypt and one updateMany per subject instead of per run.
36
36
  const stale = await selectMany(db, jobRunsTable, {
37
37
  status: "running",
@@ -1,4 +1,4 @@
1
- // Payload schemas for the jobRun direct-write path (#2243). Pre-#2243 these
1
+ // Payload schemas for the jobRun direct-write path. Previously these
2
2
  // backed jobRun's event-store payloads (r.defineEvent + inline projections);
3
3
  // now job-run-logger.ts parses against them before writing straight into
4
4
  // jobRunsTable/jobRunLogsTable, so an out-of-dispatcher write still gets the
@@ -2,5 +2,6 @@ import { type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
2
2
  export type JobsFeatureOptions = {
3
3
  readonly retentionDays?: number;
4
4
  readonly staleRunTimeoutHours?: number;
5
+ readonly readRoles?: readonly string[];
5
6
  };
6
7
  export declare function createJobsFeature(options?: JobsFeatureOptions): FeatureDefinition;
@@ -9,8 +9,8 @@ import { reindexEntityJob, reindexEntityPayloadSchema } from "./handlers/reindex
9
9
  import { createRetentionCleanupJob, DEFAULT_JOB_RUN_RETENTION_DAYS, } from "./handlers/retention-cleanup.job.js";
10
10
  import { retryWrite } from "./handlers/retry.write.js";
11
11
  import { createStaleRunSweepJob, DEFAULT_JOB_RUN_STALE_TIMEOUT_HOURS, } from "./handlers/stale-run-sweep.job.js";
12
- import { tenantFailuresQuery } from "./handlers/tenant-failures.query.js";
13
- import { tenantRunsQuery } from "./handlers/tenant-runs.query.js";
12
+ import { createTenantFailuresQuery } from "./handlers/tenant-failures.query.js";
13
+ import { createTenantRunsQuery } from "./handlers/tenant-runs.query.js";
14
14
  import { triggerWrite } from "./handlers/trigger.write.js";
15
15
  import { jobRunLogsTableMeta, jobRunsTableMeta } from "./job-run-table.js";
16
16
  import { eventConsumerDetailScreen, eventConsumersScreen, jobRunDetailScreen, jobRunsScreen, jobTriggerScreen, } from "./screens.js";
@@ -20,6 +20,10 @@ import { JOBS_I18N } from "./web/i18n.js";
20
20
  export function createJobsFeature(options = {}) {
21
21
  const retentionDays = options.retentionDays ?? DEFAULT_JOB_RUN_RETENTION_DAYS;
22
22
  const staleRunTimeoutHours = options.staleRunTimeoutHours ?? DEFAULT_JOB_RUN_STALE_TIMEOUT_HOURS;
23
+ const readRoles = options.readRoles ?? [];
24
+ if (readRoles.includes("anonymous")) {
25
+ throw new Error(`createJobsFeature: readRoles must not contain "anonymous" — job status and failures are only readable by members of the tenant.`);
26
+ }
23
27
  return defineFeature("jobs", (r) => {
24
28
  r.describe("Persistence and operator tooling for background jobs registered via `r.job(...)`. Every job execution writes directly into `store_job_runs` (current status + duration) and `store_job_run_logs` (per-line log rows) from the BullMQ callbacks — no event stream in between (#2243). A daily `retention-cleanup` job deletes runs (and their logs) older than `retentionDays`; an hourly `stale-run-sweep` job marks runs stuck at status `running` past `staleRunTimeoutHours` as `failed` (#2246 — a crashed worker never fires the completion callback, so nothing else ever revisits the row). Exposes `jobs:write:trigger` (manual run) and `jobs:write:retry` (operator retry of a failed run), plus `jobs:query:list`, `jobs:query:details`, and `jobs:query:catalog` (manual jobs) for the operator UI. A job that declares `tenantVisibleFailure` also records its last failed attempt per tenant and subject in `store_tenant_job_failures`, which the tenant itself reads through `jobs:query:failures` — a translation key only, never the provider's message (fw#3079). A job that declares `tenantVisibleRun` also keeps its run state per tenant and subject in `store_tenant_job_runs` (queued, running, plus the latest completed or failed run, no payload, error text or logs), which the tenant reads through `jobs:query:tenant-runs` (fw#3616); the stale-run sweep fails its stuck `running` rows and drops `queued` rows older than `retentionDays`.");
25
29
  r.uiHints({
@@ -31,11 +35,10 @@ export function createJobsFeature(options = {}) {
31
35
  r.storeTable(jobRunsTableMeta, {
32
36
  reason: "direct_write.job_runs",
33
37
  // payload/error carry personal:{of:"triggeredById"} (job-run-table.ts): encrypted under the
34
- // triggering user's DEK, or the system tenant key when triggeredById is null
35
- // (whenAbsent: "tenant", fw#3654).
38
+ // triggering user's DEK, or the system tenant key when triggeredById is null.
36
39
  // job-run-logger.ts manually encrypts both before every insert/update
37
40
  // (encryptStartedPayload/encryptFailureError) since this store bypasses
38
- // the executor's automatic PII pipeline (#2243).
41
+ // the executor's automatic PII pipeline.
39
42
  piiEncryptedOnWrite: true,
40
43
  });
41
44
  r.storeTable(jobRunLogsTableMeta, {
@@ -49,7 +52,7 @@ export function createJobsFeature(options = {}) {
49
52
  });
50
53
  // Framework-provided rebuild job — available whenever `jobs` is composed; enqueueProjectionRebuild dispatches it.
51
54
  r.job("projectionRebuild", { trigger: { manual: true }, concurrency: "skip", schema: projectionRebuildPayloadSchema }, projectionRebuildJob);
52
- // Retroactive search backfill (#1206/#1215) — manual + perTenant, so one
55
+ // Retroactive search backfill — manual + perTenant, so one
53
56
  // `jobs:write:trigger` call with { entity } fans out to every active
54
57
  // tenant (job-runner.ts perTenant dispatch applies to manual triggers
55
58
  // too, not just cron).
@@ -60,10 +63,10 @@ export function createJobsFeature(options = {}) {
60
63
  schema: reindexEntityPayloadSchema,
61
64
  }, reindexEntityJob);
62
65
  // store_job_runs/store_job_run_logs are direct-write, unbounded-growth
63
- // stores (#2243) — nothing else purges them.
66
+ // stores — nothing else purges them.
64
67
  r.job("retention-cleanup", { trigger: { cron: "0 3 * * *" }, concurrency: "skip" }, createRetentionCleanupJob(retentionDays));
65
68
  // Sweeps store_job_runs for rows stuck at status "running" past the
66
- // timeout (#2246). Hourly matches the timeout's own granularity —
69
+ // timeout. Hourly matches the timeout's own granularity —
67
70
  // frequent enough to catch a stuck run soon after it crosses the
68
71
  // threshold, cheap enough that an (almost always empty) result set
69
72
  // doesn't matter.
@@ -80,8 +83,8 @@ export function createJobsFeature(options = {}) {
80
83
  list: r.queryHandler(listQuery),
81
84
  detail: r.queryHandler(detailQuery),
82
85
  catalog: r.queryHandler(catalogQuery),
83
- failures: r.queryHandler(tenantFailuresQuery),
84
- tenantRuns: r.queryHandler(tenantRunsQuery),
86
+ failures: r.queryHandler(createTenantFailuresQuery(readRoles)),
87
+ tenantRuns: r.queryHandler(createTenantRunsQuery(readRoles)),
85
88
  consumers: r.queryHandler(consumersQuery),
86
89
  consumerDetails: r.queryHandler(consumerDetailQuery),
87
90
  };
@@ -27,11 +27,11 @@ export const detailQuery = defineQueryHandler({
27
27
  const row = await fetchOne(db, jobRunsTable, { id: query.payload.runId });
28
28
  if (!row)
29
29
  return null;
30
- // payload is stored encrypted under the triggering user's DEK (#799).
30
+ // payload is stored encrypted under the triggering user's DEK.
31
31
  if (typeof row["payload"] === "string") {
32
32
  row["payload"] = await decryptStoredPii(row["payload"], "payload", "job-run-detail");
33
33
  }
34
- // error is stored encrypted under the triggering user's DEK (#2307),
34
+ // error is stored encrypted under the triggering user's DEK,
35
35
  // same mechanism as row.payload above.
36
36
  if (typeof row["error"] === "string") {
37
37
  row["error"] = await decryptStoredPii(row["error"], "error", "job-run-detail");
@@ -39,8 +39,8 @@ export const detailQuery = defineQueryHandler({
39
39
  const logs = await selectMany(db, jobRunLogsTable, { runId: query.payload.runId }, {
40
40
  orderBy: { col: "id", direction: "asc" },
41
41
  });
42
- // message is stored encrypted under the triggering user's DEK (#2247),
43
- // same mechanism as row.payload above. Bounded concurrency (#2307) —
42
+ // message is stored encrypted under the triggering user's DEK,
43
+ // same mechanism as row.payload above. Bounded concurrency —
44
44
  // unbounded Promise.all would fire one decrypt per log line at once
45
45
  // against the KMS adapter's pool.
46
46
  const decryptedLogs = await mapWithConcurrency(logs, KMS_POOL_CONCURRENCY, async (log) => {
@@ -88,7 +88,7 @@ export const listQuery = defineQueryHandler({
88
88
  // countWhere reruns the SAME `where` without the limit — `rows.length` is
89
89
  // capped at the page size and would silently undercount the total.
90
90
  const total = query.payload.totalCount === true ? await countWhere(db, jobRunsTable, where) : undefined;
91
- // payload/error are stored encrypted under the triggering user's DEK (#799, #2307).
91
+ // payload/error are stored encrypted under the triggering user's DEK.
92
92
  return {
93
93
  rows: await mapWithConcurrency(rows, KMS_POOL_CONCURRENCY, decryptRunRow),
94
94
  nextCursor: hasMore ? encodeCursor(String(offset + limit)) : null,
@@ -4,7 +4,7 @@ import { rebuildProjectionOrMultiStream } from "@cosmicdrift/kumiko-framework/mi
4
4
  import * as z from "zod";
5
5
  export const projectionRebuildPayloadSchema = z.object({
6
6
  projection: z.string().min(1),
7
- // Quarantine mode (#760): skip + dead-letter poison events instead of
7
+ // Quarantine mode: skip + dead-letter poison events instead of
8
8
  // failing the whole rebuild. Operator opt-in per run.
9
9
  skipApplyErrors: z.boolean().optional(),
10
10
  });
@@ -1,4 +1,4 @@
1
- // Manual, perTenant backfill job (#1206/#1215) — indexes existing rows for
1
+ // Manual, perTenant backfill job — indexes existing rows for
2
2
  // an entity that only got `searchable: true` after rows already existed.
3
3
  // perTenant fan-out (job-runner.ts) also applies to a manual dispatch, not
4
4
  // just cron: one `jobs:write:trigger` call with { entity } re-runs once per
@@ -35,7 +35,7 @@ export const retryWrite = defineWriteHandler({
35
35
  details: { status: run.status },
36
36
  }));
37
37
  }
38
- // payload is stored encrypted under the triggering user's DEK (#799),
38
+ // payload is stored encrypted under the triggering user's DEK,
39
39
  // same mechanism as detail.query.ts/list.query.ts — decrypt before
40
40
  // parsing it as JSON. A key erased since the run finished decrypts to
41
41
  // PII_ERASED_SENTINEL, which is not JSON; reject the retry rather than
@@ -1,5 +1,5 @@
1
1
  import * as z from "zod";
2
- export declare const tenantFailuresQuery: import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"failures", z.ZodObject<{
2
+ export declare function createTenantFailuresQuery(readRoles: readonly string[]): import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"failures", z.ZodObject<{
3
3
  jobName: z.ZodOptional<z.ZodString>;
4
4
  subject: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
5
5
  limit: z.ZodOptional<z.ZodNumber>;
@@ -20,45 +20,49 @@ function parseSubject(stored) {
20
20
  return null;
21
21
  return Object.fromEntries(parsed.filter(isSubjectEntry));
22
22
  }
23
- export const tenantFailuresQuery = defineQueryHandler({
24
- name: "failures",
25
- description: "Lists the calling tenant's own failed jobs — one record per job and subject, newest first, each carrying a translation key for the reason, never the provider's own error message; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to tell a tenant that their asynchronous job failed instead of leaving the screen waiting.",
26
- schema: z.object({
27
- jobName: z.string().optional(),
28
- subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
29
- limit: z.number().int().min(1).max(200).optional(),
30
- }),
31
- // Every membership rank: a failure record carries a job name and a
32
- // translation key, nothing a team member of the tenant may not see.
33
- access: { roles: access.roles("User", "Editor", ...access.admin) },
34
- handler: async (query, ctx) => {
35
- if (!ctx.systemDb) {
36
- throw new InternalError({
37
- message: "jobs:query:failures requires ctx.systemDb (feature must declare r.systemScope())",
23
+ export function createTenantFailuresQuery(readRoles) {
24
+ return defineQueryHandler({
25
+ name: "failures",
26
+ description: "Lists the calling tenant's own failed jobs — one record per job and subject, newest first, each carrying a translation key for the reason, never the provider's own error message; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to tell a tenant that their asynchronous job failed instead of leaving the screen waiting.",
27
+ schema: z.object({
28
+ jobName: z.string().optional(),
29
+ subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
30
+ limit: z.number().int().min(1).max(200).optional(),
31
+ }),
32
+ // Every membership rank: a failure record carries a job name and a
33
+ // translation key, nothing a team member of the tenant may not see.
34
+ access: {
35
+ roles: [...new Set([...access.roles("User", "Editor", ...access.admin), ...readRoles])],
36
+ },
37
+ handler: async (query, ctx) => {
38
+ if (!ctx.systemDb) {
39
+ throw new InternalError({
40
+ message: "jobs:query:failures requires ctx.systemDb (feature must declare r.systemScope())",
41
+ });
42
+ }
43
+ // assertTenantMatch is a self-check on the caller and returns the same
44
+ // unfiltered system-mode db (tenant-db.ts) — the explicit tenantId below
45
+ // is the filter, assertRowsTenant the second net. There is no
46
+ // cross-tenant mode here: SystemAdmin reads runs via jobs:query:list.
47
+ const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
48
+ const where = { tenantId: [query.user.tenantId] };
49
+ if (query.payload.jobName)
50
+ where["jobName"] = query.payload.jobName;
51
+ if (query.payload.subject)
52
+ where["subject"] = serializeJobSubject(query.payload.subject);
53
+ const rows = await selectMany(db, tenantJobFailuresTable, where, {
54
+ orderBy: { col: "failedAt", direction: "desc" },
55
+ limit: query.payload.limit ?? DEFAULT_LIMIT,
38
56
  });
39
- }
40
- // assertTenantMatch is a self-check on the caller and returns the same
41
- // unfiltered system-mode db (tenant-db.ts) — the explicit tenantId below
42
- // is the filter, assertRowsTenant the second net. There is no
43
- // cross-tenant mode here: SystemAdmin reads runs via jobs:query:list.
44
- const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
45
- const where = { tenantId: [query.user.tenantId] };
46
- if (query.payload.jobName)
47
- where["jobName"] = query.payload.jobName;
48
- if (query.payload.subject)
49
- where["subject"] = serializeJobSubject(query.payload.subject);
50
- const rows = await selectMany(db, tenantJobFailuresTable, where, {
51
- orderBy: { col: "failedAt", direction: "desc" },
52
- limit: query.payload.limit ?? DEFAULT_LIMIT,
53
- });
54
- return {
55
- rows: ctx.systemDb.assertRowsTenant(rows, "tenantId").map((row) => ({
56
- jobName: row.jobName,
57
- subject: parseSubject(row.subject),
58
- messageKey: row.messageKey,
59
- failedAt: row.failedAt,
60
- })),
61
- nextCursor: null,
62
- };
63
- },
64
- });
57
+ return {
58
+ rows: ctx.systemDb.assertRowsTenant(rows, "tenantId").map((row) => ({
59
+ jobName: row.jobName,
60
+ subject: parseSubject(row.subject),
61
+ messageKey: row.messageKey,
62
+ failedAt: row.failedAt,
63
+ })),
64
+ nextCursor: null,
65
+ };
66
+ },
67
+ });
68
+ }
@@ -1,6 +1,6 @@
1
1
  import * as z from "zod";
2
2
  import { type TenantJobRunStatus } from "../tenant-job-run-table.ts";
3
- export declare const tenantRunsQuery: import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"tenant-runs", z.ZodObject<{
3
+ export declare function createTenantRunsQuery(readRoles: readonly string[]): import("@cosmicdrift/kumiko-types/define-handler").QueryHandlerDefinition<"tenant-runs", z.ZodObject<{
4
4
  jobName: z.ZodOptional<z.ZodString>;
5
5
  subject: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
6
6
  limit: z.ZodOptional<z.ZodNumber>;
@@ -19,54 +19,58 @@ function parseSubject(stored) {
19
19
  return null;
20
20
  return Object.fromEntries(parsed.filter(isSubjectEntry));
21
21
  }
22
- export const tenantRunsQuery = defineQueryHandler({
23
- name: "tenant-runs",
24
- description: "Lists the calling tenant's own job runs that opted in via tenantVisibleRun — per job and subject every queued or running run plus the latest completed or failed one, active runs first, then newest first; each row carries only status and queuedAt/startedAt/finishedAt, never payloads, error text or logs; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to show whether work for a subject is waiting, running or done, and to tell a failed run from a finished one.",
25
- schema: z.object({
26
- jobName: z.string().optional(),
27
- subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
28
- limit: z.number().int().min(1).max(200).optional(),
29
- }),
30
- // Every membership rank: a run state carries a job name, a status and
31
- // times, nothing a team member of the tenant may not see.
32
- access: { roles: access.roles("User", "Editor", ...access.admin) },
33
- handler: async (query, ctx) => {
34
- if (!ctx.systemDb) {
35
- throw new InternalError({
36
- message: "jobs:query:tenant-runs requires ctx.systemDb (feature must declare r.systemScope())",
22
+ export function createTenantRunsQuery(readRoles) {
23
+ return defineQueryHandler({
24
+ name: "tenant-runs",
25
+ description: "Lists the calling tenant's own job runs that opted in via tenantVisibleRun — per job and subject every queued or running run plus the latest completed or failed one, active runs first, then newest first; each row carries only status and queuedAt/startedAt/finishedAt, never payloads, error text or logs; the optional subject filter matches exactly: all declared subjectFields with the same JSON types as the job payload; use it to show whether work for a subject is waiting, running or done, and to tell a failed run from a finished one.",
26
+ schema: z.object({
27
+ jobName: z.string().optional(),
28
+ subject: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
29
+ limit: z.number().int().min(1).max(200).optional(),
30
+ }),
31
+ // Every membership rank: a run state carries a job name, a status and
32
+ // times, nothing a team member of the tenant may not see.
33
+ access: {
34
+ roles: [...new Set([...access.roles("User", "Editor", ...access.admin), ...readRoles])],
35
+ },
36
+ handler: async (query, ctx) => {
37
+ if (!ctx.systemDb) {
38
+ throw new InternalError({
39
+ message: "jobs:query:tenant-runs requires ctx.systemDb (feature must declare r.systemScope())",
40
+ });
41
+ }
42
+ // assertTenantMatch returns the same unfiltered system-mode db — the
43
+ // explicit tenantId below is the filter, assertRowsTenant the second net.
44
+ const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
45
+ const where = { tenantId: [query.user.tenantId] };
46
+ if (query.payload.jobName)
47
+ where["jobName"] = query.payload.jobName;
48
+ if (query.payload.subject)
49
+ where["subject"] = serializeJobSubject(query.payload.subject);
50
+ const limit = query.payload.limit ?? DEFAULT_LIMIT;
51
+ const newestFirst = { col: "updatedAt", direction: "desc" };
52
+ const activeRows = await selectMany(db, tenantJobRunsTable, { ...where, status: { in: ["queued", "running"] } }, { orderBy: newestFirst, limit });
53
+ const finishedRows = await selectMany(db, tenantJobRunsTable, { ...where, status: { in: ["completed", "failed"] } }, { orderBy: newestFirst, limit });
54
+ const seenFinishedKeys = new Set();
55
+ const finishedNewestPerKey = finishedRows.filter((row) => {
56
+ const key = JSON.stringify([row.jobName, row.subject]);
57
+ if (seenFinishedKeys.has(key))
58
+ return false;
59
+ seenFinishedKeys.add(key);
60
+ return true;
37
61
  });
38
- }
39
- // assertTenantMatch returns the same unfiltered system-mode db — the
40
- // explicit tenantId below is the filter, assertRowsTenant the second net.
41
- const db = ctx.systemDb.assertTenantMatch(query.user.tenantId);
42
- const where = { tenantId: [query.user.tenantId] };
43
- if (query.payload.jobName)
44
- where["jobName"] = query.payload.jobName;
45
- if (query.payload.subject)
46
- where["subject"] = serializeJobSubject(query.payload.subject);
47
- const limit = query.payload.limit ?? DEFAULT_LIMIT;
48
- const newestFirst = { col: "updatedAt", direction: "desc" };
49
- const activeRows = await selectMany(db, tenantJobRunsTable, { ...where, status: { in: ["queued", "running"] } }, { orderBy: newestFirst, limit });
50
- const finishedRows = await selectMany(db, tenantJobRunsTable, { ...where, status: { in: ["completed", "failed"] } }, { orderBy: newestFirst, limit });
51
- const seenFinishedKeys = new Set();
52
- const finishedNewestPerKey = finishedRows.filter((row) => {
53
- const key = JSON.stringify([row.jobName, row.subject]);
54
- if (seenFinishedKeys.has(key))
55
- return false;
56
- seenFinishedKeys.add(key);
57
- return true;
58
- });
59
- const activeFirst = [...activeRows, ...finishedNewestPerKey];
60
- return {
61
- rows: ctx.systemDb.assertRowsTenant(activeFirst.slice(0, limit), "tenantId").map((row) => ({
62
- jobName: row.jobName,
63
- subject: parseSubject(row.subject),
64
- status: row.status,
65
- queuedAt: row.queuedAt,
66
- startedAt: row.startedAt,
67
- finishedAt: row.finishedAt,
68
- })),
69
- nextCursor: null,
70
- };
71
- },
72
- });
62
+ const activeFirst = [...activeRows, ...finishedNewestPerKey];
63
+ return {
64
+ rows: ctx.systemDb.assertRowsTenant(activeFirst.slice(0, limit), "tenantId").map((row) => ({
65
+ jobName: row.jobName,
66
+ subject: parseSubject(row.subject),
67
+ status: row.status,
68
+ queuedAt: row.queuedAt,
69
+ startedAt: row.startedAt,
70
+ finishedAt: row.finishedAt,
71
+ })),
72
+ nextCursor: null,
73
+ };
74
+ },
75
+ });
76
+ }
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
2
- // kumiko-framework#1525: the five value-position Temporal.Instant.from
2
+ // The five value-position Temporal.Instant.from
3
3
  // call sites in feature.ts live inside defineApply callbacks with no
4
4
  // exported seam, so this thin wrapper gives the ambient-global-independence
5
5
  // regression test something to import directly.