@cosmicdrift/kumiko-bundled-features 0.367.0 → 0.369.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 (359) hide show
  1. package/dist/audit/handlers/details.query.js +1 -1
  2. package/dist/audit/handlers/list.query.js +1 -1
  3. package/dist/audit/run-escape-hatch-retention.js +1 -1
  4. package/dist/auth-email-password/bootstrap.js +1 -1
  5. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +6 -3
  6. package/dist/auth-email-password/handlers/invite-accept.write.js +6 -3
  7. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  8. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +6 -3
  9. package/dist/auth-email-password/handlers/signup-confirm.write.js +1 -1
  10. package/dist/auth-email-password/seeding.js +2 -2
  11. package/dist/auth-foundation/feature.d.ts +4 -0
  12. package/dist/auth-foundation/feature.js +37 -33
  13. package/dist/auth-foundation/index.d.ts +1 -1
  14. package/dist/auth-foundation/index.js +1 -1
  15. package/dist/auth-mfa/db/queries.js +1 -2
  16. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +1 -1
  17. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  18. package/dist/auth-mfa/handlers/reencrypt.job.js +2 -3
  19. package/dist/auth-mfa/handlers/status.query.js +1 -1
  20. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  21. package/dist/auth-mfa/mfa-code-verifier.js +1 -1
  22. package/dist/auth-mfa/mfa-status-checker.js +1 -1
  23. package/dist/auth-mfa-user-data/index.d.ts +4 -0
  24. package/dist/auth-mfa-user-data/index.js +13 -9
  25. package/dist/billing-foundation/billing-info-query.js +1 -1
  26. package/dist/billing-foundation/feature.d.ts +1 -0
  27. package/dist/billing-foundation/feature.js +5 -6
  28. package/dist/billing-foundation/handlers/create-portal-session.write.js +1 -1
  29. package/dist/billing-foundation/projection.js +1 -2
  30. package/dist/cap-counter/calendar-cap-usage-reservation.d.ts +7 -0
  31. package/dist/cap-counter/calendar-cap-usage-reservation.js +28 -2
  32. package/dist/cap-counter/cap-reservation.d.ts +16 -0
  33. package/dist/cap-counter/cap-reservation.js +144 -14
  34. package/dist/cap-counter/feature.d.ts +4 -0
  35. package/dist/cap-counter/feature.js +74 -68
  36. package/dist/cap-counter/handlers/increment-rolling.write.js +3 -4
  37. package/dist/cap-counter/index.d.ts +3 -2
  38. package/dist/cap-counter/index.js +3 -2
  39. package/dist/cap-counter/tables.js +10 -3
  40. package/dist/cap-overview/handlers/caps-usage.query.js +1 -2
  41. package/dist/cap-overview/handlers/tenant-caps-list.query.js +1 -2
  42. package/dist/cap-overview/handlers/tenant-options.query.js +1 -1
  43. package/dist/channel-email/email-channel.d.ts +13 -5
  44. package/dist/channel-email/email-channel.js +17 -3
  45. package/dist/channel-email/feature.js +1 -1
  46. package/dist/channel-email/index.d.ts +1 -1
  47. package/dist/channel-email/index.js +1 -1
  48. package/dist/channel-in-app/handlers/inbox.query.js +1 -1
  49. package/dist/channel-in-app/handlers/mark-all-read.write.js +1 -1
  50. package/dist/channel-in-app/handlers/mark-read.write.js +1 -1
  51. package/dist/channel-in-app/handlers/unread-count.query.js +1 -1
  52. package/dist/channel-in-app/tables.js +1 -2
  53. package/dist/compliance-profiles/handlers/for-tenant.query.js +1 -1
  54. package/dist/compliance-profiles/handlers/needs-profile.query.js +1 -1
  55. package/dist/compliance-profiles/handlers/set-profile.write.js +1 -2
  56. package/dist/compliance-profiles/resolve-for-tenant.js +1 -1
  57. package/dist/compliance-profiles/seeding.js +3 -5
  58. package/dist/compliance-profiles-ops/index.d.ts +8 -0
  59. package/dist/compliance-profiles-ops/index.js +19 -15
  60. package/dist/config/db/queries/resolver.js +1 -1
  61. package/dist/config/handlers/reencrypt.job.js +2 -2
  62. package/dist/config/resolver.js +1 -1
  63. package/dist/config/web/i18n.js +1 -2
  64. package/dist/config/write-helpers.js +1 -1
  65. package/dist/crypto-shredding/handlers/forget-subject.write.js +6 -3
  66. package/dist/custom-fields/db/queries/field-access.js +1 -1
  67. package/dist/custom-fields/db/queries/projection.js +1 -1
  68. package/dist/custom-fields/db/queries/quota.js +1 -1
  69. package/dist/custom-fields/db/queries/retention.js +1 -2
  70. package/dist/custom-fields/db/queries/user-data-rights.js +1 -1
  71. package/dist/custom-fields/feature.d.ts +20 -2
  72. package/dist/custom-fields/feature.js +9 -13
  73. package/dist/custom-fields/handlers/clear-custom-field.write.js +2 -2
  74. package/dist/custom-fields/handlers/delete-system-field.write.js +2 -2
  75. package/dist/custom-fields/handlers/delete-tenant-field.write.js +2 -2
  76. package/dist/custom-fields/handlers/set-custom-field.write.js +2 -2
  77. package/dist/custom-fields/wire-for-entity.js +4 -4
  78. package/dist/data-retention/resolve-for-tenant.js +1 -1
  79. package/dist/data-retention/run-retention-cleanup.js +17 -13
  80. package/dist/delivery/address-opt-out.js +1 -2
  81. package/dist/delivery/attempt-log-retention.js +1 -1
  82. package/dist/delivery/channel-context.js +1 -1
  83. package/dist/delivery/db/queries/address-opt-outs.js +1 -1
  84. package/dist/delivery/db/queries/preferences.js +1 -1
  85. package/dist/delivery/delivery-service.js +16 -7
  86. package/dist/delivery/feature.js +2 -2
  87. package/dist/delivery/handlers/log.query.js +2 -3
  88. package/dist/delivery/handlers/preferences.query.js +1 -1
  89. package/dist/delivery/index.d.ts +3 -2
  90. package/dist/delivery/index.js +3 -2
  91. package/dist/delivery/unsubscribe.d.ts +13 -0
  92. package/dist/delivery/unsubscribe.js +32 -27
  93. package/dist/delivery/upsert-preference.js +1 -2
  94. package/dist/derivatives-sharp/feature.d.ts +4 -0
  95. package/dist/derivatives-sharp/feature.js +15 -11
  96. package/dist/derivatives-sharp/index.d.ts +1 -1
  97. package/dist/derivatives-sharp/index.js +1 -1
  98. package/dist/document-ingest-foundation/feature.d.ts +7 -0
  99. package/dist/document-ingest-foundation/feature.js +94 -90
  100. package/dist/document-ingest-foundation/forget-extract-with-file-ref.js +3 -3
  101. package/dist/document-ingest-foundation/index.d.ts +1 -1
  102. package/dist/document-ingest-foundation/index.js +1 -1
  103. package/dist/feature-toggles/global-feature-state-table.js +1 -2
  104. package/dist/feature-toggles/handlers/set.write.js +3 -5
  105. package/dist/feature-toggles/toggle-runtime.js +1 -1
  106. package/dist/file-derivatives/feature.d.ts +1 -0
  107. package/dist/file-derivatives/feature.js +2 -1
  108. package/dist/file-derivatives/handlers/public-variant-by-file-ref.query.js +1 -1
  109. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  110. package/dist/file-foundation/feature.d.ts +6 -0
  111. package/dist/file-foundation/feature.js +29 -25
  112. package/dist/file-foundation/index.d.ts +1 -1
  113. package/dist/file-foundation/index.js +1 -1
  114. package/dist/file-foundation/read-file-ref-content.js +1 -1
  115. package/dist/file-provider-inmemory/feature.d.ts +4 -0
  116. package/dist/file-provider-inmemory/feature.js +24 -20
  117. package/dist/file-provider-inmemory/index.d.ts +1 -1
  118. package/dist/file-provider-inmemory/index.js +1 -1
  119. package/dist/file-provider-s3/env-feature.d.ts +3 -0
  120. package/dist/file-provider-s3/env-feature.js +46 -0
  121. package/dist/file-provider-s3/feature.d.ts +26 -0
  122. package/dist/file-provider-s3/feature.js +84 -72
  123. package/dist/file-provider-s3/index.d.ts +1 -1
  124. package/dist/file-provider-s3/index.js +1 -1
  125. package/dist/file-provider-s3/lib/index.d.ts +3 -0
  126. package/dist/file-provider-s3/lib/index.js +2 -0
  127. package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.js +19 -19
  128. package/dist/file-provider-s3-env/index.d.ts +8 -1
  129. package/dist/file-provider-s3-env/index.js +7 -2
  130. package/dist/files-provider-s3/index.d.ts +5 -3
  131. package/dist/files-provider-s3/index.js +5 -2
  132. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +1 -1
  133. package/dist/files-tenant-data/hooks.js +1 -2
  134. package/dist/folders/feature.d.ts +6 -2
  135. package/dist/folders/feature.js +4 -2
  136. package/dist/folders-user-data/index.d.ts +4 -0
  137. package/dist/folders-user-data/index.js +21 -17
  138. package/dist/form-draft/db/queries/cleanup.js +1 -1
  139. package/dist/form-draft/db/queries/draft-count.js +1 -1
  140. package/dist/form-draft/db/queries/owned-file-refs.js +1 -2
  141. package/dist/form-draft/feature.d.ts +4 -0
  142. package/dist/form-draft/feature.js +5 -1
  143. package/dist/form-draft/handlers/cleanup.job.js +2 -2
  144. package/dist/form-draft/index.d.ts +1 -1
  145. package/dist/form-draft/index.js +1 -1
  146. package/dist/form-draft/lookup.js +1 -1
  147. package/dist/form-draft-user-data/index.d.ts +4 -0
  148. package/dist/form-draft-user-data/index.js +13 -9
  149. package/dist/inbound-mail-foundation/feature.d.ts +4 -0
  150. package/dist/inbound-mail-foundation/feature.js +151 -147
  151. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -2
  152. package/dist/inbound-mail-foundation/index.d.ts +1 -1
  153. package/dist/inbound-mail-foundation/index.js +1 -1
  154. package/dist/inbound-mail-foundation/oauth-access-token.js +1 -2
  155. package/dist/inbound-mail-foundation/projection.js +1 -2
  156. package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
  157. package/dist/inbound-provider-imap/feature.d.ts +4 -0
  158. package/dist/inbound-provider-imap/feature.js +16 -12
  159. package/dist/inbound-provider-imap/index.d.ts +1 -1
  160. package/dist/inbound-provider-imap/index.js +1 -1
  161. package/dist/inbound-provider-inmemory/feature.d.ts +4 -0
  162. package/dist/inbound-provider-inmemory/feature.js +14 -10
  163. package/dist/inbound-provider-inmemory/index.d.ts +1 -1
  164. package/dist/inbound-provider-inmemory/index.js +1 -1
  165. package/dist/jobs/db/queries/retention.js +1 -1
  166. package/dist/jobs/db/queries/stale-run-sweep.js +1 -1
  167. package/dist/jobs/handlers/detail.query.js +1 -1
  168. package/dist/jobs/handlers/list.query.js +1 -2
  169. package/dist/jobs/handlers/retry.write.js +1 -1
  170. package/dist/jobs/handlers/tenant-failures.query.js +1 -1
  171. package/dist/jobs/handlers/tenant-runs.query.js +1 -1
  172. package/dist/jobs/job-run-logger.js +1 -2
  173. package/dist/jobs/tenant-job-failure-table.js +1 -2
  174. package/dist/jobs/tenant-job-run-table.js +1 -2
  175. package/dist/ledger/feature.d.ts +6 -2
  176. package/dist/ledger/feature.js +4 -2
  177. package/dist/mail-foundation/feature.d.ts +11 -0
  178. package/dist/mail-foundation/feature.js +52 -42
  179. package/dist/mail-foundation/i18n.d.ts +14 -0
  180. package/dist/mail-foundation/i18n.js +8 -0
  181. package/dist/mail-foundation/index.d.ts +1 -1
  182. package/dist/mail-foundation/index.js +1 -1
  183. package/dist/mail-transport-inmemory/feature.d.ts +4 -0
  184. package/dist/mail-transport-inmemory/feature.js +26 -16
  185. package/dist/mail-transport-inmemory/index.d.ts +1 -1
  186. package/dist/mail-transport-inmemory/index.js +1 -1
  187. package/dist/mail-transport-smtp/config-keys.d.ts +7 -0
  188. package/dist/mail-transport-smtp/config-keys.js +65 -0
  189. package/dist/mail-transport-smtp/feature.d.ts +17 -1
  190. package/dist/mail-transport-smtp/feature.js +58 -80
  191. package/dist/mail-transport-smtp/i18n.d.ts +41 -0
  192. package/dist/mail-transport-smtp/i18n.js +28 -0
  193. package/dist/mail-transport-smtp/index.d.ts +1 -1
  194. package/dist/mail-transport-smtp/index.js +1 -1
  195. package/dist/managed-pages/handlers/by-slug.query.js +1 -1
  196. package/dist/managed-pages/handlers/by-tenant-published.query.js +1 -2
  197. package/dist/managed-pages/handlers/set.write.js +1 -2
  198. package/dist/managed-pages/seeding.js +3 -5
  199. package/dist/metrics/compute.d.ts +1 -1
  200. package/dist/metrics/filters.d.ts +1 -1
  201. package/dist/metrics/filters.js +1 -1
  202. package/dist/metrics/validate.js +1 -1
  203. package/dist/notes-history/feature.d.ts +7 -2
  204. package/dist/notes-history/feature.js +4 -2
  205. package/dist/notes-history/handlers/add-note.write.js +1 -1
  206. package/dist/notes-history-user-data/hooks.js +1 -1
  207. package/dist/notes-history-user-data/index.d.ts +4 -0
  208. package/dist/notes-history-user-data/index.js +21 -17
  209. package/dist/personal-access-tokens/feature.d.ts +4 -1
  210. package/dist/personal-access-tokens/feature.js +10 -2
  211. package/dist/personal-access-tokens/handlers/create.write.js +1 -1
  212. package/dist/personal-access-tokens/handlers/list.query.js +2 -2
  213. package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
  214. package/dist/personal-access-tokens/resolver.js +1 -1
  215. package/dist/personal-access-tokens/revoke-for-user.js +1 -1
  216. package/dist/personal-access-tokens/roles.js +3 -5
  217. package/dist/personal-access-tokens/screens.js +2 -0
  218. package/dist/readiness/feature.d.ts +8 -0
  219. package/dist/readiness/feature.js +18 -14
  220. package/dist/readiness/index.d.ts +1 -1
  221. package/dist/readiness/index.js +1 -1
  222. package/dist/secrets/db/queries/read.js +1 -1
  223. package/dist/secrets/feature.d.ts +4 -0
  224. package/dist/secrets/feature.js +19 -6
  225. package/dist/secrets/handlers/delete.write.js +3 -2
  226. package/dist/secrets/handlers/rotate.job.js +2 -3
  227. package/dist/secrets/handlers/set.write.js +3 -2
  228. package/dist/secrets/secrets-context.js +3 -4
  229. package/dist/sessions/db/queries/cleanup.js +1 -1
  230. package/dist/sessions/handlers/detail.query.js +1 -1
  231. package/dist/sessions/handlers/list.query.js +2 -2
  232. package/dist/sessions/handlers/mine.query.js +1 -1
  233. package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
  234. package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
  235. package/dist/sessions/handlers/revoke.write.js +1 -1
  236. package/dist/sessions/session-callbacks.js +4 -6
  237. package/dist/sessions/testing.d.ts +1 -1
  238. package/dist/tags/feature.d.ts +6 -2
  239. package/dist/tags/feature.js +4 -2
  240. package/dist/template-resolver/api.js +1 -1
  241. package/dist/template-resolver/constants.d.ts +0 -1
  242. package/dist/template-resolver/constants.js +0 -1
  243. package/dist/template-resolver/handlers/bundle-import.js +1 -1
  244. package/dist/template-resolver/handlers/by-slug.query.js +1 -1
  245. package/dist/template-resolver/handlers/by-tenant.query.js +1 -2
  246. package/dist/template-resolver/handlers/collection-item.query.js +1 -1
  247. package/dist/template-resolver/handlers/collection-list.query.js +1 -2
  248. package/dist/template-resolver/handlers/collection-set.write.js +1 -1
  249. package/dist/template-resolver/handlers/copy-locale.write.js +1 -1
  250. package/dist/template-resolver/handlers/diff-to-system.query.js +1 -1
  251. package/dist/template-resolver/handlers/export-bundle.query.js +1 -1
  252. package/dist/template-resolver/handlers/find-by-id.query.js +1 -1
  253. package/dist/template-resolver/handlers/layout-source.query.js +1 -1
  254. package/dist/template-resolver/handlers/list.query.js +1 -1
  255. package/dist/template-resolver/handlers/overview.query.js +1 -1
  256. package/dist/template-resolver/handlers/reset-to-system.write.js +1 -1
  257. package/dist/template-resolver/handlers/resource-remove.write.js +1 -1
  258. package/dist/template-resolver/handlers/send-test.write.js +4 -2
  259. package/dist/template-resolver/handlers/set.write.js +1 -1
  260. package/dist/template-resolver/handlers/template-write.js +1 -1
  261. package/dist/template-resolver/handlers/tenant-overrides.query.js +1 -1
  262. package/dist/template-resolver/handlers/toggle-status.write.js +1 -1
  263. package/dist/template-resolver/handlers/usage.query.js +1 -1
  264. package/dist/template-resolver/handlers/validate.query.js +1 -1
  265. package/dist/template-resolver/seeding.js +3 -4
  266. package/dist/template-resolver/store-template-resource.js +1 -1
  267. package/dist/template-resolver/template-preview.js +1 -1
  268. package/dist/template-resolver/template-resources.js +1 -1
  269. package/dist/template-resolver/testing.js +1 -1
  270. package/dist/template-resolver-user-data/index.d.ts +4 -0
  271. package/dist/template-resolver-user-data/index.js +17 -13
  272. package/dist/tenant/handlers/active-tenant-ids.query.js +1 -1
  273. package/dist/tenant/handlers/add-member.write.js +1 -2
  274. package/dist/tenant/handlers/cancel-invitation.write.js +1 -1
  275. package/dist/tenant/handlers/invitations.query.js +1 -1
  276. package/dist/tenant/handlers/me.query.js +1 -1
  277. package/dist/tenant/handlers/member-directory.query.js +1 -1
  278. package/dist/tenant/handlers/members.query.js +1 -1
  279. package/dist/tenant/handlers/memberships.query.js +1 -1
  280. package/dist/tenant/handlers/remove-member.write.js +1 -2
  281. package/dist/tenant/handlers/resolve-user-ids.query.js +1 -1
  282. package/dist/tenant/handlers/team-list.query.js +1 -1
  283. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  284. package/dist/tenant/handlers/update-member-roles.write.js +1 -2
  285. package/dist/tenant/invited-membership.js +2 -3
  286. package/dist/tenant/last-tenant-admin.js +1 -2
  287. package/dist/tenant/seeding.js +12 -6
  288. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +1 -2
  289. package/dist/tenant-lifecycle/handlers/request-destruction.write.js +1 -2
  290. package/dist/tenant-lifecycle/lib/revoke-tenant-sessions.js +1 -1
  291. package/dist/tenant-lifecycle/lifecycle-gate.js +1 -1
  292. package/dist/tenant-lifecycle/run-tenant-destroy.js +3 -5
  293. package/dist/tenant-lifecycle/stages.js +10 -6
  294. package/dist/tenant-lifecycle/testing.d.ts +1 -1
  295. package/dist/tenant-lifecycle/testing.js +2 -2
  296. package/dist/tenant-settings/feature.d.ts +1 -0
  297. package/dist/tenant-settings/feature.js +2 -1
  298. package/dist/tier-engine/feature.d.ts +1 -8
  299. package/dist/tier-engine/feature.js +71 -78
  300. package/dist/tier-engine/handlers/get-tenant-tier.query.js +2 -3
  301. package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -2
  302. package/dist/user/db/queries/stream-tenant-backfill.js +1 -1
  303. package/dist/user/handlers/create.write.js +1 -2
  304. package/dist/user/handlers/find-for-auth.query.js +1 -1
  305. package/dist/user/handlers/list.query.js +1 -1
  306. package/dist/user/handlers/update-roles.js +1 -2
  307. package/dist/user/index.d.ts +1 -1
  308. package/dist/user/index.js +1 -1
  309. package/dist/user/invited-global-roles.js +2 -3
  310. package/dist/user/principal-status.d.ts +4 -0
  311. package/dist/user/principal-status.js +9 -3
  312. package/dist/user/resolve-display-names.js +1 -1
  313. package/dist/user/seeding.js +5 -6
  314. package/dist/user-data-rights/audit-download.js +2 -2
  315. package/dist/user-data-rights/db/queries/export-jobs.js +1 -1
  316. package/dist/user-data-rights/db/queries/forget-cleanup.js +1 -1
  317. package/dist/user-data-rights/feature.js +7 -4
  318. package/dist/user-data-rights/handlers/download-by-job.query.js +1 -1
  319. package/dist/user-data-rights/handlers/download-by-token.query.js +1 -1
  320. package/dist/user-data-rights/handlers/export-status.query.js +1 -1
  321. package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
  322. package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
  323. package/dist/user-data-rights/handlers/request-export.write.js +1 -2
  324. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +3 -3
  325. package/dist/user-data-rights/lib/default-mailers.d.ts +3 -0
  326. package/dist/user-data-rights/lib/default-mailers.js +25 -3
  327. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.d.ts +1 -1
  328. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.js +1 -1
  329. package/dist/user-data-rights/lib/update-user-lifecycle.d.ts +1 -0
  330. package/dist/user-data-rights/lib/update-user-lifecycle.js +3 -3
  331. package/dist/user-data-rights/run-export-jobs.js +2 -3
  332. package/dist/user-data-rights/run-forget-cleanup.js +9 -5
  333. package/dist/user-data-rights/run-user-export.js +9 -5
  334. package/dist/waitlist/handlers/invite.write.js +1 -2
  335. package/dist/waitlist/handlers/reject.write.js +1 -1
  336. package/dist/waitlist/lib.js +1 -2
  337. package/dist/workflow-runner/event-subscriber.js +1 -1
  338. package/dist/workflow-runner/feature.d.ts +4 -0
  339. package/dist/workflow-runner/feature.js +44 -40
  340. package/dist/workflow-runner/handlers/resume-run.write.js +1 -1
  341. package/dist/workflow-runner/index.d.ts +1 -1
  342. package/dist/workflow-runner/index.js +1 -1
  343. package/dist/workflow-runner/pending-projection.js +1 -1
  344. package/package.json +28 -11
  345. package/src/cap-counter/changes.json +13 -0
  346. package/src/channel-email/changes.json +7 -0
  347. package/src/crypto-shredding/changes.json +6 -0
  348. package/src/delivery/changes.json +6 -0
  349. package/src/file-provider-s3/changes.json +10 -1
  350. package/src/mail-transport-smtp/changes.json +7 -0
  351. package/src/personal-access-tokens/changes.json +6 -0
  352. package/src/secrets/changes.json +6 -0
  353. package/src/user/changes.json +6 -0
  354. package/src/user-data-rights/changes.json +6 -0
  355. package/dist/file-provider-s3-env/feature.d.ts +0 -3
  356. package/dist/file-provider-s3-env/feature.js +0 -46
  357. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.d.ts +0 -0
  358. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.js +0 -0
  359. /package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.d.ts +0 -0
@@ -15,8 +15,7 @@
15
15
  // The refresh token is re-read inside the lock via `secrets.get` without an
16
16
  // audit context. SecretsContext does not cache values (only unwrapped DEKs),
17
17
  // so the read always reflects the latest committed write.
18
- import { transaction } from "@cosmicdrift/kumiko-framework/bun-db";
19
- import { acquireNamespacedAdvisoryLock } from "@cosmicdrift/kumiko-framework/db";
18
+ import { acquireNamespacedAdvisoryLock, transaction, } from "@cosmicdrift/kumiko-framework/db";
20
19
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
21
20
  import { InboundMailAuthMethods, inboundCredentialSecretKey } from "./constants.js";
22
21
  import { InboundAuthError, } from "./types.js";
@@ -16,8 +16,7 @@
16
16
  // kommen bereits als Ciphertext an — encrypted VOR dem append im
17
17
  // write-handler. Die applies kopieren nur durch; decrypted wird erst
18
18
  // in den list-queries.
19
- import { insertOnConflictDoNothing, requireEntityTableMeta, upsertOnConflict, } from "@cosmicdrift/kumiko-framework/bun-db";
20
- import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
19
+ import { buildEntityTable, insertOnConflictDoNothing, requireEntityTableMeta, upsertOnConflict, } from "@cosmicdrift/kumiko-framework/db";
21
20
  import { defineApply } from "@cosmicdrift/kumiko-framework/engine";
22
21
  import { inboundMessageEntity, mailAccountEntity, mailThreadEntity } from "./entities.js";
23
22
  // Drizzle-table-instances aus den entity-shapes — geteilt zwischen
@@ -43,8 +43,8 @@
43
43
  // as the watcher state lives, including across reconnect backoff, not
44
44
  // only while the connection is open. Losing the claim (Redis outage, TTL
45
45
  // exceeded) tears down the local watcher instead of racing a new holder.
46
- import { fetchOne, insertOne, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
47
46
  import { configuredPiiSubjectKms, decryptPiiFieldValues, } from "@cosmicdrift/kumiko-framework/crypto";
47
+ import { fetchOne, insertOne, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/db";
48
48
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
49
49
  import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
50
50
  import { InboundMailAccountStatuses, InboundMailFoundationHandlers } from "./constants.js";
@@ -4,6 +4,10 @@ export { setImapMailHostLookup } from "./imap-client.js";
4
4
  /** Exportiert für den Live-Test (imap-live.integration.test.ts) —
5
5
  * Apps nutzen das Feature, nie das Plugin direkt. */
6
6
  export declare const imapInboundMailPlugin: InboundMailProviderPlugin;
7
+ export declare function createInboundProviderImapFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
8
+ readonly exports: void;
9
+ };
10
+ /** @deprecated Use createInboundProviderImapFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
7
11
  export declare const inboundProviderImapFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
8
12
  readonly exports: void;
9
13
  };
@@ -217,15 +217,19 @@ export const imapInboundMailPlugin = {
217
217
  // Formular (connect-account + Secret-Write); XOAUTH2-Token-Flows
218
218
  // gehören den OAuth-Providern (M365/Gmail).
219
219
  };
220
- export const inboundProviderImapFeature = defineFeature(FEATURE_NAME, (r) => {
221
- r.describe('Registers the `"imap"` provider for `inbound-mail-foundation` using imapflow — password/app-password auth covers classic IMAP hosts without any OAuth (plus an XOAUTH2 fallback consuming an access token from the secret slot). Incremental sync via a UIDVALIDITY:lastUid cursor (UIDVALIDITY change triggers a cursor-invalid full resync), initial backfill bounded by the foundation backfill window, and live push via IMAP IDLE for the watch supervisor. Store the per-account connection JSON (host/port/secure/user/password) in the account credential secret slot before the first sync.');
222
- r.uiHints({
223
- displayLabel: "Inbound Mail · IMAP",
224
- category: "notifications",
225
- recommended: false,
226
- });
227
- r.requires({ features: ["inbound-mail-foundation"] });
228
- r.requires({ features: ["secrets"] });
229
- r.envSchema(mailAllowedPrivateHostsEnvSchema);
230
- r.useExtension(INBOUND_MAIL_PROVIDER_EXTENSION, IMAP_PROVIDER_KEY, imapInboundMailPlugin);
231
- });
220
+ export function createInboundProviderImapFeature() {
221
+ return defineFeature(FEATURE_NAME, (r) => {
222
+ r.describe('Registers the `"imap"` provider for `inbound-mail-foundation` using imapflow — password/app-password auth covers classic IMAP hosts without any OAuth (plus an XOAUTH2 fallback consuming an access token from the secret slot). Incremental sync via a UIDVALIDITY:lastUid cursor (UIDVALIDITY change triggers a cursor-invalid full resync), initial backfill bounded by the foundation backfill window, and live push via IMAP IDLE for the watch supervisor. Store the per-account connection JSON (host/port/secure/user/password) in the account credential secret slot before the first sync.');
223
+ r.uiHints({
224
+ displayLabel: "Inbound Mail · IMAP",
225
+ category: "notifications",
226
+ recommended: false,
227
+ });
228
+ r.requires({ features: ["inbound-mail-foundation"] });
229
+ r.requires({ features: ["secrets"] });
230
+ r.envSchema(mailAllowedPrivateHostsEnvSchema);
231
+ r.useExtension(INBOUND_MAIL_PROVIDER_EXTENSION, IMAP_PROVIDER_KEY, imapInboundMailPlugin);
232
+ }, { dedupeOptions: {} });
233
+ }
234
+ /** @deprecated Use createInboundProviderImapFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
235
+ export const inboundProviderImapFeature = createInboundProviderImapFeature();
@@ -1,3 +1,3 @@
1
1
  export { type ImapCredentialDocument, imapCredentialDocumentSchema, type ParseCredentialResult, parseImapCredentialDocument, } from "./credential-document.js";
2
- export { IMAP_PROVIDER_KEY, inboundProviderImapFeature, setImapMailHostLookup } from "./feature.js";
2
+ export { createInboundProviderImapFeature, IMAP_PROVIDER_KEY, inboundProviderImapFeature, setImapMailHostLookup, } from "./feature.js";
3
3
  export { assertUidValidity, buildProviderMessageId, type ImapCursor, mapImapError, normalizeReferences, parseImapCursor, } from "./imap-client.js";
@@ -1,4 +1,4 @@
1
1
  // Public API of the inbound-provider-imap bundled-feature.
2
2
  export { imapCredentialDocumentSchema, parseImapCredentialDocument, } from "./credential-document.js";
3
- export { IMAP_PROVIDER_KEY, inboundProviderImapFeature, setImapMailHostLookup } from "./feature.js";
3
+ export { createInboundProviderImapFeature, IMAP_PROVIDER_KEY, inboundProviderImapFeature, setImapMailHostLookup, } from "./feature.js";
4
4
  export { assertUidValidity, buildProviderMessageId, mapImapError, normalizeReferences, parseImapCursor, } from "./imap-client.js";
@@ -18,6 +18,10 @@ export declare function isWatching(accountId: string): boolean;
18
18
  * nie zwischen Tests teilen). */
19
19
  export declare function resetInboundInMemory(): void;
20
20
  export declare const inMemoryInboundMailPlugin: InboundMailProviderPlugin;
21
+ export declare function createInboundProviderInMemoryFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
22
+ readonly exports: void;
23
+ };
24
+ /** @deprecated Use createInboundProviderInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
21
25
  export declare const inboundProviderInMemoryFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
22
26
  readonly exports: void;
23
27
  };
@@ -103,13 +103,17 @@ export const inMemoryInboundMailPlugin = {
103
103
  // =============================================================================
104
104
  // Feature-definition
105
105
  // =============================================================================
106
- export const inboundProviderInMemoryFeature = defineFeature(FEATURE_NAME, (r) => {
107
- r.describe('Registers a scriptable in-process `"inmemory"` provider for `inbound-mail-foundation`. Seed messages with `seedInboundMessage(accountId, msg)` — an active watch pushes them immediately (IDLE simulation) and the cursor-based `fetch` re-delivers them on the reconciliation path, exercising the foundation dedup guarantee. Error injection via `failNextFetchWith`/`failNextVerifyWith`/`emitWatchError`; reset state with `resetInboundInMemory()`. For tests, demos and sample apps — not for production.');
108
- r.uiHints({
109
- displayLabel: "Inbound Mail · In-Memory Provider",
110
- category: "notifications",
111
- recommended: false,
112
- });
113
- r.requires({ features: ["inbound-mail-foundation"] });
114
- r.useExtension("inboundMailProvider", INMEMORY_PROVIDER_KEY, inMemoryInboundMailPlugin);
115
- });
106
+ export function createInboundProviderInMemoryFeature() {
107
+ return defineFeature(FEATURE_NAME, (r) => {
108
+ r.describe('Registers a scriptable in-process `"inmemory"` provider for `inbound-mail-foundation`. Seed messages with `seedInboundMessage(accountId, msg)` — an active watch pushes them immediately (IDLE simulation) and the cursor-based `fetch` re-delivers them on the reconciliation path, exercising the foundation dedup guarantee. Error injection via `failNextFetchWith`/`failNextVerifyWith`/`emitWatchError`; reset state with `resetInboundInMemory()`. For tests, demos and sample apps — not for production.');
109
+ r.uiHints({
110
+ displayLabel: "Inbound Mail · In-Memory Provider",
111
+ category: "notifications",
112
+ recommended: false,
113
+ });
114
+ r.requires({ features: ["inbound-mail-foundation"] });
115
+ r.useExtension("inboundMailProvider", INMEMORY_PROVIDER_KEY, inMemoryInboundMailPlugin);
116
+ }, { dedupeOptions: {} });
117
+ }
118
+ /** @deprecated Use createInboundProviderInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
119
+ export const inboundProviderInMemoryFeature = createInboundProviderInMemoryFeature();
@@ -1 +1 @@
1
- export { emitWatchError, failNextFetchWith, failNextVerifyWith, INMEMORY_PROVIDER_KEY, inboundProviderInMemoryFeature, isWatching, resetInboundInMemory, seedInboundMessage, } from "./feature.js";
1
+ export { createInboundProviderInMemoryFeature, emitWatchError, failNextFetchWith, failNextVerifyWith, INMEMORY_PROVIDER_KEY, inboundProviderInMemoryFeature, isWatching, resetInboundInMemory, seedInboundMessage, } from "./feature.js";
@@ -1,2 +1,2 @@
1
1
  // Public API of the inbound-provider-inmemory bundled-feature.
2
- export { emitWatchError, failNextFetchWith, failNextVerifyWith, INMEMORY_PROVIDER_KEY, inboundProviderInMemoryFeature, isWatching, resetInboundInMemory, seedInboundMessage, } from "./feature.js";
2
+ export { createInboundProviderInMemoryFeature, emitWatchError, failNextFetchWith, failNextVerifyWith, INMEMORY_PROVIDER_KEY, inboundProviderInMemoryFeature, isWatching, resetInboundInMemory, seedInboundMessage, } from "./feature.js";
@@ -9,7 +9,7 @@
9
9
  //
10
10
  // deleteManyBatched (typed query API, no raw SQL in this file) chunks each
11
11
  // delete so a large backlog doesn't hold one lock for the whole sweep.
12
- import { deleteManyBatched } from "@cosmicdrift/kumiko-framework/bun-db";
12
+ import { deleteManyBatched } from "@cosmicdrift/kumiko-framework/db";
13
13
  import { jobRunLogsTable, jobRunsTable } from "../../job-run-table.js";
14
14
  import { tenantJobFailuresTable } from "../../tenant-job-failure-table.js";
15
15
  import { tenantJobRunsTable } from "../../tenant-job-run-table.js";
@@ -11,7 +11,7 @@
11
11
  // schema/migration change, no web filter-dropdown/status-enum update, and
12
12
  // the run becomes retriable via the existing jobs:write:retry gate
13
13
  // (retry.write.ts only allows retry from "failed").
14
- import { deleteManyBatched, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
14
+ import { deleteManyBatched, selectMany, updateMany } from "@cosmicdrift/kumiko-framework/db";
15
15
  import { mapWithConcurrency } from "../../../shared/index.js";
16
16
  import { DEFAULT_JOB_RUN_RETENTION_DAYS } from "../../handlers/retention-cleanup.job.js";
17
17
  import { encryptFailureError } from "../../job-run-logger.js";
@@ -1,4 +1,4 @@
1
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import * as z from "zod";
@@ -1,5 +1,4 @@
1
- import { countWhere, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { decodeCursor, encodeCursor } from "@cosmicdrift/kumiko-framework/db";
1
+ import { countWhere, decodeCursor, encodeCursor, selectMany, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { InternalError, ValidationError } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import * as z from "zod";
@@ -1,5 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import { isPiiCiphertext, PII_ERASED_SENTINEL } from "@cosmicdrift/kumiko-framework/crypto";
2
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { InternalError, NotFoundError, UnprocessableError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
5
5
  import { parseJsonOrThrow } from "@cosmicdrift/kumiko-framework/utils";
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import { serializeJobSubject } from "@cosmicdrift/kumiko-framework/jobs";
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import { serializeJobSubject } from "@cosmicdrift/kumiko-framework/jobs";
@@ -1,6 +1,5 @@
1
- import { deleteMany, fetchOne, insertMany, insertOnConflictDoNothing, insertOne, transaction, updateMany, upsertOnConflict, } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import { configuredPiiSubjectKms, encryptPiiValueForSubject, KeyErasedError, PII_ERASED_SENTINEL, } from "@cosmicdrift/kumiko-framework/crypto";
3
- import { acquireNamespacedAdvisoryLock } from "@cosmicdrift/kumiko-framework/db";
2
+ import { acquireNamespacedAdvisoryLock, deleteMany, fetchOne, insertMany, insertOnConflictDoNothing, insertOne, transaction, updateMany, upsertOnConflict, } from "@cosmicdrift/kumiko-framework/db";
4
3
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
5
4
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
6
5
  import { generateId } from "@cosmicdrift/kumiko-framework/utils";
@@ -1,5 +1,4 @@
1
- import { requireEntityTableMeta } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { index, instant, table as pgTable, serial, sql, text, uniqueIndex, uuid, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { index, instant, table as pgTable, requireEntityTableMeta, serial, sql, text, uniqueIndex, uuid, } from "@cosmicdrift/kumiko-framework/db";
3
2
  // The tenant's own view of a failed job (fw#3079). Direct-write store like
4
3
  // store_job_runs: job-run-logger.ts writes it from the BullMQ callbacks,
5
4
  // outside any dispatcher transaction.
@@ -1,5 +1,4 @@
1
- import { requireEntityTableMeta } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { index, instant, table as pgTable, serial, sql, text, uniqueIndex, uuid, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { index, instant, table as pgTable, requireEntityTableMeta, serial, sql, text, uniqueIndex, uuid, } from "@cosmicdrift/kumiko-framework/db";
3
2
  // The tenant's own view of a job's run state (fw#3616). Direct-write store
4
3
  // like store_job_runs, written by job-run-logger.ts from the runner callbacks.
5
4
  //
@@ -2,7 +2,7 @@ import { type AccessRule } from "@cosmicdrift/kumiko-framework/engine";
2
2
  type LedgerToggleable = {
3
3
  readonly default: boolean;
4
4
  };
5
- export declare const ledgerFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
5
+ declare const defaultLedgerFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
6
6
  readonly exports: void;
7
7
  };
8
8
  export type LedgerFeatureOptions = {
@@ -15,5 +15,9 @@ export type LedgerFeatureOptions = {
15
15
  * for fail-closed gating. Omit to keep the ledger always-on (default). */
16
16
  readonly toggleable?: LedgerToggleable;
17
17
  };
18
- export declare function createLedgerFeature(opts?: LedgerFeatureOptions): typeof ledgerFeature;
18
+ export declare function createLedgerFeature(opts?: LedgerFeatureOptions): typeof defaultLedgerFeature;
19
+ /** @deprecated Use createLedgerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
20
+ export declare const ledgerFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
21
+ readonly exports: void;
22
+ };
19
23
  export {};
@@ -90,7 +90,7 @@ function registerLedger(r, access, toggleable) {
90
90
  r.queryHandler(createIncomeStatementHandler(access));
91
91
  r.queryHandler(createBalanceSheetHandler(access));
92
92
  }
93
- export const ledgerFeature = defineFeature(LEDGER_FEATURE_NAME, (r) => registerLedger(r, DEFAULT_LEDGER_ACCESS, undefined));
93
+ const defaultLedgerFeature = defineFeature(LEDGER_FEATURE_NAME, (r) => registerLedger(r, DEFAULT_LEDGER_ACCESS, undefined));
94
94
  function resolveAccess(opts) {
95
95
  if (opts.access !== undefined)
96
96
  return opts.access;
@@ -102,8 +102,10 @@ function resolveAccess(opts) {
102
102
  // rebuild). access/roles/toggleable build a fresh feature-definition.
103
103
  export function createLedgerFeature(opts = {}) {
104
104
  if (opts.access === undefined && opts.roles === undefined && opts.toggleable === undefined) {
105
- return ledgerFeature;
105
+ return defaultLedgerFeature;
106
106
  }
107
107
  const access = resolveAccess(opts);
108
108
  return defineFeature(LEDGER_FEATURE_NAME, (r) => registerLedger(r, access, opts.toggleable));
109
109
  }
110
+ /** @deprecated Use createLedgerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
111
+ export const ledgerFeature = createLedgerFeature();
@@ -46,6 +46,10 @@ export type MailTransportContext = {
46
46
  */
47
47
  export type MailTransportPlugin = {
48
48
  readonly build: (ctx: MailTransportContext, tenantId: string) => Promise<EmailTransport>;
49
+ /** `false` keeps the provider out of the generated settings: it can still be set by a
50
+ * seed or config write, but a tenant admin is never offered it (e.g. a test inbox
51
+ * that swallows every mail). */
52
+ readonly selectableInSettings?: false;
49
53
  };
50
54
  export declare function isMailTransportPlugin(o: unknown): o is MailTransportPlugin;
51
55
  declare module "@cosmicdrift/kumiko-framework/engine" {
@@ -53,6 +57,13 @@ declare module "@cosmicdrift/kumiko-framework/engine" {
53
57
  [MAIL_TRANSPORT_EXTENSION]: MailTransportPlugin;
54
58
  }
55
59
  }
60
+ export declare function createMailFoundationFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
61
+ readonly exports: {
62
+ /** Config-key-handle for the provider-selector. */
63
+ providerConfigKey: import("@cosmicdrift/kumiko-types/config").ConfigKeyHandle<"text">;
64
+ };
65
+ };
66
+ /** @deprecated Use createMailFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
56
67
  export declare const mailFoundationFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
57
68
  readonly exports: {
58
69
  /** Config-key-handle for the provider-selector. */
@@ -33,6 +33,7 @@
33
33
  import { withPiiCiphertextGuard, } from "@cosmicdrift/kumiko-bundled-features/channel-email";
34
34
  import { requireDefined } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
35
35
  import { access, createSystemUser, createTenantConfig, defineFeature, } from "@cosmicdrift/kumiko-framework/engine";
36
+ import { MAIL_FOUNDATION_I18N } from "./i18n.js";
36
37
  const FEATURE_NAME = "mail-foundation";
37
38
  // Extension-point name for transport-provider plugins (mail-transport-smtp,
38
39
  // mail-transport-brevo-api, ...).
@@ -45,47 +46,56 @@ export function isMailTransportPlugin(o) {
45
46
  // =============================================================================
46
47
  // Feature-definition
47
48
  // =============================================================================
48
- export const mailFoundationFeature = defineFeature(FEATURE_NAME, (r) => {
49
- r.describe("Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending \u2014 use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences. Pass `tenantMailTransport` as `tenantTransport` to `createChannelEmailFeature` so a tenant with a provider configured sends delivery mails through its own transport and other tenants through the app transport.");
50
- r.uiHints({
51
- displayLabel: "Mail Transport Foundation",
52
- category: "notifications",
53
- recommended: false,
54
- });
55
- r.requires({ features: ["config"] });
56
- // Plugin extension-point. Provider-features register here. The
57
- // entityName at registration time becomes the value tenants pick in
58
- // `provider` config-key (e.g. "smtp", "brevo-api").
59
- r.extendsRegistrar(MAIL_TRANSPORT_EXTENSION, {
60
- onRegister: () => {
61
- // No side-effects at register-time — the registry stores the
62
- // usage, factory looks it up at request-time. Same shape as
63
- // delivery's extendsRegistrar.
64
- },
65
- });
66
- // Provider-selector. Default empty so the boot-validator throws if a
67
- // tenant tries to send mail without first picking + setting up a
68
- // provider — better than a silent fallback. The actual list of valid
69
- // values lives in the registered plugins, not here — Designer-UI can
70
- // render `getExtensionUsages("mailTransport").map(u => u.entityName)`
71
- // as the option-list.
72
- const providerConfigKey = r.config("provider", createTenantConfig("text", {
73
- default: "",
74
- // required: ohne gewählten Provider wirft createTransportForTenant —
75
- // readiness meldete vorher ready:true und der erste Mail-Send
76
- // lieferte den UnconfiguredError (280/1).
77
- required: true,
78
- write: access.roles("TenantAdmin", "SystemAdmin"),
79
- read: access.roles("TenantAdmin", "SystemAdmin", "User"),
80
- }));
81
- // Readiness gating: transport-plugins' required keys/secrets count only
82
- // while their plugin is the one this key selects.
83
- r.extensionSelector(MAIL_TRANSPORT_EXTENSION, providerConfigKey);
84
- return {
85
- /** Config-key-handle for the provider-selector. */
86
- providerConfigKey,
87
- };
88
- });
49
+ export function createMailFoundationFeature() {
50
+ return defineFeature(FEATURE_NAME, (r) => {
51
+ r.describe("Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending \u2014 use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences. Pass `tenantMailTransport` as `tenantTransport` to `createChannelEmailFeature`: notifications declared with `tenantTransport: true` then go through the tenant's own transport when it has a provider and through the app transport otherwise. Tenant admins pick the provider and fill in its settings on the generated Email sending settings screen; an empty provider is a valid choice and means the platform sends.");
52
+ r.uiHints({
53
+ displayLabel: "Mail Transport Foundation",
54
+ category: "notifications",
55
+ recommended: false,
56
+ });
57
+ r.requires({ features: ["config"] });
58
+ // Plugin extension-point. Provider-features register here. The
59
+ // entityName at registration time becomes the value tenants pick in
60
+ // `provider` config-key (e.g. "smtp", "brevo-api").
61
+ r.extendsRegistrar(MAIL_TRANSPORT_EXTENSION, {
62
+ onRegister: () => {
63
+ // No side-effects at register-time — the registry stores the
64
+ // usage, factory looks it up at request-time. Same shape as
65
+ // delivery's extendsRegistrar.
66
+ },
67
+ });
68
+ // Empty = this tenant has no own provider: tenantMailTransport yields null and
69
+ // channel-email uses the app transport, so empty is a valid choice a tenant can
70
+ // return to (reset in the settings mask) and readiness must not flag it.
71
+ // createTransportForTenant still throws on empty.
72
+ const providerConfigKey = r.config("provider", createTenantConfig("text", {
73
+ default: "",
74
+ // No SystemAdmin: a platform-level provider would be inherited by every tenant,
75
+ // whose own credentials (tenant secrets) are missing, and break all their mail.
76
+ write: access.withSystem(access.roles("TenantAdmin")),
77
+ read: access.roles("TenantAdmin", "SystemAdmin", "User"),
78
+ mask: {
79
+ title: "mail-foundation.provider",
80
+ description: "mail-foundation.provider.description",
81
+ icon: "mail",
82
+ order: 1,
83
+ },
84
+ }));
85
+ // Readiness gating: transport-plugins' required keys/secrets count only
86
+ // while their plugin is the one this key selects.
87
+ r.extensionSelector(MAIL_TRANSPORT_EXTENSION, providerConfigKey);
88
+ r.translations({ keys: MAIL_FOUNDATION_I18N });
89
+ return {
90
+ /** Config-key-handle for the provider-selector. */
91
+ providerConfigKey,
92
+ };
93
+ }, { dedupeOptions: {} });
94
+ }
95
+ // The typed handles below come from one shared instance; each factory call builds its own handle objects.
96
+ const sharedMailFoundationFeature = createMailFoundationFeature();
97
+ /** @deprecated Use createMailFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
98
+ export const mailFoundationFeature = sharedMailFoundationFeature;
89
99
  // =============================================================================
90
100
  // Transport-factory — looks up the registered plugin + delegates
91
101
  // =============================================================================
@@ -121,7 +131,7 @@ export async function createTransportForTenantIfConfigured(ctx, tenantId, handle
121
131
  if (!ctx.registry) {
122
132
  throw new Error(`${handlerName}: ctx.registry is missing — required to look up registered mail-transport plugins`);
123
133
  }
124
- const provider = requireDefined(await ctxConfig(mailFoundationFeature.exports.providerConfigKey), FEATURE_NAME, "provider"); // @cast-boundary engine-payload
134
+ const provider = requireDefined(await ctxConfig(sharedMailFoundationFeature.exports.providerConfigKey), FEATURE_NAME, "provider"); // @cast-boundary engine-payload
125
135
  if (provider.length === 0)
126
136
  return null;
127
137
  const usages = ctx.registry.getExtensionUsages(MAIL_TRANSPORT_EXTENSION);
@@ -0,0 +1,14 @@
1
+ export declare const MAIL_FOUNDATION_I18N: {
2
+ readonly "screen:mail-foundation-tenant.title": {
3
+ readonly en: "Email sending";
4
+ };
5
+ readonly "mail-foundation.settings": {
6
+ readonly en: "Email sending";
7
+ };
8
+ readonly "mail-foundation.provider": {
9
+ readonly en: "Own mail server";
10
+ };
11
+ readonly "mail-foundation.provider.description": {
12
+ readonly en: "Without one, the platform sends the mails. Reset the choice to go back to that.";
13
+ };
14
+ };
@@ -0,0 +1,8 @@
1
+ export const MAIL_FOUNDATION_I18N = {
2
+ "screen:mail-foundation-tenant.title": { en: "Email sending" },
3
+ "mail-foundation.settings": { en: "Email sending" },
4
+ "mail-foundation.provider": { en: "Own mail server" },
5
+ "mail-foundation.provider.description": {
6
+ en: "Without one, the platform sends the mails. Reset the choice to go back to that.",
7
+ },
8
+ };
@@ -1 +1 @@
1
- export { createTransportForTenant, createTransportForTenantIfConfigured, isMailTransportPlugin, MAIL_TRANSPORT_EXTENSION, type MailTransportContext, type MailTransportPlugin, mailFoundationFeature, type TenantMailTransportScope, tenantMailTransport, } from "./feature.js";
1
+ export { createMailFoundationFeature, createTransportForTenant, createTransportForTenantIfConfigured, isMailTransportPlugin, MAIL_TRANSPORT_EXTENSION, type MailTransportContext, type MailTransportPlugin, mailFoundationFeature, type TenantMailTransportScope, tenantMailTransport, } from "./feature.js";
@@ -6,4 +6,4 @@
6
6
  // up the registered transport-plugin, returns its EmailTransport
7
7
  // - `MailTransportPlugin` — type that provider-features implement
8
8
  // when registering via `r.useExtension("mailTransport", ...)`
9
- export { createTransportForTenant, createTransportForTenantIfConfigured, isMailTransportPlugin, MAIL_TRANSPORT_EXTENSION, mailFoundationFeature, tenantMailTransport, } from "./feature.js";
9
+ export { createMailFoundationFeature, createTransportForTenant, createTransportForTenantIfConfigured, isMailTransportPlugin, MAIL_TRANSPORT_EXTENSION, mailFoundationFeature, tenantMailTransport, } from "./feature.js";
@@ -9,6 +9,10 @@ export declare function getInbox(tenantId: string): readonly EmailMessage[];
9
9
  * Szenarien).
10
10
  */
11
11
  export declare function clearInbox(tenantId: string): void;
12
+ export declare function createMailTransportInMemoryFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
13
+ readonly exports: void;
14
+ };
15
+ /** @deprecated Use createMailTransportInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
12
16
  export declare const mailTransportInMemoryFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
13
17
  readonly exports: void;
14
18
  };
@@ -60,19 +60,29 @@ export function clearInbox(tenantId) {
60
60
  // =============================================================================
61
61
  // Feature-definition
62
62
  // =============================================================================
63
- export const mailTransportInMemoryFeature = defineFeature(FEATURE_NAME, (r) => {
64
- r.describe('Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).');
65
- // Kein requires auf "config" oder "secrets" — der
66
- // In-Memory-Transport hat keine Config (nichts zu konfigurieren) und
67
- // kein Secret. Der einzige hard-require ist mail-foundation, das den
68
- // extension-point "mailTransport" definiert.
69
- r.requires({ features: ["mail-foundation"] });
70
- const plugin = {
71
- build: async (_ctx, tenantId) => {
72
- // Returnt den per-tenant Buffer. Identitätsstabil zwischen calls
73
- // damit die Demo-Inbox accumulated bleibt.
74
- return getOrCreateTransportForTenant(tenantId);
75
- }, // @wrapper-known semantic-alias
76
- };
77
- r.useExtension(MAIL_TRANSPORT_EXTENSION, "inmemory", plugin);
78
- });
63
+ export function createMailTransportInMemoryFeature() {
64
+ return defineFeature(FEATURE_NAME, (r) => {
65
+ r.describe('Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).');
66
+ // Kein requires auf "config" oder "secrets" — der
67
+ // In-Memory-Transport hat keine Config (nichts zu konfigurieren) und
68
+ // kein Secret. Der einzige hard-require ist mail-foundation, das den
69
+ // extension-point "mailTransport" definiert.
70
+ r.requires({ features: ["mail-foundation"] });
71
+ const plugin = {
72
+ // Solon and studio mount it next to smtp in production; offering it there would
73
+ // let a tenant admin route every mail into process memory.
74
+ selectableInSettings: false,
75
+ build: async (_ctx, tenantId) => {
76
+ // Returns the per-tenant buffer. Identity-stable across calls so the
77
+ // demo inbox keeps accumulating.
78
+ return getOrCreateTransportForTenant(tenantId);
79
+ }, // @wrapper-known semantic-alias
80
+ };
81
+ r.useExtension(MAIL_TRANSPORT_EXTENSION, "inmemory", plugin);
82
+ r.translations({
83
+ keys: { "mail-transport-inmemory.settings": { en: "Test inbox (in memory)" } },
84
+ });
85
+ }, { dedupeOptions: {} });
86
+ }
87
+ /** @deprecated Use createMailTransportInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
88
+ export const mailTransportInMemoryFeature = createMailTransportInMemoryFeature();
@@ -1 +1 @@
1
- export { clearInbox, getInbox, mailTransportInMemoryFeature } from "./feature.js";
1
+ export { clearInbox, createMailTransportInMemoryFeature, getInbox, mailTransportInMemoryFeature, } from "./feature.js";
@@ -1,2 +1,2 @@
1
1
  // Public API of the mail-transport-inmemory bundled-feature.
2
- export { clearInbox, getInbox, mailTransportInMemoryFeature } from "./feature.js";
2
+ export { clearInbox, createMailTransportInMemoryFeature, getInbox, mailTransportInMemoryFeature, } from "./feature.js";
@@ -0,0 +1,7 @@
1
+ export declare const SMTP_CONFIG_KEYS: {
2
+ host: import("@cosmicdrift/kumiko-types/config").ConfigKeyDefinition<"text">;
3
+ port: import("@cosmicdrift/kumiko-types/config").ConfigKeyDefinition<"number">;
4
+ secure: import("@cosmicdrift/kumiko-types/config").ConfigKeyDefinition<"boolean">;
5
+ authUser: import("@cosmicdrift/kumiko-types/config").ConfigKeyDefinition<"text">;
6
+ from: import("@cosmicdrift/kumiko-types/config").ConfigKeyDefinition<"text">;
7
+ };
@@ -0,0 +1,65 @@
1
+ import { access, createTenantConfig } from "@cosmicdrift/kumiko-framework/engine";
2
+ // No SystemAdmin write: the password is a tenant secret, so platform-level SMTP keys
3
+ // could never form a working transport (see mail-foundation's provider key).
4
+ const tenantAdminWrite = access.withSystem(access.roles("TenantAdmin"));
5
+ const tenantAdminRead = access.roles("TenantAdmin", "SystemAdmin");
6
+ // required: true ↔ the requireNonEmpty calls in buildSmtpTransport — keep in sync.
7
+ export const SMTP_CONFIG_KEYS = {
8
+ host: createTenantConfig("text", {
9
+ required: true,
10
+ default: "",
11
+ write: tenantAdminWrite,
12
+ read: tenantAdminRead,
13
+ mask: {
14
+ title: "mail-transport-smtp.host",
15
+ description: "mail-transport-smtp.host.description",
16
+ icon: "server",
17
+ order: 1,
18
+ },
19
+ }),
20
+ port: createTenantConfig("number", {
21
+ default: 587,
22
+ bounds: { min: 1, max: 65535 },
23
+ write: tenantAdminWrite,
24
+ mask: {
25
+ title: "mail-transport-smtp.port",
26
+ description: "mail-transport-smtp.port.description",
27
+ icon: "hash",
28
+ order: 2,
29
+ },
30
+ }),
31
+ secure: createTenantConfig("boolean", {
32
+ default: false,
33
+ write: tenantAdminWrite,
34
+ mask: {
35
+ title: "mail-transport-smtp.secure",
36
+ description: "mail-transport-smtp.secure.description",
37
+ icon: "lock",
38
+ order: 3,
39
+ },
40
+ }),
41
+ authUser: createTenantConfig("text", {
42
+ required: true,
43
+ default: "",
44
+ write: tenantAdminWrite,
45
+ read: tenantAdminRead,
46
+ mask: {
47
+ title: "mail-transport-smtp.authUser",
48
+ description: "mail-transport-smtp.authUser.description",
49
+ icon: "user",
50
+ order: 4,
51
+ },
52
+ }),
53
+ from: createTenantConfig("text", {
54
+ required: true,
55
+ default: "",
56
+ write: tenantAdminWrite,
57
+ read: tenantAdminRead,
58
+ mask: {
59
+ title: "mail-transport-smtp.from",
60
+ description: "mail-transport-smtp.from.description",
61
+ icon: "mail",
62
+ order: 5,
63
+ },
64
+ }),
65
+ };