@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,4 +1,4 @@
1
- import { updateMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { updateMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import * as z from "zod";
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
4
  import { inAppMessagesTable } from "../tables.js";
@@ -1,5 +1,4 @@
1
- import { requireEntityTableMeta } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { boolean, index, instant, table as pgTable, serial, sql, text, uuid, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { boolean, index, instant, table as pgTable, requireEntityTableMeta, serial, sql, text, uuid, } from "@cosmicdrift/kumiko-framework/db";
3
2
  export const inAppMessagesTable = pgTable("in_app_messages", {
4
3
  id: serial("id").primaryKey(),
5
4
  tenantId: uuid("tenant_id").notNull(),
@@ -1,5 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import { resolveComplianceProfile, } from "@cosmicdrift/kumiko-framework/compliance";
2
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import * as z from "zod";
5
5
  import { parseComplianceProfileOverride } from "../_internal/parse-override.js";
@@ -1,5 +1,5 @@
1
1
  import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
2
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import * as z from "zod";
5
5
  import { tenantComplianceProfileTable } from "../schema/profile-selection.js";
@@ -1,6 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import { complianceProfileOverrideSchema, SELECTABLE_PROFILE_KEYS, } from "@cosmicdrift/kumiko-framework/compliance";
3
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
2
+ import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
4
3
  import { access, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
5
4
  import { UnprocessableError, validationErrorFromZod, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
6
5
  import * as z from "zod";
@@ -7,8 +7,8 @@
7
7
  // Pattern matched data-retention's `resolveRetentionPolicyForTenant`.
8
8
  // Beide Pfade nutzen `resolveComplianceProfile` aus framework/compliance,
9
9
  // also kein Drift zwischen Query-API und Worker-Pfad.
10
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
11
10
  import { resolveComplianceProfile, } from "@cosmicdrift/kumiko-framework/compliance";
11
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
12
12
  import { isTenantDb } from "../shared/index.js";
13
13
  import { parseComplianceProfileOverride } from "./_internal/parse-override.js";
14
14
  import { tenantComplianceProfileTable } from "./schema/profile-selection.js";
@@ -9,10 +9,8 @@
9
9
  // Profile-Wahl in einem Helper-Call).
10
10
  //
11
11
  // Pattern matched seedTextBlock aus text-content.
12
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
13
- import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
14
- import { runEventStoreSeed } from "@cosmicdrift/kumiko-framework/seeding";
15
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
12
+ import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
13
+ import { runEventStoreSeed, TestUsers, } from "@cosmicdrift/kumiko-framework/seeding";
16
14
  import { tenantComplianceProfileEntity, tenantComplianceProfileTable, } from "./schema/profile-selection.js";
17
15
  const executor = createEventStoreExecutor(tenantComplianceProfileTable, tenantComplianceProfileEntity, { entityName: "tenant-compliance-profile" });
18
16
  export async function seedComplianceProfile(db, opts) {
@@ -20,7 +18,7 @@ export async function seedComplianceProfile(db, opts) {
20
18
  // + Projection im selben Tenant-Bucket landen (Memory:
21
19
  // feedback_event_store_tenant_consistency).
22
20
  const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
23
- const tdb = createTenantDb(db, opts.tenantId, "system");
21
+ const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
24
22
  const overrideJson = opts.override !== undefined ? JSON.stringify(opts.override) : null;
25
23
  const existing = (await fetchOne(db, tenantComplianceProfileTable, {
26
24
  tenantId: opts.tenantId,
@@ -1,3 +1,11 @@
1
+ export declare function createComplianceProfilesOpsFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
+ readonly exports: {
3
+ queries: {
4
+ tenantsMissingProfile: import("@cosmicdrift/kumiko-types/handlers").HandlerRef;
5
+ };
6
+ };
7
+ };
8
+ /** @deprecated Use createComplianceProfilesOpsFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
1
9
  export declare const complianceProfilesOpsFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
10
  readonly exports: {
3
11
  queries: {
@@ -11,18 +11,22 @@
11
11
  // per-tenant picker (the vast majority) stay unaffected.
12
12
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
13
13
  import { tenantsMissingProfileQuery } from "./handlers/tenants-missing-profile.query.js";
14
- export const complianceProfilesOpsFeature = defineFeature("compliance-profiles-ops", (r) => {
15
- r.describe("Platform-wide SystemAdmin counterpart to `compliance-profiles`' `needs-profile` query (#2089): `tenants-missing-profile` lists every enabled tenant with no row in `tenantComplianceProfile` at all, tenant-wide instead of scoped to the caller's own tenant. Mount alongside `compliance-profiles` and `tenant` when an operator UI needs to see which tenants still silently run on `minimal-no-region`.");
16
- r.uiHints({
17
- displayLabel: "Compliance Profiles · Operator Visibility",
18
- category: "compliance",
19
- recommended: false,
20
- });
21
- r.systemScope();
22
- r.requires({ features: ["compliance-profiles"] });
23
- r.requires({ features: ["tenant"] });
24
- const queries = {
25
- tenantsMissingProfile: r.queryHandler(tenantsMissingProfileQuery),
26
- };
27
- return { queries };
28
- });
14
+ export function createComplianceProfilesOpsFeature() {
15
+ return defineFeature("compliance-profiles-ops", (r) => {
16
+ r.describe("Platform-wide SystemAdmin counterpart to `compliance-profiles`' `needs-profile` query (#2089): `tenants-missing-profile` lists every enabled tenant with no row in `tenantComplianceProfile` at all, tenant-wide instead of scoped to the caller's own tenant. Mount alongside `compliance-profiles` and `tenant` when an operator UI needs to see which tenants still silently run on `minimal-no-region`.");
17
+ r.uiHints({
18
+ displayLabel: "Compliance Profiles · Operator Visibility",
19
+ category: "compliance",
20
+ recommended: false,
21
+ });
22
+ r.systemScope();
23
+ r.requires({ features: ["compliance-profiles"] });
24
+ r.requires({ features: ["tenant"] });
25
+ const queries = {
26
+ tenantsMissingProfile: r.queryHandler(tenantsMissingProfileQuery),
27
+ };
28
+ return { queries };
29
+ }, { dedupeOptions: {} });
30
+ }
31
+ /** @deprecated Use createComplianceProfilesOpsFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
32
+ export const complianceProfilesOpsFeature = createComplianceProfilesOpsFeature();
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { configValuesTable } from "../../table.js";
3
3
  // Method-form so a tenant-mode TenantDb stays filtered. Two parallel selects
4
4
  // (disjoint via userId IS NULL) instead of one OR query: the buckets don't share
@@ -84,7 +84,7 @@ export const reencryptJob = async (rawPayload, ctx) => {
84
84
  function tdbFor(tenantId) {
85
85
  let existing = tdbCache.get(tenantId);
86
86
  if (!existing) {
87
- existing = createTenantDb(db, tenantId, "system");
87
+ existing = createTenantDb({ db, tenantId, mode: "system" });
88
88
  tdbCache.set(tenantId, existing);
89
89
  }
90
90
  return existing;
@@ -102,7 +102,7 @@ export const reencryptJob = async (rawPayload, ctx) => {
102
102
  // to acknowledge the cross-tenant scan below, never bound to a real
103
103
  // tenant's writes — sharing it with sdbFor(SYSTEM_TENANT_ID) would make a
104
104
  // write-path cache entry double as the scan's ack gate.
105
- const scanDb = createSystemDbView(createTenantDb(db, SYSTEM_TENANT_ID, "system"), undefined, reportEscapeHatchFor(SYSTEM_TENANT_ID));
105
+ const scanDb = createSystemDbView(createTenantDb({ db, tenantId: SYSTEM_TENANT_ID, mode: "system" }), undefined, reportEscapeHatchFor(SYSTEM_TENANT_ID));
106
106
  let alreadyCurrent = 0;
107
107
  const targetVersion = provider.currentVersion();
108
108
  // ponytail: one full candidate scan — config rows are operator-scale
@@ -1,6 +1,6 @@
1
1
  import { requestContext } from "@cosmicdrift/kumiko-framework/api";
2
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
3
2
  import { configuredPiiSubjectKms, decryptPiiValueForSubject, } from "@cosmicdrift/kumiko-framework/crypto";
3
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
4
4
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
5
5
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
6
6
  import { assertUnreachable, parseJsonOrThrow } from "@cosmicdrift/kumiko-framework/utils";
@@ -27,9 +27,8 @@ export const defaultTranslations = {
27
27
  "config.errors.invalidScope": "This scope is not allowed for this key.",
28
28
  "config.errors.unknownKey": "Unknown configuration key.",
29
29
  "config.errors.unknownExtensionPlugin": "This provider is not available.",
30
- "config.settings.extensionSelectorHint": "Choose a provider and save. Its settings appear below.",
30
+ "config.settings.extensionSelectorHint": "Choose a provider. Its settings appear below and are saved together with it.",
31
31
  "config.settings.provider": "Provider",
32
- "config.settings.saveProvider": "Save provider",
33
32
  "config.settings.audience.system": "Applies to every tenant unless a tenant sets its own value.",
34
33
  "config.settings.audience.tenant": "Applies to everyone in this tenant. Platform defaults are shown where nothing is set here.",
35
34
  "config.settings.audience.user": "Only applies to you.",
@@ -1,7 +1,7 @@
1
1
  // Shared helpers for the config feature's write + query handlers.
2
2
  // Extracted from set.write.ts so reset.write.ts + values.query.ts don't
3
3
  // have to cross-import from another handler file.
4
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
4
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
5
5
  import { ConfigScopes, extensionSelectorTargets, isEncryptedAtRest, SYSTEM_ROLE, SYSTEM_TENANT_ID, selectablePluginIds, } from "@cosmicdrift/kumiko-framework/engine";
6
6
  import { AccessDeniedError, InternalError, NotFoundError, UnprocessableError, ValidationError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
7
7
  import { assertUnreachable } from "@cosmicdrift/kumiko-framework/utils";
@@ -1,8 +1,7 @@
1
1
  import { requestContext } from "@cosmicdrift/kumiko-framework/api";
2
2
  import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
3
- import { fetchOne, runInSavepointIfSupported, runnerCanBeginTransaction, transaction, } from "@cosmicdrift/kumiko-framework/bun-db";
4
3
  import { computeBlindIndex, configuredBlindIndexKey, configuredPiiSubjectKms, subjectIdSchema, subjectIdToKey, } from "@cosmicdrift/kumiko-framework/crypto";
5
- import { nullBlindIndexesForSubject, recordEventsOwnedExclusivelyByTenant, recordRowExistsInTenant, recordRowOwningTenantId, subjectRowExistsInTenant, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
4
+ import { fetchOne, nullBlindIndexesForSubject, recordEventsOwnedExclusivelyByTenant, recordRowExistsInTenant, recordRowOwningTenantId, runInSavepointIfSupported, runnerCanBeginTransaction, subjectRowExistsInTenant, transaction, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
6
5
  import { defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
7
6
  import { AccessDeniedError, InternalError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
8
7
  import { appendDomainEventCore, assertIrreversibleOperationAllowed, } from "@cosmicdrift/kumiko-framework/pipeline";
@@ -254,7 +253,11 @@ async function closeUserLoginDoor(ctx, userId, outsideRunner, handlerTxRunner) {
254
253
  if (!userRow)
255
254
  return;
256
255
  const closeDoor = async (runner) => {
257
- await updateUserLifecycle(runner, userId, { status: USER_STATUS.Deleted }, { writePurpose: WritePurposes.erasure });
256
+ await updateUserLifecycle(runner, userId, { status: USER_STATUS.Deleted },
257
+ // includeDeleted: a user whose stream is already deleted but whose status
258
+ // still reads active would otherwise fail with not_found (500) and keep
259
+ // sessions and PATs alive.
260
+ { writePurpose: WritePurposes.erasure, includeDeleted: true });
258
261
  if (ctx.registry.features.has("personal-access-tokens")) {
259
262
  await revokeAllPatTokensForUser(runner, userId);
260
263
  }
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  export async function selectSerializedFieldDefinition(runner, tenantId, entityName, fieldKey) {
3
3
  const rows = await unsafeReadRetrying(runner, "SELECT serialized_field FROM read_custom_field_definitions WHERE entity_name = $1 AND field_key = $2 AND tenant_id = $3 LIMIT 1", [entityName, fieldKey, tenantId]);
4
4
  const first = rows[0]; // @cast-boundary db-row
@@ -1,4 +1,4 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { asRawClient } from "@cosmicdrift/kumiko-framework/db";
2
2
  function quoteTable(tableName) {
3
3
  return `"${tableName.replace(/"/g, '""')}"`;
4
4
  }
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  export async function countTenantFieldDefinitions(runner, tenantId) {
3
3
  // Active definitions only — delete soft-deletes (the deterministic stream is
4
4
  // kept so a re-define can restore it), so isDeleted rows must not consume quota.
@@ -1,5 +1,4 @@
1
- import { asRawClient, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { toPostgresArrayLiteral } from "@cosmicdrift/kumiko-framework/db";
1
+ import { asRawClient, toPostgresArrayLiteral, unsafeReadRetrying, } from "@cosmicdrift/kumiko-framework/db";
3
2
  export async function selectHostRowsWithCustomFields(db, tableName, tenantId) {
4
3
  const quoted = `"${tableName.replace(/"/g, '""')}"`;
5
4
  const rowsResult = await unsafeReadRetrying(db, `SELECT id, modified_at, custom_fields FROM ${quoted} WHERE tenant_id = $1 AND custom_fields IS NOT NULL`, [tenantId]);
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  function quoteTable(tableName) {
3
3
  return `"${tableName.replace(/"/g, '""')}"`;
4
4
  }
@@ -1,4 +1,4 @@
1
- export declare const customFieldsFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
1
+ declare const defaultCustomFieldsFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
2
2
  readonly exports: {
3
3
  setEvent: import("@cosmicdrift/kumiko-types/handlers").EventDef<{
4
4
  fieldKey: string;
@@ -44,4 +44,22 @@ export type CustomFieldsFeatureOptions = {
44
44
  readonly fieldDefinitionWriteRoles?: readonly string[];
45
45
  };
46
46
  export declare function resolveFieldDefinitionListRoles(opts: Pick<CustomFieldsFeatureOptions, "valueWriteRoles" | "fieldDefinitionListRoles" | "fieldDefinitionWriteRoles">): readonly string[];
47
- export declare function createCustomFieldsFeature(opts?: CustomFieldsFeatureOptions): typeof customFieldsFeature;
47
+ export declare function createCustomFieldsFeature(opts?: CustomFieldsFeatureOptions): typeof defaultCustomFieldsFeature;
48
+ /** @deprecated Use createCustomFieldsFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
49
+ export declare const customFieldsFeature: import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
50
+ readonly exports: {
51
+ setEvent: import("@cosmicdrift/kumiko-types/handlers").EventDef<{
52
+ fieldKey: string;
53
+ value?: unknown;
54
+ }, "custom-fields:event:custom-field-set">;
55
+ clearedEvent: import("@cosmicdrift/kumiko-types/handlers").EventDef<{
56
+ fieldKey: string;
57
+ }, "custom-fields:event:custom-field-cleared">;
58
+ fieldDefinitionDeletedEvent: import("@cosmicdrift/kumiko-types/handlers").EventDef<{
59
+ entityName: string;
60
+ fieldKey: string;
61
+ tenantId?: string | undefined;
62
+ }, "custom-fields:event:field-definition-deleted">;
63
+ };
64
+ };
65
+ export {};
@@ -33,7 +33,7 @@
33
33
  // `customFieldsField()` (jsonb) deklarieren.
34
34
  //
35
35
  // **Exports-Pattern (2026-05-23 refactor)**:
36
- // `customFieldsFeature.exports.{setEvent,clearedEvent,fieldDefinitionDeletedEvent}`
36
+ // `createCustomFieldsFeature().exports.{setEvent,clearedEvent,fieldDefinitionDeletedEvent}`
37
37
  // liefern typed EventDef-handles. Handler + wire-for-entity nutzen
38
38
  // `<event>.name` als compile-time-literal-typed qualified-string — keine
39
39
  // hand-gebauten Template-Literals mehr (T1 hat den toKebab-collapse-drift
@@ -117,12 +117,9 @@ function registerCustomFields(r, variant) {
117
117
  }));
118
118
  return { setEvent, clearedEvent, fieldDefinitionDeletedEvent };
119
119
  }
120
- // Singleton feature-definition mit typed exports. Handler + wire-for-entity
121
- // importieren diesen `customFieldsFeature` und greifen lazy in ihrer
122
- // runtime-arrow-fn auf `.exports.<event>.name` zu — der module-cycle
123
- // (feature.ts -> handlers/*.write.ts -> feature.ts) löst sich auf weil
124
- // kein top-level-access stattfindet.
125
- export const customFieldsFeature = defineFeature(CUSTOM_FIELDS_FEATURE_NAME, (r) => registerCustomFields(r, {
120
+ // Handlers and wire-for-entity read `.exports.<event>.name` lazily inside their runtime
121
+ // arrow functions, which resolves the module cycle (feature.ts -> handlers/*.write.ts -> feature.ts).
122
+ const defaultCustomFieldsFeature = defineFeature(CUSTOM_FIELDS_FEATURE_NAME, (r) => registerCustomFields(r, {
126
123
  defineTenantHandler: defineTenantFieldHandler,
127
124
  updateTenantHandler: updateTenantFieldHandler,
128
125
  deleteTenantHandler: deleteTenantFieldHandler,
@@ -146,18 +143,15 @@ export function resolveFieldDefinitionListRoles(opts) {
146
143
  ]),
147
144
  ];
148
145
  }
149
- // Backwards-compat-wrapper. Bestehende Caller (z.B. integration-tests,
150
- // host-apps) nutzen weiterhin `createCustomFieldsFeature()`. Returnt den
151
- // module-level-Singleton — kein neuer build pro Aufruf, was für consumer
152
- // nicht erkennbar ist (read-only inspection). Jede gesetzte Option baut
153
- // eine frische Feature-Definition mit den Varianten-Handlern.
146
+ // Without options this returns the module-level singleton (no rebuild per call); every
147
+ // option builds a fresh feature definition with the variant handlers.
154
148
  export function createCustomFieldsFeature(opts = {}) {
155
149
  const hasOptions = opts.fieldDefinitionLimitPerTenant !== undefined ||
156
150
  opts.valueWriteRoles !== undefined ||
157
151
  opts.fieldDefinitionListRoles !== undefined ||
158
152
  opts.fieldDefinitionWriteRoles !== undefined;
159
153
  if (!hasOptions) {
160
- return customFieldsFeature;
154
+ return defaultCustomFieldsFeature;
161
155
  }
162
156
  const limit = opts.fieldDefinitionLimitPerTenant;
163
157
  const definitionWriteRoles = opts.fieldDefinitionWriteRoles;
@@ -179,3 +173,5 @@ export function createCustomFieldsFeature(opts = {}) {
179
173
  fieldDefinitionListRoles: resolveFieldDefinitionListRoles(opts),
180
174
  }));
181
175
  }
176
+ /** @deprecated Use createCustomFieldsFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
177
+ export const customFieldsFeature = createCustomFieldsFeature();
@@ -1,7 +1,7 @@
1
1
  import { failNotFound, failUnprocessable } from "@cosmicdrift/kumiko-framework/errors";
2
2
  import * as z from "zod";
3
3
  import { DEFAULT_VALUE_WRITE_ROLES } from "../constants.js";
4
- import { customFieldsFeature } from "../feature.js";
4
+ import { createCustomFieldsFeature } from "../feature.js";
5
5
  import { checkFieldAccessForWrite } from "../lib/field-access.js";
6
6
  export const clearCustomFieldPayloadSchema = z.object({
7
7
  entityName: z.string().min(1).max(64),
@@ -47,7 +47,7 @@ export const clearCustomFieldHandler = {
47
47
  await ctx.unsafeAppendEvent({
48
48
  aggregateId: payload.entityId,
49
49
  aggregateType: payload.entityName,
50
- type: customFieldsFeature.exports.clearedEvent.name,
50
+ type: createCustomFieldsFeature().exports.clearedEvent.name,
51
51
  payload: { fieldKey: payload.fieldKey },
52
52
  });
53
53
  return {
@@ -3,7 +3,7 @@ import { requireForTenant } from "../../shared/index.js";
3
3
  import { fieldDefinitionAggregateId } from "../aggregate-id.js";
4
4
  import { FIELD_DEFINITION_AGGREGATE_TYPE } from "../constants.js";
5
5
  import { fieldDefinitionExecutor } from "../executor.js";
6
- import { customFieldsFeature } from "../feature.js";
6
+ import { createCustomFieldsFeature } from "../feature.js";
7
7
  import { deleteFieldPayloadSchema } from "../schemas.js";
8
8
  // delete-system-field — SystemAdmin entfernt eine system-weite Field-
9
9
  // Definition. Konsequenz: KEIN Tenant kann mehr neue Werte dafür setzen,
@@ -29,7 +29,7 @@ export const deleteSystemFieldHandler = {
29
29
  await ctx.unsafeAppendEvent({
30
30
  aggregateId,
31
31
  aggregateType: FIELD_DEFINITION_AGGREGATE_TYPE,
32
- type: customFieldsFeature.exports.fieldDefinitionDeletedEvent.name,
32
+ type: createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name,
33
33
  payload: {
34
34
  entityName: payload.entityName,
35
35
  fieldKey: payload.fieldKey,
@@ -2,7 +2,7 @@ import { isSystemTenant } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { fieldDefinitionAggregateId } from "../aggregate-id.js";
3
3
  import { DEFAULT_FIELD_DEFINITION_WRITE_ROLES, FIELD_DEFINITION_AGGREGATE_TYPE, } from "../constants.js";
4
4
  import { fieldDefinitionExecutor } from "../executor.js";
5
- import { customFieldsFeature } from "../feature.js";
5
+ import { createCustomFieldsFeature } from "../feature.js";
6
6
  import { deleteFieldPayloadSchema } from "../schemas.js";
7
7
  export function createDeleteTenantFieldHandler(opts = {}) {
8
8
  return {
@@ -26,7 +26,7 @@ export function createDeleteTenantFieldHandler(opts = {}) {
26
26
  await ctx.unsafeAppendEvent({
27
27
  aggregateId,
28
28
  aggregateType: FIELD_DEFINITION_AGGREGATE_TYPE,
29
- type: customFieldsFeature.exports.fieldDefinitionDeletedEvent.name,
29
+ type: createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name,
30
30
  payload: { entityName: payload.entityName, fieldKey: payload.fieldKey, tenantId },
31
31
  });
32
32
  }
@@ -1,7 +1,7 @@
1
1
  import { failNotFound, failUnprocessable } from "@cosmicdrift/kumiko-framework/errors";
2
2
  import * as z from "zod";
3
3
  import { DEFAULT_VALUE_WRITE_ROLES } from "../constants.js";
4
- import { customFieldsFeature } from "../feature.js";
4
+ import { createCustomFieldsFeature } from "../feature.js";
5
5
  import { fieldWriteAccessDeniedRoles, loadFieldDefinition } from "../lib/field-access.js";
6
6
  import { buildCustomFieldValueSchema } from "../lib/value-schema.js";
7
7
  export const setCustomFieldPayloadSchema = z.object({
@@ -87,7 +87,7 @@ export const setCustomFieldHandler = {
87
87
  await ctx.unsafeAppendEvent({
88
88
  aggregateId: payload.entityId,
89
89
  aggregateType: payload.entityName,
90
- type: customFieldsFeature.exports.setEvent.name,
90
+ type: createCustomFieldsFeature().exports.setEvent.name,
91
91
  payload: { fieldKey: payload.fieldKey, value: payload.value },
92
92
  });
93
93
  return {
@@ -2,7 +2,7 @@ import { extractTableName } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { createJsonbField, isSystemTenant, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { CUSTOM_FIELDS_EXTENSION, FIELD_DEFINITION_AGGREGATE_TYPE } from "./constants.js";
4
4
  import { clearCustomFieldKey, removeCustomFieldKeyForTenant, removeCustomFieldKeyFromAllTenants, setCustomFieldValue, } from "./db/queries/projection.js";
5
- import { customFieldsFeature } from "./feature.js";
5
+ import { createCustomFieldsFeature } from "./feature.js";
6
6
  // Helper für entity-definitions — fügt eine `customFields jsonb`-Spalte
7
7
  // hinzu. Consumer:
8
8
  //
@@ -69,9 +69,9 @@ export function wireCustomFieldsFor(r, entityName, entityTable) {
69
69
  // Qualified event-type-names — sourced from typed EventDef.name handles
70
70
  // (compile-time literal-typed, no Template-Literal-Drift à la toKebab-
71
71
  // collapse-bug die T1 aufgedeckt hat).
72
- const setEventType = customFieldsFeature.exports.setEvent.name;
73
- const clearedEventType = customFieldsFeature.exports.clearedEvent.name;
74
- const fieldDefDeletedType = customFieldsFeature.exports.fieldDefinitionDeletedEvent.name;
72
+ const setEventType = createCustomFieldsFeature().exports.setEvent.name;
73
+ const clearedEventType = createCustomFieldsFeature().exports.clearedEvent.name;
74
+ const fieldDefDeletedType = createCustomFieldsFeature().exports.fieldDefinitionDeletedEvent.name;
75
75
  // Geteilte apply-Bodies: die MSP liefert sie live (async cursor), die
76
76
  // entity-projection-extension replayt sie in rebuildProjection — gleiche
77
77
  // SQL-Helper, beide idempotent. 2-Param-Signatur ist die gemeinsame
@@ -1,7 +1,7 @@
1
1
  // Single implementation of the three-layer policy resolution: the cleanup cron,
2
2
  // the forget runner and the `policy-for` query all go through here, so a caller
3
3
  // cannot skip a layer (e.g. the tenant preset) by accident.
4
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
4
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
5
5
  import { isTenantDb } from "../shared/index.js";
6
6
  import { parseRetentionOverrideOrNull } from "./_internal/parse-override.js";
7
7
  import { resolveTenantRetentionPreset } from "./resolve-tenant-preset.js";
@@ -37,9 +37,8 @@
37
37
  // taegliche Re-Lauf appended also null Events. Der WHERE matcht anonymisierte
38
38
  // Rows weiter (reference bleibt alt), deshalb id-Cursor-Paging statt einer
39
39
  // einzelnen Page — sonst verstopfen erledigte Rows das batchLimit-Fenster.
40
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
41
- import { collectPiiSubjectFields, configuredPiiSubjectKms, isSelfPiiField, resolveSubjectForField, subjectIdToKey, } from "@cosmicdrift/kumiko-framework/crypto";
42
- import { createEventStoreExecutor, createTenantDb, nullBlindIndexesForSubject, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
40
+ import { collectPiiSubjectFields, configuredPiiSubjectKms, isRecordKeyedField, isSelfPiiField, resolveSubjectForField, subjectIdToKey, } from "@cosmicdrift/kumiko-framework/crypto";
41
+ import { createEventStoreExecutor, createTenantDb, nullBlindIndexesForSubject, selectMany, WritePurposes, } from "@cosmicdrift/kumiko-framework/db";
43
42
  import { deleteFileRefBytes } from "@cosmicdrift/kumiko-framework/derivatives";
44
43
  import { createSystemUser, entityHasAnonymizableSubjectField, } from "@cosmicdrift/kumiko-framework/engine";
45
44
  import { fileRefEntity, fileRefsTable, } from "@cosmicdrift/kumiko-framework/files";
@@ -81,24 +80,29 @@ async function purgeMatchingRows(db, table, where, batchLimit, op) {
81
80
  // (purgeMatchingRows's hardDelete select) is enough; the with-files path's
82
81
  // full row works the same way.
83
82
  //
84
- // userOwned/tenantOwned are explicitly excluded: hardDelete only destroys
83
+ // userOwned/tenantOwned are explicitly excluded (except a whenAbsent: "self" field
84
+ // of an ownerless row, which resolves to this row's own record key): hardDelete only destroys
85
85
  // THIS row's own data, but the owning user's/tenant's key may still protect
86
86
  // OTHER live rows that reference the same subject — erasing it here would
87
87
  // be a silent cross-row data-loss bug, not a retention fix.
88
+ function mayResolveToOwnRecordKey(field) {
89
+ if ("tenantOwned" in field && field.tenantOwned === true)
90
+ return false;
91
+ if ("userOwned" in field && field.userOwned !== undefined)
92
+ return isRecordKeyedField(field);
93
+ return ("recordOwned" in field && field.recordOwned === true) || isSelfPiiField(field);
94
+ }
88
95
  function collectHardDeleteEraseSubjects(entity, entityName, tenantId, row) {
89
96
  const subjectsByKey = new Map();
90
97
  for (const fieldName of collectPiiSubjectFields(entity)) {
91
98
  const field = entity.fields[fieldName];
92
- if (!field)
99
+ if (!field || !mayResolveToOwnRecordKey(field))
93
100
  continue;
94
- const isRecordOwned = "recordOwned" in field && field.recordOwned === true;
101
+ const subject = resolveSubjectForField(entity, fieldName, row, { tenantId, entityName });
102
+ // whenAbsent: "self" resolves to the owner's key while the row has an owner — never erased here
95
103
  const isUserOwned = "userOwned" in field && field.userOwned !== undefined;
96
- const isTenantOwned = "tenantOwned" in field && field.tenantOwned === true;
97
- if (isUserOwned || isTenantOwned)
98
- continue; // never erase — see header comment
99
- if (!isRecordOwned && !isSelfPiiField(field))
104
+ if (isUserOwned && subject?.kind !== "record")
100
105
  continue;
101
- const subject = resolveSubjectForField(entity, fieldName, row, { tenantId, entityName });
102
106
  if (subject)
103
107
  subjectsByKey.set(subjectIdToKey(subject), subject);
104
108
  }
@@ -132,7 +136,7 @@ async function eraseHardDeletedRowKeys(args) {
132
136
  // unconfined and leave the row gone with its key still live.
133
137
  async function forgetRowAndEraseKeys(args) {
134
138
  return runInSubTransaction(args.db, async (sp) => {
135
- const tdb = createTenantDb(sp, args.tenantId, "system");
139
+ const tdb = createTenantDb({ db: sp, tenantId: args.tenantId, mode: "system" });
136
140
  const result = await args.executor.forget({ id: args.row["id"] }, args.systemUser, tdb);
137
141
  if (!result.isSuccess)
138
142
  return { isSuccess: false };
@@ -445,7 +449,7 @@ export async function runRetentionCleanup(args) {
445
449
  // the daily cron converges (hardDelete removes rows, softDelete's isDeleted
446
450
  // filter shrinks the set). A single batched forget/delete event is a follow-up.
447
451
  const systemUser = createSystemUser(tenantId);
448
- const tdb = createTenantDb(db, tenantId, "system");
452
+ const tdb = createTenantDb({ db, tenantId, mode: "system" });
449
453
  const fileHolders = collectSingleFileHolders(registry);
450
454
  // Pre-load every override row for this tenant ONCE — N entities × M
451
455
  // tenants would otherwise mean one fetchOne per entity per tenant, even
@@ -1,6 +1,5 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import { computeBlindIndex, configuredBlindIndexKey } from "@cosmicdrift/kumiko-framework/crypto";
3
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
2
+ import { createEventStoreExecutor, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
4
3
  import { ConflictError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { generateDeterministicId } from "@cosmicdrift/kumiko-framework/utils";
6
5
  import { DeliveryErrors } from "./public-names.js";
@@ -1,4 +1,4 @@
1
- import { deleteManyBatched } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { deleteManyBatched } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { pruneEvents } from "@cosmicdrift/kumiko-framework/pipeline";
3
3
  import { deliveryAttemptsTable } from "./tables.js";
4
4
  export const DEFAULT_ATTEMPT_LOG_RETENTION_DAYS = 90;
@@ -87,7 +87,7 @@ export function createEmailAttachmentReader(db, registry, tenantId, config, file
87
87
  // and it never runs through a job).
88
88
  export function buildChannelContext(db, registry, sseBroker, tenantId, secrets, tenantConfig, filesForTenant) {
89
89
  return {
90
- db: createTenantDb(db, tenantId),
90
+ db: createTenantDb({ db, tenantId }),
91
91
  registry,
92
92
  sseBroker,
93
93
  tenantId,
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { notificationAddressOptOutsTable } from "../../tables.js";
3
3
  export function addressOptOutKey(addressHash, channel) {
4
4
  return `${addressHash}|${channel}`;
@@ -1,4 +1,4 @@
1
- import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
2
2
  // @wrapper-known semantic-alias
3
3
  export async function selectNotificationPreferences(db, tenantId, userId, notificationTypeNames, channelName) {
4
4
  return unsafeReadRetrying(db, `SELECT notification_type AS "notificationType", channel, enabled
@@ -1,8 +1,7 @@
1
1
  import { createSystemDbView, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
2
- import { assertNotificationVariables, createSystemUser, } from "@cosmicdrift/kumiko-framework/engine";
2
+ import { assertNotificationVariables, bridgeStub, createSystemUser, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
4
4
  import { assertNotifyTargetsOwnTenant, createEscapeHatchReporter, } from "@cosmicdrift/kumiko-framework/pipeline";
5
- import { bridgeStub } from "@cosmicdrift/kumiko-framework/testing/handler-context";
6
5
  import { generateId } from "@cosmicdrift/kumiko-framework/utils";
7
6
  import { fileContextFromResolver } from "../file-foundation/index.js";
8
7
  import { redactErrorText } from "../shared/index.js";
@@ -125,17 +124,27 @@ export function createDeliveryService(options) {
125
124
  // path a cross-tenant read the dispatcher never allows. Cross-tenant reach only
126
125
  // exists through the grant-carrying systemDb view below.
127
126
  const isSystem = registry.isHandlerSystemScoped(tenantUserIdsQuery);
128
- const tenantDb = createTenantDb(run.db, tenantId, "tenant", undefined, undefined, undefined, {
129
- report,
127
+ const tenantDb = createTenantDb({
128
+ db: run.db,
129
+ tenantId,
130
+ mode: "tenant",
131
+ grants: {
132
+ report,
133
+ },
130
134
  });
131
135
  // The dispatcher grants a systemScope handler's ctx.systemDb.unsafeRaw() ungated —
132
136
  // the grant comes from the handler's own r.systemScope() registration, not from this
133
137
  // caller. Only the systemDb view's own source TenantDb carries the grant, so it
134
138
  // can't leak onto ctx.db.
135
139
  const systemDbSourceTenantDb = isSystem
136
- ? createTenantDb(run.db, tenantId, "system", undefined, undefined, undefined, {
137
- report,
138
- unsafeRaw: { reason: `r.systemScope() handler "${tenantUserIdsQuery}"` },
140
+ ? createTenantDb({
141
+ db: run.db,
142
+ tenantId,
143
+ mode: "system",
144
+ grants: {
145
+ report,
146
+ unsafeRaw: { reason: `r.systemScope() handler "${tenantUserIdsQuery}"` },
147
+ },
139
148
  })
140
149
  : undefined;
141
150
  // Hand-built context, not routed through the dispatcher — this needs both