@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
@@ -1,6 +1,7 @@
1
1
  import type { EmailTransport } from "@cosmicdrift/kumiko-bundled-features/channel-email";
2
2
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { ConfigAccessor, NotifyFn, Registry, TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
+ import type { SecretsContext } from "@cosmicdrift/kumiko-framework/secrets";
4
5
  import { type GdprMailLocale } from "../email-templates.js";
5
6
  import type { SendDeletionRequestedEmailFn } from "../handlers/request-deletion.write.js";
6
7
  import type { SendExportFailedEmailFn, SendExportReadyEmailFn } from "../run-export-jobs.js";
@@ -19,7 +20,9 @@ export declare function makeDefaultDeletionRequestedEmail(notify: NotifyFn, defa
19
20
  export type DeletionExecutedMailDeps = {
20
21
  readonly registry: Registry;
21
22
  readonly db: DbConnection;
23
+ /** Used only when no email delivery channel is mounted. */
22
24
  readonly resolveTransport: (tenantId: string) => Promise<EmailTransport>;
23
25
  readonly configFor: (tenantId: TenantId) => ConfigAccessor | undefined;
26
+ readonly secrets?: SecretsContext;
24
27
  };
25
28
  export declare function makeDefaultDeletionExecutedEmail(deps: DeletionExecutedMailDeps, defaults?: GdprMailDefaults): SendDeletionExecutedEmailFn;
@@ -7,11 +7,11 @@
7
7
  // to the user, so delivery resolves the address and the attempt row carries
8
8
  // the recipientId the forget path erases. Deletion-executed cannot: the user
9
9
  // is gone by then, and an attempt row written after the erasure would be new
10
- // personal data. It renders the seeded template and sends over the tenant's
11
- // mail transport, with no delivery log.
10
+ // personal data. It renders the seeded template and sends it straight through the
11
+ // email channel (or, without one, the tenant's mail transport), with no delivery log.
12
12
  import { MAIL_TRANSPORT_EXTENSION } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
13
13
  import { hasMailTranslations, mailT } from "@cosmicdrift/kumiko-framework/i18n";
14
- import { DELIVERY_CHANNEL_EXTENSION } from "../../delivery/index.js";
14
+ import { buildChannelContext, collectChannels, DELIVERY_CHANNEL_EXTENSION, EMAIL_CHANNEL_NAME, } from "../../delivery/index.js";
15
15
  import { collectRendererPlugins, createRendererFoundationApi, } from "../../renderer-foundation/index.js";
16
16
  import { formatGdprMailTimestamp, normalizeGdprMailLocale, } from "../email-templates.js";
17
17
  import { GdprMailNotificationTypes, gdprMailTemplateLocale } from "../mail-notifications.js";
@@ -88,6 +88,9 @@ export function makeDefaultDeletionRequestedEmail(notify, defaults = {}) {
88
88
  });
89
89
  };
90
90
  }
91
+ function emailChannelOf(registry) {
92
+ return collectChannels(registry).find((channel) => channel.name === EMAIL_CHANNEL_NAME);
93
+ }
91
94
  export function makeDefaultDeletionExecutedEmail(deps, defaults = {}) {
92
95
  return async (args) => {
93
96
  // Der User ist global, der Mail-Transport per-Tenant — wir senden ueber den
@@ -121,6 +124,25 @@ export function makeDefaultDeletionExecutedEmail(deps, defaults = {}) {
121
124
  if (rendered.kind !== "mail") {
122
125
  throw new Error(`deletion-executed mail: renderer answered with kind "${rendered.kind}"`);
123
126
  }
127
+ // The channel picks the same transport as every other mail of this notification
128
+ // (the app transport unless it is declared tenantTransport), so a tenant without
129
+ // its own mail provider still gets the confirmation. channel.send writes no attempt row.
130
+ const channel = emailChannelOf(deps.registry);
131
+ if (channel !== undefined) {
132
+ const result = await channel.send(args.userEmail, {
133
+ notificationType: type,
134
+ title: rendered.subject,
135
+ body: undefined,
136
+ data: undefined,
137
+ locale,
138
+ }, buildChannelContext(deps.db, deps.registry, undefined, tenantId, deps.secrets, config), { subject: rendered.subject, html: rendered.html, text: rendered.text });
139
+ if (result.status !== "sent") {
140
+ // No address in the message: the user is already erased.
141
+ throw new Error(`deletion-executed mail not sent: ${result.error ?? result.status}`);
142
+ }
143
+ // skip: the channel delivered it, the transport fallback below is for apps without one
144
+ return;
145
+ }
124
146
  const transport = await deps.resolveTransport(tenantId);
125
147
  await transport.send({
126
148
  to: args.userEmail,
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import type { SessionUser } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { type WriteFailure } from "@cosmicdrift/kumiko-framework/errors";
4
4
  export declare const TARGET_USER_NOT_IN_ADMIN_TENANT: "target_user_not_in_admin_tenant";
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { AccessDeniedError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
3
3
  import { tenantMembershipsTable } from "../../tenant/index.js";
4
4
  import { isSystemAdminActor } from "./is-admin-actor.js";
@@ -3,6 +3,7 @@ import { type WritePurpose } from "@cosmicdrift/kumiko-framework/db";
3
3
  export type UpdateUserLifecycleOptions = {
4
4
  readonly expect?: Readonly<Record<string, string | number | boolean | null>>;
5
5
  readonly writePurpose?: WritePurpose;
6
+ readonly includeDeleted?: boolean;
6
7
  };
7
8
  export declare function updateUserLifecycle(conn: DbRunner, userId: string, changes: Record<string, unknown>, options?: UpdateUserLifecycleOptions): Promise<{
8
9
  readonly applied: boolean;
@@ -1,5 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { createEventStoreExecutor, createTenantDb, selectMany, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { createSystemUser, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { USER_STATUS, userEntity, userTable } from "../../user/index.js";
@@ -38,11 +37,12 @@ export async function updateUserLifecycle(conn, userId, changes, options) {
38
37
  // (restrict/lift-restriction/grace-period/cancel/forget) that holds no row
39
38
  // version to pass as `payload.version`, which update() requires otherwise.
40
39
  // Callers needing a guard use `options.expect` instead.
41
- const tenantDb = createTenantDb(conn, SYSTEM_TENANT_ID, "system");
40
+ const tenantDb = createTenantDb({ db: conn, tenantId: SYSTEM_TENANT_ID, mode: "system" });
42
41
  const result = await userExecutor.update({ id: userId, changes }, createSystemUser(SYSTEM_TENANT_ID), tenantDb, {
43
42
  skipOptimisticLock: true,
44
43
  ...(options?.expect && { expect: options.expect }),
45
44
  ...(options?.writePurpose && { writePurpose: options.writePurpose }),
45
+ ...(options?.includeDeleted && { includeDeleted: true }),
46
46
  });
47
47
  if (result.isSuccess)
48
48
  return { applied: true };
@@ -43,10 +43,9 @@
43
43
  // **Storage-Cleanup:** dritter Pass loescht abgelaufene downloadStorageKeys
44
44
  // (`expiresAt + exportStorageCleanupGraceHours < now`) — abgelaufene ZIPs
45
45
  // auf S3 sollen nicht ewig liegen.
46
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
47
46
  import { addDurationSpec } from "@cosmicdrift/kumiko-framework/compliance";
48
47
  import { PII_ERASED_SENTINEL } from "@cosmicdrift/kumiko-framework/crypto";
49
- import { createEventStoreExecutor, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
48
+ import { createEventStoreExecutor, createTenantDb, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
50
49
  import { createSystemUser } from "@cosmicdrift/kumiko-framework/engine";
51
50
  import { createZipStream, tenantExportPrefix, } from "@cosmicdrift/kumiko-framework/files";
52
51
  import { resolveProfileForTenant } from "../compliance-profiles/index.js";
@@ -547,7 +546,7 @@ function reportCleanupLastRun(metrics, now) {
547
546
  // Stream-Counter konsistent bleibt (Memory feedback_event_store_tenant_consistency).
548
547
  // @wrapper-known semantic-alias
549
548
  function systemTenantDb(db, tenantId) {
550
- return createTenantDb(db, tenantId, "system");
549
+ return createTenantDb({ db, tenantId, mode: "system" });
551
550
  }
552
551
  function buildExportStorageKey(job) {
553
552
  return `${tenantExportPrefix(job.requestedFromTenantId)}${job.id}.zip`;
@@ -34,9 +34,8 @@ import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
34
34
  // gesammelt + zurueckgegeben fuer Operator-Visibility. Ein User mit
35
35
  // gefailten Hooks bleibt im DeletionRequested-Status (next Lauf
36
36
  // retried automatisch).
37
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
38
37
  import { configuredPiiSubjectKms, subjectIdToKey, } from "@cosmicdrift/kumiko-framework/crypto";
39
- import { createTenantDb, entityEventName, executeRawQuery, nullBlindIndexesForSubject, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
38
+ import { createTenantDb, entityEventName, executeRawQuery, fetchOne, nullBlindIndexesForSubject, selectMany, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
40
39
  import { EXT_USER_DATA, EXT_USER_DATA_ORDER, extensionUsageEscapeHatchReason, } from "@cosmicdrift/kumiko-framework/engine";
41
40
  import { createEscapeHatchReporter, UNATTRIBUTED_ACTOR, } from "@cosmicdrift/kumiko-framework/pipeline";
42
41
  import { purgeSearchDocumentsForSubject, } from "@cosmicdrift/kumiko-framework/search";
@@ -54,9 +53,14 @@ function buildHookDb(db, tenantId, entry, args) {
54
53
  sink: args.escapeHatchAuditSink,
55
54
  log: args.escapeHatchAuditLog ?? createFallbackLogger("user-data-rights"),
56
55
  });
57
- return createTenantDb(db, tenantId, "tenant", undefined, undefined, undefined, {
58
- unsafeRaw: entry.escapeHatchReason !== undefined ? { reason: entry.escapeHatchReason } : undefined,
59
- report,
56
+ return createTenantDb({
57
+ db,
58
+ tenantId,
59
+ mode: "tenant",
60
+ grants: {
61
+ unsafeRaw: entry.escapeHatchReason !== undefined ? { reason: entry.escapeHatchReason } : undefined,
62
+ report,
63
+ },
60
64
  });
61
65
  }
62
66
  // EXT_USER_DATA delete-hooks default here; a hook that redacts data keyed on an
@@ -20,9 +20,8 @@ import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
20
20
  // **PII-Surface:** Hooks definieren selbst welche Felder ins Bundle
21
21
  // landen. user-data-rights-defaults/hooks/user.userdata-hook expose
22
22
  // expliziert KEIN passwordHash + KEINE roles (privileged columns).
23
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
24
23
  import { configuredPiiSubjectKms, decryptPiiFieldValues, isPiiCiphertext, } from "@cosmicdrift/kumiko-framework/crypto";
25
- import { collectEncryptedFieldNames, configuredEntityFieldEncryption, createTenantDb, decryptEntityFieldValues, } from "@cosmicdrift/kumiko-framework/db";
24
+ import { collectEncryptedFieldNames, configuredEntityFieldEncryption, createTenantDb, decryptEntityFieldValues, selectMany, } from "@cosmicdrift/kumiko-framework/db";
26
25
  import { EXT_USER_DATA, extensionUsageEscapeHatchReason, maskWriteOnlyFields, } from "@cosmicdrift/kumiko-framework/engine";
27
26
  import { createEscapeHatchReporter, UNATTRIBUTED_ACTOR, } from "@cosmicdrift/kumiko-framework/pipeline";
28
27
  import { tenantMembershipsTable } from "../tenant/index.js";
@@ -35,9 +34,14 @@ function buildHookDb(db, tenantId, entry, args) {
35
34
  sink: args.escapeHatchAuditSink,
36
35
  log: args.escapeHatchAuditLog ?? createFallbackLogger("user-data-rights"),
37
36
  });
38
- return createTenantDb(db, tenantId, "tenant", undefined, undefined, undefined, {
39
- unsafeRaw: entry.escapeHatchReason !== undefined ? { reason: entry.escapeHatchReason } : undefined,
40
- report,
37
+ return createTenantDb({
38
+ db,
39
+ tenantId,
40
+ mode: "tenant",
41
+ grants: {
42
+ unsafeRaw: entry.escapeHatchReason !== undefined ? { reason: entry.escapeHatchReason } : undefined,
43
+ report,
44
+ },
41
45
  });
42
46
  }
43
47
  /**
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { acquireNamespacedAdvisoryLock } from "@cosmicdrift/kumiko-framework/db";
1
+ import { acquireNamespacedAdvisoryLock, fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { createSystemUser, defineWriteHandler, parseTenantId, } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { InternalError, NotFoundError, UnprocessableError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { createSystemUser, defineWriteHandler, parseTenantId, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError, NotFoundError, UnprocessableError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import { cancelPendingInvitation, INVITATION_STATUS, tenantInvitationsTable, } from "../../tenant/index.js";
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
1
+ import { createEventStoreExecutor, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { access, createSystemUser, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { tenantMembershipsTable } from "../tenant/index.js";
@@ -23,7 +23,7 @@
23
23
  // + triggerEventRef + wakeAt=now() onto the matching pending row(s); the
24
24
  // existing resume-due-runs job (Phase 2) picks the row up on its next
25
25
  // cron tick — the one resume path stays exactly the one Phase 2 built.
26
- import { selectMany, updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
26
+ import { selectMany, updateMany } from "@cosmicdrift/kumiko-framework/db";
27
27
  import { evaluateEventMatch } from "@cosmicdrift/kumiko-framework/engine";
28
28
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
29
29
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
@@ -1,3 +1,7 @@
1
+ export declare function createWorkflowRunnerFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: void;
3
+ };
4
+ /** @deprecated Use createWorkflowRunnerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
5
  export declare const workflowRunnerFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
6
  readonly exports: void;
3
7
  };
@@ -32,45 +32,49 @@ import { workflowRunPendingTableMeta } from "./tables.js";
32
32
  // bundled feature's runtime name follows this convention, and
33
33
  // use-all-bundled's check-coverage matches exports to mounted features by it.
34
34
  const FEATURE_NAME = "workflow-runner";
35
- export const workflowRunnerFeature = defineFeature(FEATURE_NAME, (r) => {
36
- r.describe("Writes the run-envelope (`workflow.run-started` / `workflow.run-completed` / `workflow.run-failed`) for a workflow run onto its `workflow-run` aggregate stream. Provides `startAndRunWorkflow` and `registerEventTrigger` for consumer features to wire up `defineWorkflow`-based workflows against domain events. Registers no workflows itself. Runs the resume loop for suspended `wait`/`retry`/`waitForEvent` steps (`resume-due-runs` job + `resume-run` handler); `registerEventTrigger` wires an event-wakeup subscriber per workflow that declares `awaits` so a `waitForEvent` step resumes as soon as its awaited event arrives, not just on timeout.");
37
- r.uiHints({
38
- displayLabel: "Workflow Runner",
39
- category: "infrastructure",
40
- recommended: false,
41
- });
42
- // resume-run needs a full HandlerContext + ctx.systemDb (the pending-row
43
- // scan crosses whatever tenant the row belongs to relative to the job's
44
- // own tenant loop iteration) — same reasoning as tenant/feature.ts.
45
- r.systemScope();
46
- r.storeTable(workflowRunPendingTableMeta, {
47
- reason: "resume_loop.pending_suspended_steps",
48
- });
49
- registerWorkflowRunPendingProjection(r);
50
- r.writeHandler(resumeRunHandler);
51
- r.job("resume-due-runs", { trigger: { cron: "* * * * *" }, perTenant: true, concurrency: "skip" }, async (_payload, ctx) => {
52
- if (!ctx.systemDb) {
53
- throw new Error("resume-due-runs: ctx.systemDb required (r.systemScope() feature)");
54
- }
55
- const tenantId = ctx.systemUser?.tenantId ?? ctx._tenantId;
56
- if (tenantId === undefined) {
57
- // skip: cron fired without a perTenant fan-out tenant — nothing scoped
58
- return;
59
- }
60
- const dueRows = await selectDueWorkflowRunPending(ctx.systemDb.assertTenantMatch(tenantId));
61
- for (const row of dueRows) {
62
- try {
63
- await ctx.write("workflow-runner:write:resume-run", {
64
- runId: row.runId,
65
- stepIndex: row.stepIndex,
66
- });
35
+ export function createWorkflowRunnerFeature() {
36
+ return defineFeature(FEATURE_NAME, (r) => {
37
+ r.describe("Writes the run-envelope (`workflow.run-started` / `workflow.run-completed` / `workflow.run-failed`) for a workflow run onto its `workflow-run` aggregate stream. Provides `startAndRunWorkflow` and `registerEventTrigger` for consumer features to wire up `defineWorkflow`-based workflows against domain events. Registers no workflows itself. Runs the resume loop for suspended `wait`/`retry`/`waitForEvent` steps (`resume-due-runs` job + `resume-run` handler); `registerEventTrigger` wires an event-wakeup subscriber per workflow that declares `awaits` so a `waitForEvent` step resumes as soon as its awaited event arrives, not just on timeout.");
38
+ r.uiHints({
39
+ displayLabel: "Workflow Runner",
40
+ category: "infrastructure",
41
+ recommended: false,
42
+ });
43
+ // resume-run needs a full HandlerContext + ctx.systemDb (the pending-row
44
+ // scan crosses whatever tenant the row belongs to relative to the job's
45
+ // own tenant loop iteration) — same reasoning as tenant/feature.ts.
46
+ r.systemScope();
47
+ r.storeTable(workflowRunPendingTableMeta, {
48
+ reason: "resume_loop.pending_suspended_steps",
49
+ });
50
+ registerWorkflowRunPendingProjection(r);
51
+ r.writeHandler(resumeRunHandler);
52
+ r.job("resume-due-runs", { trigger: { cron: "* * * * *" }, perTenant: true, concurrency: "skip" }, async (_payload, ctx) => {
53
+ if (!ctx.systemDb) {
54
+ throw new Error("resume-due-runs: ctx.systemDb required (r.systemScope() feature)");
67
55
  }
68
- catch (error) {
69
- // skip: one row's dispatch failing (infra hiccup, not a business
70
- // outcome — resume-run itself never throws for expected cases)
71
- // must not stop the rest of this tenant's due rows from resuming.
72
- ctx.log.warn(`[workflow-runner:resume-due-runs] runId=${row.runId} stepIndex=${row.stepIndex} dispatch failed: ${String(error)}`);
56
+ const tenantId = ctx.systemUser?.tenantId ?? ctx._tenantId;
57
+ if (tenantId === undefined) {
58
+ // skip: cron fired without a perTenant fan-out tenant — nothing scoped
59
+ return;
73
60
  }
74
- }
75
- });
76
- });
61
+ const dueRows = await selectDueWorkflowRunPending(ctx.systemDb.assertTenantMatch(tenantId));
62
+ for (const row of dueRows) {
63
+ try {
64
+ await ctx.write("workflow-runner:write:resume-run", {
65
+ runId: row.runId,
66
+ stepIndex: row.stepIndex,
67
+ });
68
+ }
69
+ catch (error) {
70
+ // skip: one row's dispatch failing (infra hiccup, not a business
71
+ // outcome — resume-run itself never throws for expected cases)
72
+ // must not stop the rest of this tenant's due rows from resuming.
73
+ ctx.log.warn(`[workflow-runner:resume-due-runs] runId=${row.runId} stepIndex=${row.stepIndex} dispatch failed: ${String(error)}`);
74
+ }
75
+ }
76
+ });
77
+ }, { dedupeOptions: {} });
78
+ }
79
+ /** @deprecated Use createWorkflowRunnerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
80
+ export const workflowRunnerFeature = createWorkflowRunnerFeature();
@@ -29,7 +29,7 @@
29
29
  // pipeline's result for the skipped waitForEvent step itself (see
30
30
  // resultKey on steps/wait-for-event.ts) — pre-seeded into stepsAcc below so
31
31
  // a subsequent step's resolver can read `ctx.steps[awaits.someKey]`.
32
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
32
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
33
33
  import { buildPipelineSteps, computeDefinitionFingerprint, describeWorkflowStepError, getStep, runStepList, SYSTEM_ROLE, unwrapWorkflowStepError, WORKFLOW_AGGREGATE_TYPE, WORKFLOW_RESUMED_TYPE, WORKFLOW_RETRY_SCHEDULED_TYPE, WORKFLOW_RUN_COMPLETED_TYPE, WORKFLOW_RUN_FAILED_TYPE, WORKFLOW_RUN_STARTED_TYPE, WORKFLOW_WAITING_FOR_EVENT_TYPE, WorkflowStepError, } from "@cosmicdrift/kumiko-framework/engine";
34
34
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
35
35
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
@@ -1,4 +1,4 @@
1
1
  export { workflowRunAggregateId } from "./aggregate-id.js";
2
2
  export { registerEventTrigger } from "./event-trigger.js";
3
- export { workflowRunnerFeature } from "./feature.js";
3
+ export { createWorkflowRunnerFeature, workflowRunnerFeature } from "./feature.js";
4
4
  export { startAndRunWorkflow, type WorkflowRunCompletedPayload, type WorkflowRunFailedPayload, type WorkflowRunStartedPayload, WorkflowSuspensionUnsupportedError, } from "./runner.js";
@@ -1,5 +1,5 @@
1
1
  // Public API of the workflow-runner bundled-feature.
2
2
  export { workflowRunAggregateId } from "./aggregate-id.js";
3
3
  export { registerEventTrigger } from "./event-trigger.js";
4
- export { workflowRunnerFeature } from "./feature.js";
4
+ export { createWorkflowRunnerFeature, workflowRunnerFeature } from "./feature.js";
5
5
  export { startAndRunWorkflow, WorkflowSuspensionUnsupportedError, } from "./runner.js";
@@ -11,7 +11,7 @@
11
11
  // No resume logic here — framework#2513 Phase 2 owns the job that reads
12
12
  // this table and dispatches the actual resume. This projection only writes
13
13
  // the rows.
14
- import { deleteMany, fetchOne, upsertOnConflict } from "@cosmicdrift/kumiko-framework/bun-db";
14
+ import { deleteMany, fetchOne, upsertOnConflict } from "@cosmicdrift/kumiko-framework/db";
15
15
  import { WORKFLOW_RESUMED_TYPE, WORKFLOW_RETRY_SCHEDULED_TYPE, WORKFLOW_RUN_COMPLETED_TYPE, WORKFLOW_RUN_FAILED_TYPE, WORKFLOW_WAITING_FOR_EVENT_TYPE, WORKFLOW_WAITING_TYPE, } from "@cosmicdrift/kumiko-framework/engine";
16
16
  import { workflowRunPendingTable } from "./tables.js";
17
17
  async function upsertPending(tx, row) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-bundled-features",
3
- "version": "0.367.0",
3
+ "version": "0.369.0",
4
4
  "description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -226,6 +226,10 @@
226
226
  "types": "./dist/file-provider-s3/index.d.ts",
227
227
  "default": "./dist/file-provider-s3/index.js"
228
228
  },
229
+ "./file-provider-s3/lib": {
230
+ "types": "./dist/file-provider-s3/lib/index.d.ts",
231
+ "default": "./dist/file-provider-s3/lib/index.js"
232
+ },
229
233
  "./document-ingest-foundation": {
230
234
  "types": "./dist/document-ingest-foundation/index.d.ts",
231
235
  "default": "./dist/document-ingest-foundation/index.js"
@@ -524,12 +528,12 @@
524
528
  }
525
529
  },
526
530
  "dependencies": {
527
- "@cosmicdrift/kumiko-dispatcher-live": "0.367.0",
528
- "@cosmicdrift/kumiko-framework": "0.367.0",
529
- "@cosmicdrift/kumiko-headless": "0.367.0",
530
- "@cosmicdrift/kumiko-renderer": "0.367.0",
531
- "@cosmicdrift/kumiko-renderer-web": "0.367.0",
532
- "@cosmicdrift/kumiko-types": "0.367.0",
531
+ "@cosmicdrift/kumiko-dispatcher-live": "0.369.0",
532
+ "@cosmicdrift/kumiko-framework": "0.369.0",
533
+ "@cosmicdrift/kumiko-headless": "0.369.0",
534
+ "@cosmicdrift/kumiko-renderer": "0.369.0",
535
+ "@cosmicdrift/kumiko-renderer-web": "0.369.0",
536
+ "@cosmicdrift/kumiko-types": "0.369.0",
533
537
  "@mollie/api-client": "^4.5.0",
534
538
  "@node-rs/argon2": "^2.0.2",
535
539
  "@tiptap/core": "3.31.3",
@@ -772,6 +776,10 @@
772
776
  "types": "./dist/file-provider-s3/index.d.ts",
773
777
  "default": "./dist/file-provider-s3/index.js"
774
778
  },
779
+ "./file-provider-s3/lib": {
780
+ "types": "./dist/file-provider-s3/lib/index.d.ts",
781
+ "default": "./dist/file-provider-s3/lib/index.js"
782
+ },
775
783
  "./document-ingest-foundation": {
776
784
  "types": "./dist/document-ingest-foundation/index.d.ts",
777
785
  "default": "./dist/document-ingest-foundation/index.js"
@@ -1078,10 +1086,19 @@
1078
1086
  ],
1079
1087
  "devDependencies": {
1080
1088
  "@testing-library/user-event": "^14.6.1",
1081
- "@cosmicdrift/kumiko-locale-de": "0.367.0",
1082
- "@cosmicdrift/kumiko-locale-es": "0.367.0",
1083
- "@cosmicdrift/kumiko-renderer-mail-html": "0.367.0",
1089
+ "@cosmicdrift/kumiko-locale-de": "0.369.0",
1090
+ "@cosmicdrift/kumiko-locale-es": "0.369.0",
1091
+ "@cosmicdrift/kumiko-renderer-mail-html": "0.369.0",
1084
1092
  "jsqr": "^1.4.0",
1085
- "unpdf": "^1.8.1"
1093
+ "unpdf": "^1.8.1",
1094
+ "@cosmicdrift/kumiko-testing": "0.369.0"
1095
+ },
1096
+ "peerDependencies": {
1097
+ "@cosmicdrift/kumiko-testing": ">=0.366.0 <1.0.0"
1098
+ },
1099
+ "peerDependenciesMeta": {
1100
+ "@cosmicdrift/kumiko-testing": {
1101
+ "optional": true
1102
+ }
1086
1103
  }
1087
1104
  }
@@ -1,4 +1,17 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "improvement",
5
+ "title": "calendarCapReservationHandle consumes a reservation per unit",
6
+ "detail": "`reserveCalendarCapUsage` now returns `reservationId`. `calendarCapReservationHandle(ctx, reservationId, { capName, periodStartIso })` returns a handle with `consume(units)` (turns reserved units into booked ones, counter unchanged) and `release()` (gives back the unconsumed rest). A handler reserves the worst case before the job is dispatched, the job consumes per written unit, so parallel dispatches can no longer overshoot the hard cap and a retry only counts what was written.\n\n`consume` beyond the still-reserved rest throws `CapReservationOverConsumedError` (422, `cap_reservation_over_consumed`). `consume` against a settle tombstone throws `CapReservationSettledError` (422, `cap_reservation_settled`); `release` against it is a no-op. When the reservation outlived its TTL and was swept, `consume` books the units directly, the way settle does for a missing row, without a hard-cap check."
7
+ },
8
+ {
9
+ "version": "0.368.0",
10
+ "type": "fix",
11
+ "title": "Swept or released calendar reservations remember the units consume booked",
12
+ "detail": "The reservation row now stores `consumed_amount`. A release or the TTL sweep gives back only the unconsumed rest. If units were consumed, it keeps the row as a released tombstone (`released_at` set, `amount` 0) until the tombstone TTL passes, instead of deleting it. A later `settle` subtracts the consumed units from the booking, and a `consume` after the sweep books its units directly and is remembered the same way, so the counter ends at exactly the settled total. `settle` below the consumed units throws `CapSettleBelowConsumedError` (422, `cap_settle_below_consumed`) in every state. Expired released tombstones are deleted by the sweep.",
13
+ "migration": "Apps with cap-counter generate a migration for the new columns store_cap_reservations.consumed_amount (integer NOT NULL DEFAULT 0) and store_cap_reservations.released_at (kumiko migrate generate)."
14
+ },
2
15
  {
3
16
  "version": "0.366.0",
4
17
  "type": "fix",
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.369.0",
4
+ "type": "breaking",
5
+ "title": "The tenant mail transport applies per notification",
6
+ "detail": "r.notification(name, { tenantTransport: true }) marks a notification whose mails go through the tenant's own mail transport. channel-email consults its tenantTransport resolver only for these (also under a renamedFrom name); every other notification, such as password reset or sign-in mails, always takes the app transport, even when the tenant has a provider. With tenantTransport set, transport may be omitted: a mail that then has no transport fails with missing_credentials instead of throwing. The template test mail (template-resolver send-test) now gets the tenant config in its channel context and uses the template's notification, so it leaves through the same transport as the real mail.",
7
+ "migration": "Apps that pass tenantTransport to createChannelEmailFeature add `tenantTransport: true` to every r.notification whose mails should go through the tenant's provider; without the flag those mails now go through the app transport. Apps without an app SMTP server can drop transport and keep tenantTransport."
8
+ },
2
9
  {
3
10
  "version": "0.367.0",
4
11
  "type": "improvement",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "fix",
5
+ "title": "forget-subject closes the login door for users whose stream is already deleted",
6
+ "detail": "forget-subject returned 500 (\"user lifecycle update failed ... not_found\") when the user stream was deleted but the read_users status still read active, leaving sessions and PATs alive. The erasure now appends the status-deleted user.updated event to that stream too, so the login door closes, the handler returns 200 and a read_users rebuild keeps the state."
7
+ },
2
8
  {
3
9
  "version": "0.366.0",
4
10
  "type": "fix",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.369.0",
4
+ "type": "improvement",
5
+ "title": "Unsubscribe links in dev and a reusable result page",
6
+ "detail": "runDevApp accepts unsubscribe: { secret, tenantOrigin? } like runProdApp, mounts the unsubscribe routes and signs the links (base URL from auth.mail.baseUrl or APP_BASE_URL). Both share resolveUnsubscribeWiring from server-runtime. delivery exports renderUnsubscribeResultPage({ kind: \"unsubscribed\" | \"resubscribed\" | \"failed\", locale, resubscribeToken? }), the page the unsubscribe routes answer with, for apps that serve their own (e.g. legacy) unsubscribe links; without a resubscribeToken it offers no undo button."
7
+ },
2
8
  {
3
9
  "version": "0.367.0",
4
10
  "type": "improvement",
@@ -1 +1,10 @@
1
- []
1
+ [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "breaking",
5
+ "title": "The S3 file providers merge into createFileProviderS3Feature({ fromEnv })",
6
+ "detail": "createFileProviderS3Feature() mounts the per-tenant config provider as before. createFileProviderS3Feature({ fromEnv: true }) mounts the env-configured provider (feature name, provider key \"s3-env\" and requires unchanged). The S3 client helpers (createS3Provider, createS3ProviderFromEnv, parseS3EnvConfig, resolveForcePathStyle, S3ProviderConfig) move to the new subpath @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib.\n\nThe subpaths file-provider-s3-env and files-provider-s3 keep working as deprecated re-exports and are removed in the first release after 2026-10-29.\n\nold -> new:\n fileProviderS3EnvFeature from .../file-provider-s3-env -> createFileProviderS3Feature({ fromEnv: true }) from .../file-provider-s3\n fileProviderS3Feature -> createFileProviderS3Feature()\n @cosmicdrift/kumiko-bundled-features/files-provider-s3 -> @cosmicdrift/kumiko-bundled-features/file-provider-s3/lib",
7
+ "migration": "Run `bun kumiko-upgrade --apply`. It rewrites the imports and the env feature mount, and reports `typeof fileProviderS3EnvFeature` and re-exports of it with file and line.",
8
+ "codemod": "scripts/codemod/s3-imports.ts"
9
+ }
10
+ ]
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.369.0",
4
+ "type": "breaking",
5
+ "title": "Tenant admins edit their own SMTP server on the Email sending screen",
6
+ "detail": "mail-foundation's provider key and the SMTP keys (host, port, SSL/TLS, user name, sender address) carry settings masks, so the generated Settings-Hub shows tenant admins one Email sending form: the provider choice, the chosen provider's connection fields and its password, each field with a help text and every label in English, German and Spanish, saved together by one Save button in one /api/batch. Switching the provider swaps the fields at once; fields of a provider that is not selected are not saved. A selector owner's selection screen (`<owner>-tenant-selection`) now carries the plugins' config keys (field id `<owner>-<key>`) and secrets (field id `<plugin>-<key>`, listed in the new ConfigEditScreenDefinition.secretKeys) behind a visible condition on the provider field; the separate `<plugin>-tenant` and `<plugin>-tenant-secrets` screens and their dashboard panels are gone, and so is the `config.settings.saveProvider` label. A secret with its own writeRoles stays on the global secrets screen. Boot validation checks every secretKeys field (tenant scope, writeOnly text, declared secret). The configEdit renderer loads secretKeys fields from secrets:query:list (set or unset, no preview), writes them with secrets:write:set or secrets:write:delete in the same batch, and leaves hidden fields out. The provider key is no longer required: empty means the tenant has no own server and the platform sends, so readiness no longer reports it as missing (createTransportForTenant still throws on an empty provider). The provider and SMTP keys are written by TenantAdmin and the system identity, no longer by SystemAdmin, because a platform-level provider would reach every tenant without that tenant's password. The secrets set and delete handlers also admit the system identity, so server code stores a tenant secret via dispatchSystemWrite through the same key and value checks as an admin; the settings screens keep showing only the human roles. The provider choice shows each plugin's `<feature>.settings` name, also for a plugin without settings of its own, and keeps the English name when a locale feature mounted earlier declares the same key in its own language only. A MailTransportPlugin with `selectableInSettings: false` stays allowed on the server but is not offered in the form; the in-memory transport sets it, because apps mount it next to smtp in production and a tenant admin picking it would drop every mail. A plugin's secrets section takes an optional `<feature>.settings.secrets` title (SMTP password under \"SMTP sign-in\").",
7
+ "migration": "E2E specs that used the testIds `dashboard-panel-<plugin>-tenant`, `dashboard-panel-<plugin>-tenant-secrets` or the separate secret input of these screens address the fields of `<owner>-tenant-selection` instead (one Save). Code that wrote these keys as a SystemAdmin user writes them as the tenant's TenantAdmin or via dispatchSystemWrite. Apps that relied on readiness flagging an empty provider check it themselves."
8
+ },
2
9
  {
3
10
  "version": "0.326.1",
4
11
  "type": "fix",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "improvement",
5
+ "title": "The token list screen takes a description and slots via listScreen",
6
+ "detail": "createPersonalAccessTokensFeature({ listScreen: { description, slots } }) sets the i18n description and the slots (for example a header component) of the api-tokens list, so an app can show instructions above the list and use the bundled screen directly instead of embedding it in its own dashboard. Without the option nothing changes. Both bundled token screens are now marked agent: { expose: false }, since the mint screen reveals the token plaintext."
7
+ },
2
8
  {
3
9
  "version": "0.365.0",
4
10
  "type": "fix",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.369.0",
4
+ "type": "fix",
5
+ "title": "secrets:write:set and secrets:write:delete join the request transaction",
6
+ "detail": "Both handlers ran on the boot database connection, so in an /api/batch a later failing command rolled back the config writes but kept the stored secret. They now run on the request transaction (escape hatch unsafeRaw, reason documented on the handler), so a batch of config and secret writes is stored as a whole or not at all."
7
+ },
2
8
  {
3
9
  "version": "0.365.0",
4
10
  "type": "fix",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.368.0",
4
+ "type": "fix",
5
+ "title": "Soft-deleted users no longer count as active principals",
6
+ "detail": "A user deleted through the entity executor keeps its last status (usually active) with isDeleted set. principalStatusPlugin, the session checker and the PAT role resolver only looked at the status, so existing sessions and tokens of such a user stayed valid. They now treat isDeleted as blocked (session \"blocked\", PAT 401, principal_blocked for membership resolution) through the new isPrincipalRowBlocked predicate."
7
+ },
2
8
  {
3
9
  "version": "0.364.0",
4
10
  "type": "fix",
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.369.0",
4
+ "type": "fix",
5
+ "title": "The \"account deleted\" mail is sent through channel-email when delivery is mounted",
6
+ "detail": "The default mailer for the Art. 17 deletion confirmation called createTransportForTenant directly, which threw for a tenant without its own mail provider. With delivery and channel-email mounted it now sends through the email channel like the other GDPR mails, over the app transport, without writing a delivery-attempt row for the already erased user. Without channel-email the previous path stays."
7
+ },
2
8
  {
3
9
  "version": "0.367.0",
4
10
  "type": "fix",
@@ -1,3 +0,0 @@
1
- export declare const fileProviderS3EnvFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
- readonly exports: void;
3
- };