@cosmicdrift/kumiko-bundled-features 0.367.0 → 0.368.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 (330) 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-in-app/handlers/inbox.query.js +1 -1
  44. package/dist/channel-in-app/handlers/mark-all-read.write.js +1 -1
  45. package/dist/channel-in-app/handlers/mark-read.write.js +1 -1
  46. package/dist/channel-in-app/handlers/unread-count.query.js +1 -1
  47. package/dist/channel-in-app/tables.js +1 -2
  48. package/dist/compliance-profiles/handlers/for-tenant.query.js +1 -1
  49. package/dist/compliance-profiles/handlers/needs-profile.query.js +1 -1
  50. package/dist/compliance-profiles/handlers/set-profile.write.js +1 -2
  51. package/dist/compliance-profiles/resolve-for-tenant.js +1 -1
  52. package/dist/compliance-profiles/seeding.js +3 -5
  53. package/dist/compliance-profiles-ops/index.d.ts +8 -0
  54. package/dist/compliance-profiles-ops/index.js +19 -15
  55. package/dist/config/db/queries/resolver.js +1 -1
  56. package/dist/config/handlers/reencrypt.job.js +2 -2
  57. package/dist/config/resolver.js +1 -1
  58. package/dist/config/write-helpers.js +1 -1
  59. package/dist/crypto-shredding/handlers/forget-subject.write.js +6 -3
  60. package/dist/custom-fields/db/queries/field-access.js +1 -1
  61. package/dist/custom-fields/db/queries/projection.js +1 -1
  62. package/dist/custom-fields/db/queries/quota.js +1 -1
  63. package/dist/custom-fields/db/queries/retention.js +1 -2
  64. package/dist/custom-fields/db/queries/user-data-rights.js +1 -1
  65. package/dist/custom-fields/feature.d.ts +20 -2
  66. package/dist/custom-fields/feature.js +9 -13
  67. package/dist/custom-fields/handlers/clear-custom-field.write.js +2 -2
  68. package/dist/custom-fields/handlers/delete-system-field.write.js +2 -2
  69. package/dist/custom-fields/handlers/delete-tenant-field.write.js +2 -2
  70. package/dist/custom-fields/handlers/set-custom-field.write.js +2 -2
  71. package/dist/custom-fields/wire-for-entity.js +4 -4
  72. package/dist/data-retention/resolve-for-tenant.js +1 -1
  73. package/dist/data-retention/run-retention-cleanup.js +17 -13
  74. package/dist/delivery/address-opt-out.js +1 -2
  75. package/dist/delivery/attempt-log-retention.js +1 -1
  76. package/dist/delivery/channel-context.js +1 -1
  77. package/dist/delivery/db/queries/address-opt-outs.js +1 -1
  78. package/dist/delivery/db/queries/preferences.js +1 -1
  79. package/dist/delivery/delivery-service.js +16 -7
  80. package/dist/delivery/feature.js +1 -1
  81. package/dist/delivery/handlers/log.query.js +2 -3
  82. package/dist/delivery/handlers/preferences.query.js +1 -1
  83. package/dist/delivery/upsert-preference.js +1 -2
  84. package/dist/derivatives-sharp/feature.d.ts +4 -0
  85. package/dist/derivatives-sharp/feature.js +15 -11
  86. package/dist/derivatives-sharp/index.d.ts +1 -1
  87. package/dist/derivatives-sharp/index.js +1 -1
  88. package/dist/document-ingest-foundation/feature.d.ts +7 -0
  89. package/dist/document-ingest-foundation/feature.js +94 -90
  90. package/dist/document-ingest-foundation/forget-extract-with-file-ref.js +3 -3
  91. package/dist/document-ingest-foundation/index.d.ts +1 -1
  92. package/dist/document-ingest-foundation/index.js +1 -1
  93. package/dist/feature-toggles/global-feature-state-table.js +1 -2
  94. package/dist/feature-toggles/handlers/set.write.js +3 -5
  95. package/dist/feature-toggles/toggle-runtime.js +1 -1
  96. package/dist/file-derivatives/feature.d.ts +1 -0
  97. package/dist/file-derivatives/feature.js +2 -1
  98. package/dist/file-derivatives/handlers/public-variant-by-file-ref.query.js +1 -1
  99. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  100. package/dist/file-foundation/feature.d.ts +6 -0
  101. package/dist/file-foundation/feature.js +29 -25
  102. package/dist/file-foundation/index.d.ts +1 -1
  103. package/dist/file-foundation/index.js +1 -1
  104. package/dist/file-foundation/read-file-ref-content.js +1 -1
  105. package/dist/file-provider-inmemory/feature.d.ts +4 -0
  106. package/dist/file-provider-inmemory/feature.js +24 -20
  107. package/dist/file-provider-inmemory/index.d.ts +1 -1
  108. package/dist/file-provider-inmemory/index.js +1 -1
  109. package/dist/file-provider-s3/env-feature.d.ts +3 -0
  110. package/dist/file-provider-s3/env-feature.js +46 -0
  111. package/dist/file-provider-s3/feature.d.ts +26 -0
  112. package/dist/file-provider-s3/feature.js +84 -72
  113. package/dist/file-provider-s3/index.d.ts +1 -1
  114. package/dist/file-provider-s3/index.js +1 -1
  115. package/dist/file-provider-s3/lib/index.d.ts +3 -0
  116. package/dist/file-provider-s3/lib/index.js +2 -0
  117. package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.js +19 -19
  118. package/dist/file-provider-s3-env/index.d.ts +8 -1
  119. package/dist/file-provider-s3-env/index.js +7 -2
  120. package/dist/files-provider-s3/index.d.ts +5 -3
  121. package/dist/files-provider-s3/index.js +5 -2
  122. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +1 -1
  123. package/dist/files-tenant-data/hooks.js +1 -2
  124. package/dist/folders/feature.d.ts +6 -2
  125. package/dist/folders/feature.js +4 -2
  126. package/dist/folders-user-data/index.d.ts +4 -0
  127. package/dist/folders-user-data/index.js +21 -17
  128. package/dist/form-draft/db/queries/cleanup.js +1 -1
  129. package/dist/form-draft/db/queries/draft-count.js +1 -1
  130. package/dist/form-draft/db/queries/owned-file-refs.js +1 -2
  131. package/dist/form-draft/feature.d.ts +4 -0
  132. package/dist/form-draft/feature.js +5 -1
  133. package/dist/form-draft/handlers/cleanup.job.js +2 -2
  134. package/dist/form-draft/index.d.ts +1 -1
  135. package/dist/form-draft/index.js +1 -1
  136. package/dist/form-draft/lookup.js +1 -1
  137. package/dist/form-draft-user-data/index.d.ts +4 -0
  138. package/dist/form-draft-user-data/index.js +13 -9
  139. package/dist/inbound-mail-foundation/feature.d.ts +4 -0
  140. package/dist/inbound-mail-foundation/feature.js +151 -147
  141. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +1 -2
  142. package/dist/inbound-mail-foundation/index.d.ts +1 -1
  143. package/dist/inbound-mail-foundation/index.js +1 -1
  144. package/dist/inbound-mail-foundation/oauth-access-token.js +1 -2
  145. package/dist/inbound-mail-foundation/projection.js +1 -2
  146. package/dist/inbound-mail-foundation/watch-supervisor.js +1 -1
  147. package/dist/inbound-provider-imap/feature.d.ts +4 -0
  148. package/dist/inbound-provider-imap/feature.js +16 -12
  149. package/dist/inbound-provider-imap/index.d.ts +1 -1
  150. package/dist/inbound-provider-imap/index.js +1 -1
  151. package/dist/inbound-provider-inmemory/feature.d.ts +4 -0
  152. package/dist/inbound-provider-inmemory/feature.js +14 -10
  153. package/dist/inbound-provider-inmemory/index.d.ts +1 -1
  154. package/dist/inbound-provider-inmemory/index.js +1 -1
  155. package/dist/jobs/db/queries/retention.js +1 -1
  156. package/dist/jobs/db/queries/stale-run-sweep.js +1 -1
  157. package/dist/jobs/handlers/detail.query.js +1 -1
  158. package/dist/jobs/handlers/list.query.js +1 -2
  159. package/dist/jobs/handlers/retry.write.js +1 -1
  160. package/dist/jobs/handlers/tenant-failures.query.js +1 -1
  161. package/dist/jobs/handlers/tenant-runs.query.js +1 -1
  162. package/dist/jobs/job-run-logger.js +1 -2
  163. package/dist/jobs/tenant-job-failure-table.js +1 -2
  164. package/dist/jobs/tenant-job-run-table.js +1 -2
  165. package/dist/ledger/feature.d.ts +6 -2
  166. package/dist/ledger/feature.js +4 -2
  167. package/dist/mail-foundation/feature.d.ts +7 -0
  168. package/dist/mail-foundation/feature.js +48 -42
  169. package/dist/mail-foundation/index.d.ts +1 -1
  170. package/dist/mail-foundation/index.js +1 -1
  171. package/dist/mail-transport-inmemory/feature.d.ts +4 -0
  172. package/dist/mail-transport-inmemory/feature.js +20 -16
  173. package/dist/mail-transport-inmemory/index.d.ts +1 -1
  174. package/dist/mail-transport-inmemory/index.js +1 -1
  175. package/dist/mail-transport-smtp/feature.d.ts +16 -0
  176. package/dist/mail-transport-smtp/feature.js +85 -79
  177. package/dist/mail-transport-smtp/index.d.ts +1 -1
  178. package/dist/mail-transport-smtp/index.js +1 -1
  179. package/dist/managed-pages/handlers/by-slug.query.js +1 -1
  180. package/dist/managed-pages/handlers/by-tenant-published.query.js +1 -2
  181. package/dist/managed-pages/handlers/set.write.js +1 -2
  182. package/dist/managed-pages/seeding.js +3 -5
  183. package/dist/metrics/compute.d.ts +1 -1
  184. package/dist/metrics/filters.d.ts +1 -1
  185. package/dist/metrics/filters.js +1 -1
  186. package/dist/metrics/validate.js +1 -1
  187. package/dist/notes-history/feature.d.ts +7 -2
  188. package/dist/notes-history/feature.js +4 -2
  189. package/dist/notes-history/handlers/add-note.write.js +1 -1
  190. package/dist/notes-history-user-data/hooks.js +1 -1
  191. package/dist/notes-history-user-data/index.d.ts +4 -0
  192. package/dist/notes-history-user-data/index.js +21 -17
  193. package/dist/personal-access-tokens/feature.d.ts +4 -1
  194. package/dist/personal-access-tokens/feature.js +10 -2
  195. package/dist/personal-access-tokens/handlers/create.write.js +1 -1
  196. package/dist/personal-access-tokens/handlers/list.query.js +2 -2
  197. package/dist/personal-access-tokens/handlers/revoke.write.js +1 -1
  198. package/dist/personal-access-tokens/resolver.js +1 -1
  199. package/dist/personal-access-tokens/revoke-for-user.js +1 -1
  200. package/dist/personal-access-tokens/roles.js +3 -5
  201. package/dist/personal-access-tokens/screens.js +2 -0
  202. package/dist/readiness/feature.d.ts +8 -0
  203. package/dist/readiness/feature.js +18 -14
  204. package/dist/readiness/index.d.ts +1 -1
  205. package/dist/readiness/index.js +1 -1
  206. package/dist/secrets/db/queries/read.js +1 -1
  207. package/dist/secrets/feature.d.ts +3 -0
  208. package/dist/secrets/feature.js +3 -2
  209. package/dist/secrets/handlers/rotate.job.js +2 -3
  210. package/dist/secrets/secrets-context.js +3 -4
  211. package/dist/sessions/db/queries/cleanup.js +1 -1
  212. package/dist/sessions/handlers/detail.query.js +1 -1
  213. package/dist/sessions/handlers/list.query.js +2 -2
  214. package/dist/sessions/handlers/mine.query.js +1 -1
  215. package/dist/sessions/handlers/revoke-all-for-user.write.js +1 -1
  216. package/dist/sessions/handlers/revoke-all-others.write.js +1 -1
  217. package/dist/sessions/handlers/revoke.write.js +1 -1
  218. package/dist/sessions/session-callbacks.js +4 -6
  219. package/dist/sessions/testing.d.ts +1 -1
  220. package/dist/tags/feature.d.ts +6 -2
  221. package/dist/tags/feature.js +4 -2
  222. package/dist/template-resolver/api.js +1 -1
  223. package/dist/template-resolver/handlers/bundle-import.js +1 -1
  224. package/dist/template-resolver/handlers/by-slug.query.js +1 -1
  225. package/dist/template-resolver/handlers/by-tenant.query.js +1 -2
  226. package/dist/template-resolver/handlers/collection-item.query.js +1 -1
  227. package/dist/template-resolver/handlers/collection-list.query.js +1 -2
  228. package/dist/template-resolver/handlers/collection-set.write.js +1 -1
  229. package/dist/template-resolver/handlers/copy-locale.write.js +1 -1
  230. package/dist/template-resolver/handlers/diff-to-system.query.js +1 -1
  231. package/dist/template-resolver/handlers/export-bundle.query.js +1 -1
  232. package/dist/template-resolver/handlers/find-by-id.query.js +1 -1
  233. package/dist/template-resolver/handlers/layout-source.query.js +1 -1
  234. package/dist/template-resolver/handlers/list.query.js +1 -1
  235. package/dist/template-resolver/handlers/overview.query.js +1 -1
  236. package/dist/template-resolver/handlers/reset-to-system.write.js +1 -1
  237. package/dist/template-resolver/handlers/resource-remove.write.js +1 -1
  238. package/dist/template-resolver/handlers/set.write.js +1 -1
  239. package/dist/template-resolver/handlers/template-write.js +1 -1
  240. package/dist/template-resolver/handlers/tenant-overrides.query.js +1 -1
  241. package/dist/template-resolver/handlers/toggle-status.write.js +1 -1
  242. package/dist/template-resolver/handlers/usage.query.js +1 -1
  243. package/dist/template-resolver/handlers/validate.query.js +1 -1
  244. package/dist/template-resolver/seeding.js +3 -4
  245. package/dist/template-resolver/store-template-resource.js +1 -1
  246. package/dist/template-resolver/template-preview.js +1 -1
  247. package/dist/template-resolver/template-resources.js +1 -1
  248. package/dist/template-resolver/testing.js +1 -1
  249. package/dist/template-resolver-user-data/index.d.ts +4 -0
  250. package/dist/template-resolver-user-data/index.js +17 -13
  251. package/dist/tenant/handlers/active-tenant-ids.query.js +1 -1
  252. package/dist/tenant/handlers/add-member.write.js +1 -2
  253. package/dist/tenant/handlers/cancel-invitation.write.js +1 -1
  254. package/dist/tenant/handlers/invitations.query.js +1 -1
  255. package/dist/tenant/handlers/me.query.js +1 -1
  256. package/dist/tenant/handlers/member-directory.query.js +1 -1
  257. package/dist/tenant/handlers/members.query.js +1 -1
  258. package/dist/tenant/handlers/memberships.query.js +1 -1
  259. package/dist/tenant/handlers/remove-member.write.js +1 -2
  260. package/dist/tenant/handlers/resolve-user-ids.query.js +1 -1
  261. package/dist/tenant/handlers/team-list.query.js +1 -1
  262. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  263. package/dist/tenant/handlers/update-member-roles.write.js +1 -2
  264. package/dist/tenant/invited-membership.js +2 -3
  265. package/dist/tenant/last-tenant-admin.js +1 -2
  266. package/dist/tenant/seeding.js +12 -6
  267. package/dist/tenant-lifecycle/handlers/cancel-destruction.write.js +1 -2
  268. package/dist/tenant-lifecycle/handlers/request-destruction.write.js +1 -2
  269. package/dist/tenant-lifecycle/lib/revoke-tenant-sessions.js +1 -1
  270. package/dist/tenant-lifecycle/lifecycle-gate.js +1 -1
  271. package/dist/tenant-lifecycle/run-tenant-destroy.js +3 -5
  272. package/dist/tenant-lifecycle/stages.js +10 -6
  273. package/dist/tenant-lifecycle/testing.d.ts +1 -1
  274. package/dist/tenant-lifecycle/testing.js +2 -2
  275. package/dist/tenant-settings/feature.d.ts +1 -0
  276. package/dist/tenant-settings/feature.js +2 -1
  277. package/dist/tier-engine/feature.d.ts +1 -8
  278. package/dist/tier-engine/feature.js +71 -78
  279. package/dist/tier-engine/handlers/get-tenant-tier.query.js +2 -3
  280. package/dist/tier-engine/handlers/set-tenant-tier.write.js +1 -2
  281. package/dist/user/db/queries/stream-tenant-backfill.js +1 -1
  282. package/dist/user/handlers/create.write.js +1 -2
  283. package/dist/user/handlers/find-for-auth.query.js +1 -1
  284. package/dist/user/handlers/list.query.js +1 -1
  285. package/dist/user/handlers/update-roles.js +1 -2
  286. package/dist/user/index.d.ts +1 -1
  287. package/dist/user/index.js +1 -1
  288. package/dist/user/invited-global-roles.js +2 -3
  289. package/dist/user/principal-status.d.ts +4 -0
  290. package/dist/user/principal-status.js +9 -3
  291. package/dist/user/resolve-display-names.js +1 -1
  292. package/dist/user/seeding.js +5 -6
  293. package/dist/user-data-rights/audit-download.js +2 -2
  294. package/dist/user-data-rights/db/queries/export-jobs.js +1 -1
  295. package/dist/user-data-rights/db/queries/forget-cleanup.js +1 -1
  296. package/dist/user-data-rights/handlers/download-by-job.query.js +1 -1
  297. package/dist/user-data-rights/handlers/download-by-token.query.js +1 -1
  298. package/dist/user-data-rights/handlers/export-status.query.js +1 -1
  299. package/dist/user-data-rights/handlers/list-download-attempts.query.js +1 -1
  300. package/dist/user-data-rights/handlers/my-audit-log.query.js +1 -1
  301. package/dist/user-data-rights/handlers/request-export.write.js +1 -2
  302. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +3 -3
  303. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.d.ts +1 -1
  304. package/dist/user-data-rights/lib/deny-if-target-outside-admin-tenant.js +1 -1
  305. package/dist/user-data-rights/lib/update-user-lifecycle.d.ts +1 -0
  306. package/dist/user-data-rights/lib/update-user-lifecycle.js +3 -3
  307. package/dist/user-data-rights/run-export-jobs.js +2 -3
  308. package/dist/user-data-rights/run-forget-cleanup.js +9 -5
  309. package/dist/user-data-rights/run-user-export.js +9 -5
  310. package/dist/waitlist/handlers/invite.write.js +1 -2
  311. package/dist/waitlist/handlers/reject.write.js +1 -1
  312. package/dist/waitlist/lib.js +1 -2
  313. package/dist/workflow-runner/event-subscriber.js +1 -1
  314. package/dist/workflow-runner/feature.d.ts +4 -0
  315. package/dist/workflow-runner/feature.js +44 -40
  316. package/dist/workflow-runner/handlers/resume-run.write.js +1 -1
  317. package/dist/workflow-runner/index.d.ts +1 -1
  318. package/dist/workflow-runner/index.js +1 -1
  319. package/dist/workflow-runner/pending-projection.js +1 -1
  320. package/package.json +28 -11
  321. package/src/cap-counter/changes.json +13 -0
  322. package/src/crypto-shredding/changes.json +6 -0
  323. package/src/file-provider-s3/changes.json +10 -1
  324. package/src/personal-access-tokens/changes.json +6 -0
  325. package/src/user/changes.json +6 -0
  326. package/dist/file-provider-s3-env/feature.d.ts +0 -3
  327. package/dist/file-provider-s3-env/feature.js +0 -46
  328. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.d.ts +0 -0
  329. /package/dist/{files-provider-s3 → file-provider-s3/lib}/env-helper.js +0 -0
  330. /package/dist/{files-provider-s3 → file-provider-s3/lib}/s3-provider.d.ts +0 -0
@@ -40,8 +40,7 @@
40
40
  //
41
41
  // **Boot-Dependencies:** config + tenant.
42
42
  // kumiko-lint-ignore app-feature-structure Phase-3 conversion tracked in #2312 (feature.ts > 300 lines)
43
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
44
- import { buildEntityTable, createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
43
+ import { buildEntityTable, createEventStoreExecutor, createTenantDb, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
45
44
  import { defineEntityCreateHandler, defineEntityListHandler, defineEntityUpdateHandler, defineFeature, defineQueryHandler, HookPhases, SYSTEM_TENANT_ID, TENANT_TIER_RESOLVER_EXT, } from "@cosmicdrift/kumiko-framework/engine";
46
45
  import { getUnscopedAggregateStreamMaxVersion } from "@cosmicdrift/kumiko-framework/event-store";
47
46
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
@@ -217,14 +216,14 @@ export function createTierEngineFeature(opts = {}) {
217
216
  if (!opts.tierMap)
218
217
  return;
219
218
  const tierMap = opts.tierMap;
220
- // Closure-state: cache per-tenant effective Sets. Hooks halten den
221
- // cache aktuell during process-lifetime; build() im extension-pickup
222
- // pre-loaded existing assignments at boot.
219
+ // Closure state: per-tenant cache of effective sets. Hooks keep the
220
+ // cache current during the process lifetime; build() in the extension
221
+ // pickup pre-loads existing assignments at boot.
223
222
  const cache = new Map();
224
- // alwaysOn-Set wird in build(deps) aus registry.features berechnet (alle
225
- // non-toggleable features). Hooks brauchen Zugriff darauf für
226
- // mergeAlwaysOn-calls — Late-bind via mutable holder, gefüllt vor allen
227
- // Requests (build läuft pre-listen via runDevApp/runProdApp-pickup).
223
+ // The alwaysOn set is computed in build(deps) from registry.features (all
224
+ // non-toggleable features). Hooks need it for mergeAlwaysOn calls — late
225
+ // bound via a mutable holder, filled before any request (build runs
226
+ // pre-listen via the runDevApp/runProdApp pickup).
228
227
  const alwaysOnHolder = { set: new Set() };
229
228
  // Bus handed to build(); hooks fire outside build and publish through it.
230
229
  const busHolder = { bus: undefined };
@@ -242,13 +241,14 @@ export function createTierEngineFeature(opts = {}) {
242
241
  // The writer already updated its own cache; only other pods need to re-read.
243
242
  busHolder.bus?.publish(CACHE_SYNC_TOPICS.tierAssignment, message, { remoteOnly: true });
244
243
  };
245
- // Trial: zeit-abgeleitet aus tenant.inserted_at (≈ Signup), live am
246
- // Feature-Gate geprüft — NICHT im Resolver-Cache. Der Resolver ist
247
- // boot-cached + synchron und sieht weder frische Signups noch den
248
- // Zeitablauf; der Trial-Status ändert sich aber mit der Zeit und gilt ab
249
- // Sekunde 1 nach Signup. Darum lebt er als async trialGate (unten, am
250
- // build-Ende angehängt), den der dispatcher nur auf dem disabled-Pfad
251
- // konsultiert. trialFeatures = fixe Feature-Menge des Trial-Tiers.
244
+ // Trial: derived from time (tenant.inserted_at ≈ signup) and checked live
245
+ // at the feature gate — NOT in the resolver cache. The resolver is
246
+ // boot-cached and synchronous, so it sees neither fresh signups nor the
247
+ // passage of time; the trial status changes over time and applies from
248
+ // second 1 after signup. That is why it lives as an async trialGate
249
+ // (below, attached at the end of build) which the dispatcher consults
250
+ // only on the disabled path. trialFeatures = fixed feature set of the
251
+ // trial tier.
252
252
  if (opts.trial && !tierMap[opts.trial.tier]) {
253
253
  throw new Error(`tier-engine: trial.tier "${opts.trial.tier}" is not a key in tierMap — trial would unlock no features`);
254
254
  }
@@ -286,7 +286,7 @@ export function createTierEngineFeature(opts = {}) {
286
286
  target: { allOf: "tier-assignment" },
287
287
  handler: async (payload) => {
288
288
  const data = payload.data; // @cast-boundary engine-payload
289
- // skip: gleiche type-guard semantik wie postSave-hook oben.
289
+ // skip: same type-guard semantics as the postSave hook above.
290
290
  if (typeof data.tenantId !== "string")
291
291
  return;
292
292
  const tenantId = data.tenantId;
@@ -295,18 +295,19 @@ export function createTierEngineFeature(opts = {}) {
295
295
  publishAssignmentChange(tenantId);
296
296
  },
297
297
  });
298
- // Auto-default-tier-on-tenant-signup: hook fires inTransaction (atomic
299
- // mit tenant-create rollback), schreibt tier-assignment via Direct-
300
- // Executor (nicht ctx.write — hook hat AppContext). Pattern analog
301
- // tenant/seeding.ts seedTenant.
298
+ // Auto-default-tier-on-tenant-signup: the hook fires inTransaction (atomic
299
+ // with the tenant-create rollback) and writes the tier-assignment via the
300
+ // direct executor (not ctx.write — the hook has an AppContext). Same
301
+ // pattern as seedTenant in tenant/seeding.ts.
302
302
  //
303
- // **Idempotency:** deterministic aggregate-id aus tenantId. Re-replay
304
- // (nach projection-rebuild oder hook-retry) findet stream-version > 0
305
- // und skipt, statt version_conflict zu werfen. Caller sieht erfolgreichen
306
- // tenant-create + bestehende tier-assignment.
303
+ // **Idempotency:** deterministic aggregate id derived from tenantId. A
304
+ // re-replay (after a projection rebuild or hook retry) finds
305
+ // stream-version > 0 and skips instead of throwing version_conflict. The
306
+ // caller sees a successful tenant-create plus the existing
307
+ // tier-assignment.
307
308
  //
308
- // **Cross-tenant write:** executor braucht systemUser MIT tenantId =
309
- // neuer Tenant (Memory `feedback_event_store_tenant_consistency`).
309
+ // **Cross-tenant write:** the executor needs a systemUser WITH tenantId =
310
+ // the new tenant (memory `feedback_event_store_tenant_consistency`).
310
311
  if (opts.defaultTier !== undefined) {
311
312
  const defaultTier = opts.defaultTier;
312
313
  const autoDefaultTierHookReason = "seeds the default tier-assignment stream of the tenant just created";
@@ -314,16 +315,16 @@ export function createTierEngineFeature(opts = {}) {
314
315
  type: "postSave",
315
316
  target: { allOf: "tenant" },
316
317
  handler: async (result, ctx) => {
317
- // result-shape: kumiko-framework's SaveContext mit isNew + data
318
+ // result shape: kumiko-framework's SaveContext with isNew + data
318
319
  const saveResult = result; // @cast-boundary engine-payload
319
- // skip: nur bei tenant-create (initial) — tenant-updates feuern
320
- // auch postSave aber wir wollen kein neues tier-assignment bei
321
- // re-keying oder name-update.
320
+ // skip: only on tenant-create (initial) — tenant updates fire
321
+ // postSave too, but a re-keying or name update must not create a
322
+ // new tier-assignment.
322
323
  if (saveResult.isNew !== true)
323
324
  return;
324
325
  const data = saveResult.data; // @cast-boundary engine-payload
325
- // skip: defensive type-guard. Tenant-entity hat id zwingend, aber
326
- // CrudExecutor's payload-shape ist runtime-unknown.
326
+ // skip: defensive type guard. The tenant entity always has an id, but
327
+ // CrudExecutor's payload shape is unknown at runtime.
327
328
  if (typeof data.id !== "string")
328
329
  return;
329
330
  const newTenantId = data.id; // @cast-boundary engine-payload
@@ -342,48 +343,47 @@ export function createTierEngineFeature(opts = {}) {
342
343
  // blocking), silent-skip is defensive-soft.
343
344
  if (!rawDb)
344
345
  return;
345
- // Idempotency: stream-existence-check vor create. Pattern aus
346
- // seedTenant.ts. Bei re-replay (rebuild) nicht versionsbumpen.
346
+ // Idempotency: stream-existence check before create. Same pattern as
347
+ // seedTenant.ts. On a re-replay (rebuild) do not bump the version.
347
348
  const streamVersion = await getUnscopedAggregateStreamMaxVersion(rawDb, aggregateId);
348
349
  // skip: idempotent — tier-assignment stream already seeded (rebuild/replay).
349
350
  if (streamVersion > 0)
350
351
  return;
351
- // SystemUser für den NEUEN tenant — der Hook wird vom signup-
352
- // user (anderer tenant, oder SystemAdmin) ausgelöst, aber das
353
- // tier-assignment muss im stream des neu-erzeugten tenants
354
- // landen (= aggregate-id deterministic auf newTenantId). Memory
355
- // `feedback_event_store_tenant_consistency`: by.tenantId muss =
356
- // ziel-tenant.
352
+ // SystemUser for the NEW tenant — the hook is triggered by the signup
353
+ // user (another tenant, or SystemAdmin), but the tier-assignment has
354
+ // to land in the stream of the newly created tenant (= aggregate id
355
+ // deterministic on newTenantId). Memory
356
+ // `feedback_event_store_tenant_consistency`: by.tenantId must equal
357
+ // the target tenant.
357
358
  const systemUser = {
358
359
  id: "00000000-0000-4000-8000-000000000001",
359
360
  tenantId: newTenantId,
360
361
  roles: ["SystemAdmin"],
361
362
  };
362
- const tdb = createTenantDb(rawDb, newTenantId, "system");
363
+ const tdb = createTenantDb({ db: rawDb, tenantId: newTenantId, mode: "system" });
363
364
  await tierAssignmentExecutor.create({ id: aggregateId, tier: defaultTier, source: TierAssignmentSources.default }, systemUser, tdb);
364
365
  },
365
366
  phase: HookPhases.inTransaction,
366
367
  escapeHatch: { reason: autoDefaultTierHookReason },
367
368
  });
368
369
  }
369
- // Extension-point declaration + self-registration. Pattern analog
370
- // mail-foundation/file-foundation: das feature deklariert den
371
- // extension-point UND registriert sich als default-plugin. Andere
372
- // features könnten später auch dort registrieren (z.B. ein future
373
- // toggle-only-resolver), aber nur ein plugin gewinnt — siehe
374
- // findTierResolverUsage's "single-plugin"-comment.
370
+ // Extension-point declaration + self-registration. Same pattern as
371
+ // mail-foundation/file-foundation: the feature declares the extension
372
+ // point AND registers itself as the default plugin. Other features could
373
+ // register there later (e.g. a future toggle-only resolver), but only one
374
+ // plugin wins — see the "single-plugin" comment on findTierResolverUsage.
375
375
  r.extendsRegistrar(TENANT_TIER_RESOLVER_EXT, { onRegister: () => { } });
376
376
  // Plugin-registration: framework's runDevApp/runProdApp picks this up
377
377
  // post-stack-setup, calls build(deps), wires effectiveFeatures.
378
378
  const plugin = {
379
379
  build: async (deps) => {
380
- // Always-on-Set: alle non-toggleable features im registry. Canonical
381
- // Kumiko-pattern (matches feature-toggles' resolver): nur features
382
- // die explizit `r.toggleable()` registrieren sind tier-cuttable.
383
- // Framework-base-features (auth-email-password, config, user, tenant,
384
- // sessions, etc.) sind non-toggleable → IMMER aktiv für jeden Tenant
385
- // unabhängig vom tier. Sonst würde dispatcher 403 auf login-handler
386
- // werfen weil "feature auth-email-password disabled".
380
+ // Always-on set: all non-toggleable features in the registry. Canonical
381
+ // Kumiko pattern (matches the feature-toggles resolver): only features
382
+ // that explicitly register `r.toggleable()` are tier-cuttable.
383
+ // Framework base features (auth-email-password, config, user, tenant,
384
+ // sessions, etc.) are non-toggleable → ALWAYS active for every tenant
385
+ // regardless of tier. Otherwise the dispatcher would answer 403 on the
386
+ // login handler because "feature auth-email-password disabled".
387
387
  const computedAlwaysOn = new Set();
388
388
  for (const feature of deps.registry.features.values()) {
389
389
  if (feature.toggleableDefault === undefined)
@@ -452,16 +452,16 @@ export function createTierEngineFeature(opts = {}) {
452
452
  // Synchronous resolver-callback for dispatcher hot-path.
453
453
  const resolver = (tenantId) => {
454
454
  // Operator-tooling + async-event-dispatch convention: SYSTEM_TENANT_ID
455
- // gets the union of all tier-features (siehe DispatcherOptions doc).
455
+ // gets the union of all tier features (see DispatcherOptions doc).
456
456
  if (tenantId === SYSTEM_TENANT_ID) {
457
457
  return mergeAlwaysOn(computedAlwaysOn, unionAllTierFeatures(tierMap));
458
458
  }
459
- // Cache-miss: tenant ist noch nicht im cache (z.B. brandneu nach
460
- // boot, oder defaultTier-hook hat noch nicht gefired). Default-Set
461
- // ist least-privileged — typisch Free-Tier-features. Memory
462
- // `feedback_security_default_on`: secure-by-default. Der Trial wird
463
- // hier NICHT addiert (sync/boot-cached sieht den Zeitablauf nicht) —
464
- // das macht der trialGate unten am disabled-Gate-Pfad.
459
+ // Cache miss: the tenant is not in the cache yet (e.g. brand new after
460
+ // boot, or the defaultTier hook has not fired yet). The default set
461
+ // is least-privileged — typically free-tier features. Memory
462
+ // `feedback_security_default_on`: secure by default. The trial is NOT
463
+ // added here (sync/boot-cached, cannot see the passage of time) — the
464
+ // trialGate below does that on the disabled-gate path.
465
465
  const fallbackTier = opts.defaultTier;
466
466
  return (cache.get(tenantId) ??
467
467
  (fallbackTier === undefined
@@ -471,11 +471,11 @@ export function createTierEngineFeature(opts = {}) {
471
471
  const trial = opts.trial;
472
472
  if (trial === undefined)
473
473
  return resolver;
474
- // Live-Trial-Gate: liest tenant.inserted_at (≈ Signup, existiert für
475
- // JEDEN Tenant inkl. auth-signup via seedTenant — anders als die
476
- // tier-assignment-Row, die der seed-Pfad nicht anlegt) und prüft das
477
- // Fenster gegen die aktuelle Zeit. Nur auf dem disabled-Gate-Pfad
478
- // konsultiert. inserted_at ist immutable → pro Tenant einmal lesen.
474
+ // Live trial gate: reads tenant.inserted_at (≈ signup; exists for EVERY
475
+ // tenant incl. auth-signup via seedTenant — unlike the tier-assignment
476
+ // row, which the seed path does not create) and checks the window
477
+ // against the current time. Consulted only on the disabled-gate path.
478
+ // inserted_at is immutable → read once per tenant.
479
479
  // Promise-memo (not a plain value cache): N concurrent requests for the
480
480
  // same fresh tenant must await the SAME in-flight fetchOne, not each
481
481
  // fire their own — a plain `Map<TenantId, number>` set AFTER the await
@@ -496,8 +496,8 @@ export function createTierEngineFeature(opts = {}) {
496
496
  startedMemo.set(tenantId, startedMsPromise);
497
497
  }
498
498
  const startedMs = await startedMsPromise;
499
- // Tenant-Row noch nicht projiziert (Replay-Race) → keinen Miss
500
- // memoizen, beim nächsten Request neu lesen.
499
+ // Tenant row not projected yet (replay race) → do not memoize the
500
+ // miss, re-read on the next request.
501
501
  if (startedMs === undefined) {
502
502
  startedMemo.delete(tenantId);
503
503
  return false;
@@ -509,14 +509,7 @@ export function createTierEngineFeature(opts = {}) {
509
509
  };
510
510
  // biome-ignore lint/correctness/useHookAtTopLevel: r.useExtension is a framework registrar method, not a React hook.
511
511
  r.useExtension(TENANT_TIER_RESOLVER_EXT, TIER_ENGINE_FEATURE, plugin);
512
- });
512
+ }, Object.keys(opts).length === 0 ? { dedupeOptions: {} } : undefined);
513
513
  }
514
- /**
515
- * Legacy named export — equivalent to `createTierEngineFeature()` ohne opts.
516
- * Storage-only mode (no resolver, no auto-default). Existing apps die
517
- * `tierEngineFeature` referenzieren bekommen identical behavior.
518
- *
519
- * Migration zu `createTierEngineFeature({ defaultTier, tierMap })` gibt
520
- * volle Tier-Composition (Sprint-8a Pattern).
521
- */
514
+ /** @deprecated Use createTierEngineFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
522
515
  export const tierEngineFeature = createTierEngineFeature();
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { buildEntityTable, createTenantDb } from "@cosmicdrift/kumiko-framework/db";
1
+ import { buildEntityTable, createTenantDb, fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import * as z from "zod";
5
4
  import { tierAssignmentEntity } from "../entity.js";
@@ -20,7 +19,7 @@ export const getTenantTierQuery = defineQueryHandler({
20
19
  },
21
20
  handler: async (query, ctx) => {
22
21
  const tenantId = query.payload.tenantId; // @cast-boundary engine-bridge
23
- const tdb = createTenantDb(ctx.db.unsafeRaw(), tenantId, "system");
22
+ const tdb = createTenantDb({ db: ctx.db.unsafeRaw(), tenantId, mode: "system" });
24
23
  const row = await fetchOne(tdb, tierAssignmentTable, { tenantId });
25
24
  return row ?? null;
26
25
  },
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { buildEntityTable, createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
1
+ import { buildEntityTable, createEventStoreExecutor, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import * as z from "zod";
5
4
  import { requireForTenant } from "../../shared/index.js";
@@ -23,7 +23,7 @@
23
23
  // After a run, rebuild the user projection so read_users.tenant_id reflects
24
24
  // the stream move: rebuildProjection("user:projection:user-entity", ...) or
25
25
  // the jobs:job:projection-rebuild job.
26
- import { asRawClient, transaction, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/bun-db";
26
+ import { asRawClient, transaction, unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
27
27
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
28
28
  export async function backfillUserStreamTenants(db) {
29
29
  const candidates = await unsafeReadRetrying(db, `SELECT DISTINCT "aggregate_id" FROM "kumiko_events"
@@ -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 { defineWriteHandler, findForbiddenRoleAssignment, } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { AccessDeniedError, ConflictError, InternalError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { canonicalizeLocaleTag, isValidLocaleTag } from "@cosmicdrift/kumiko-framework/i18n";
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import * 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 { access, defineEntityListHandler, } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
4
4
  // kumiko-lint-ignore cross-feature-import SystemAdmin user-list joins memberships for tenants column
@@ -1,5 +1,4 @@
1
- import { fetchOne, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { acquireNamespacedAdvisoryLock, createEventStoreExecutor, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { acquireNamespacedAdvisoryLock, createEventStoreExecutor, fetchOne, selectMany, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { createSystemUser, findForbiddenRoleAssignment, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { AccessDeniedError, ConflictError, InternalError, NotFoundError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
@@ -2,7 +2,7 @@ export { UserCommandSchemas } from "./command-schemas.js";
2
2
  export { USER_FEATURE, UserErrors, UserHandlers, UserQueries } from "./constants.js";
3
3
  export { backfillUserStreamTenants, type UserStreamBackfillResult, } from "./db/queries/stream-tenant-backfill.js";
4
4
  export { createUserFeature } from "./feature.js";
5
- export { isPrincipalBlocked, principalStatusPlugin } from "./principal-status.js";
5
+ export { isPrincipalBlocked, isPrincipalRowBlocked, principalStatusPlugin, } from "./principal-status.js";
6
6
  export { resolveUserDisplayNames } from "./resolve-display-names.js";
7
7
  export type { UserStatus } from "./schema/user.js";
8
8
  export { USER_ANONYMIZED_DISPLAY_NAME, USER_ANONYMIZED_EMAIL_DOMAIN, USER_ANONYMIZED_EMAIL_PREFIX, USER_DELETED_DISPLAY_NAME, USER_DELETED_EMAIL_PREFIX, USER_STATUS, userEntity, userTable, } from "./schema/user.js";
@@ -2,6 +2,6 @@ export { UserCommandSchemas } from "./command-schemas.js";
2
2
  export { USER_FEATURE, UserErrors, UserHandlers, UserQueries } from "./constants.js";
3
3
  export { backfillUserStreamTenants, } from "./db/queries/stream-tenant-backfill.js";
4
4
  export { createUserFeature } from "./feature.js";
5
- export { isPrincipalBlocked, principalStatusPlugin } from "./principal-status.js";
5
+ export { isPrincipalBlocked, isPrincipalRowBlocked, principalStatusPlugin, } from "./principal-status.js";
6
6
  export { resolveUserDisplayNames } from "./resolve-display-names.js";
7
7
  export { USER_ANONYMIZED_DISPLAY_NAME, USER_ANONYMIZED_EMAIL_DOMAIN, USER_ANONYMIZED_EMAIL_PREFIX, USER_DELETED_DISPLAY_NAME, USER_DELETED_EMAIL_PREFIX, USER_STATUS, userEntity, userTable, } from "./schema/user.js";
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
1
+ import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { createSystemUser, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
5
4
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
@@ -25,7 +24,7 @@ export async function grantInvitedGlobalRoles(db, options) {
25
24
  if (missingRoles.length === 0)
26
25
  return grantedGlobalRoles(currentRoles);
27
26
  const roles = [...currentRoles, ...missingRoles];
28
- const updateResult = await userExecutor.update({ id: existing.id, version: existing.version, changes: { roles } }, createSystemUser(SYSTEM_TENANT_ID), createTenantDb(db, SYSTEM_TENANT_ID, "system"));
27
+ const updateResult = await userExecutor.update({ id: existing.id, version: existing.version, changes: { roles } }, createSystemUser(SYSTEM_TENANT_ID), createTenantDb({ db, tenantId: SYSTEM_TENANT_ID, mode: "system" }));
29
28
  if (!updateResult.isSuccess)
30
29
  return updateResult;
31
30
  return grantedGlobalRoles(roles);
@@ -1,4 +1,8 @@
1
1
  import type { PrincipalStatusPlugin } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { type UserStatus } from "./schema/user.js";
3
3
  export declare function isPrincipalBlocked(status: UserStatus): boolean;
4
+ export declare function isPrincipalRowBlocked(row: {
5
+ readonly status: UserStatus;
6
+ readonly isDeleted: boolean;
7
+ }): boolean;
4
8
  export declare const principalStatusPlugin: PrincipalStatusPlugin;
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { parseRoles } from "@cosmicdrift/kumiko-framework/utils";
3
3
  import { USER_STATUS, userTable } from "./schema/user.js";
4
4
  // Locked accounts whose live sessions must be refused. deletionRequested is
@@ -12,14 +12,20 @@ const BLOCKED_STATUSES = new Set([
12
12
  export function isPrincipalBlocked(status) {
13
13
  return BLOCKED_STATUSES.has(status);
14
14
  }
15
+ // A soft-deleted row (executor.delete) keeps its last status, so isDeleted must block on its own.
16
+ export function isPrincipalRowBlocked(row) {
17
+ return row.isDeleted || isPrincipalBlocked(row.status);
18
+ }
15
19
  // Registered via r.useExtension(EXT_PRINCIPAL_STATUS, "user", principalStatusPlugin)
16
20
  // so resolveActiveMembershipFn can reject a blocked principal without knowing about `user`'s table.
17
21
  export const principalStatusPlugin = {
18
22
  async resolveStatus(userId, { db }) {
19
- const row = await fetchOne(db, userTable, { id: userId });
23
+ const row = await fetchOne(db, userTable, {
24
+ id: userId,
25
+ });
20
26
  if (!row)
21
27
  return "unknown";
22
- return isPrincipalBlocked(row.status) ? "blocked" : "active";
28
+ return isPrincipalRowBlocked(row) ? "blocked" : "active";
23
29
  },
24
30
  // ctx.queryAsMember's global-roles/timezone/locale source — same fields
25
31
  // login mints a session from (see login.write.ts gateBuildSession).
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { decryptStoredPii, mapWithConcurrency } from "../shared/index.js";
3
3
  import { userTable } from "./schema/user.js";
4
4
  // Shares the KMS adapter's small dedicated pool, same as member-directory.
@@ -9,10 +9,9 @@
9
9
  // umgehen, also kein `user.created`-Event und keine MSP-Konsumenten
10
10
  // (audit, search-index) sehen den Seed. Der Executor-Pfad emittiert
11
11
  // das Event UND schreibt die Projection-Zeile in einer TX.
12
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
13
12
  import { computeBlindIndex, configuredBlindIndexKey } from "@cosmicdrift/kumiko-framework/crypto";
14
- import { createEventStoreExecutor, createTenantDb, } from "@cosmicdrift/kumiko-framework/db";
15
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
13
+ import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
14
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
16
15
  // kumiko-lint-ignore cross-feature-import shares the postSave-hooks fixture contract with tenant/seeding (#1478)
17
16
  import { fireEntityPostSave } from "../tenant/seeding.js";
18
17
  import { userEntity, userTable } from "./schema/user.js";
@@ -32,7 +31,7 @@ hooks) {
32
31
  // executor.create erwartet eine TenantDb (mit .insert()-API). User
33
32
  // ist zwar tenant-agnostic (kein tenant_id-Spalte), aber das runtime-
34
33
  // Interface braucht den Wrap.
35
- const tdb = createTenantDb(db, by.tenantId, "system");
34
+ const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
36
35
  const existing = await fetchOne(db, userTable, { email: options.email, isDeleted: false });
37
36
  // @cast-boundary db-row: users.id ist uuid-Spalte (string), fetchOne
38
37
  // liefert die Projection-Row als Record<string, unknown>.
@@ -66,7 +65,7 @@ export async function reconcileSeededUserEmailVerified(db, existingRow, by) {
66
65
  // @cast-boundary db-row: users.id ist uuid-Spalte (string), fetchOne
67
66
  // liefert die Projection-Row als Record<string, unknown>.
68
67
  const id = existingRow["id"];
69
- const tdb = createTenantDb(db, by.tenantId, "system");
68
+ const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
70
69
  const result = await userExecutor.update({ id, version: existingRow["version"], changes: { emailVerified: true } }, by, tdb);
71
70
  // version_conflict = a concurrent write already changed the row —
72
71
  // fine for a seed helper, don't fail the whole seed run over it.
@@ -101,7 +100,7 @@ export async function rewriteSeededUserEmail(db, existingRow, email, by) {
101
100
  if (indexed)
102
101
  return;
103
102
  }
104
- const tdb = createTenantDb(db, by.tenantId, "system");
103
+ const tdb = createTenantDb({ db, tenantId: by.tenantId, mode: "system" });
105
104
  const result = await userExecutor.update({ id, version, changes: { email } }, by, tdb);
106
105
  // version_conflict: a concurrent write already changed the row — fine for a seed helper.
107
106
  // unique_violation: a duplicate row already holds the blind index; the repair
@@ -29,7 +29,7 @@ const attemptCrud = createEventStoreExecutor(downloadAttemptsTable, downloadAtte
29
29
  export async function recordDownloadUse(args) {
30
30
  const { db, tokenId, tokenVersion, tokenUseCount, tenantId, now, ip, userAgent } = args;
31
31
  const executor = createSystemUser(tenantId);
32
- const tdb = createTenantDb(db, tenantId, "system");
32
+ const tdb = createTenantDb({ db, tenantId, mode: "system" });
33
33
  await tokenCrud
34
34
  .update({
35
35
  id: tokenId,
@@ -53,7 +53,7 @@ export async function recordDownloadUse(args) {
53
53
  export async function recordInvalidAttempt(args) {
54
54
  const { db, tenantId, now } = args;
55
55
  const executor = createSystemUser(tenantId);
56
- const tdb = createTenantDb(db, tenantId, "system");
56
+ const tdb = createTenantDb({ db, tenantId, mode: "system" });
57
57
  await attemptCrud
58
58
  .create({
59
59
  result: args.result,
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { exportJobsTable } from "../../schema/export-job.js";
3
3
  // @wrapper-known semantic-alias
4
4
  export async function selectExportJobsForStorageCleanup(db, doneStatus, failedStatus) {
@@ -1,4 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
3
3
  import { userTable } from "../../../user/index.js";
4
4
  export async function selectUsersDueForForgetCleanup(db, status, gracePeriodEndCutoff) {
@@ -23,7 +23,7 @@
23
23
  // 6. Audit-Update: useCount + 1, IP, UA, lastUsedAt (best-effort)
24
24
  // 7. Return {url, expiresAt}
25
25
  import { requestContext } from "@cosmicdrift/kumiko-framework/api";
26
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
26
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
27
27
  import { defineQueryHandler, SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
28
28
  import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
29
29
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
@@ -25,7 +25,7 @@
25
25
  // **r.httpRoute-Wrapper** (siehe feature.ts) macht 302-Redirect zu
26
26
  // signedUrl — User klickt 1× Email-Link, Browser folgt redirect, Download
27
27
  // startet. Dieser query-handler liefert nur das JSON.
28
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
28
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
29
29
  import { defineQueryHandler, SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
30
30
  import { NotFoundError, UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
31
31
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
@@ -10,7 +10,7 @@
10
10
  //
11
11
  // **Read-Only-Endpoint:** Pollt nur, kein State-Flip. Idempotent + cache-
12
12
  // fest. UI poll-Intervall typisch 2-5s waehrend running.
13
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
13
+ import { selectMany } from "@cosmicdrift/kumiko-framework/db";
14
14
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
15
15
  import * as z from "zod";
16
16
  import { exportJobsTable } from "../schema/export-job.js";
@@ -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 { Temporal } from "@cosmicdrift/kumiko-types/temporal";
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 { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
4
4
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
@@ -19,8 +19,7 @@
19
19
  // `requestedFromTenantId` persistiert den Initial-Tenant aus dem
20
20
  // 1. Klick — Worker liest sein Compliance-Profile aus DIESEM Tenant
21
21
  // fuer Job-TTL/Stale/Cleanup.
22
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
23
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
22
+ import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
24
23
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
25
24
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
26
25
  import * as z from "zod";
@@ -9,7 +9,7 @@
9
9
  // Setup laeuft der Job mit `createSystemUser(...)` als executor.
10
10
  //
11
11
  // Rueckgabe: Stats fuer Operator-Monitoring (processed-count, error-list).
12
- import { access, defineWriteHandler, SYSTEM_USER_ID } from "@cosmicdrift/kumiko-framework/engine";
12
+ import { access, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
13
13
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
14
14
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
15
15
  import * as z from "zod";
@@ -46,7 +46,7 @@ export function createRunForgetCleanupHandler(opts = {}) {
46
46
  registry: ctx.registry,
47
47
  configResolver: ctx.configResolver,
48
48
  db: forgetDb,
49
- userId: ctx._userId ?? SYSTEM_USER_ID,
49
+ userId: ctx.user.id,
50
50
  });
51
51
  const result = await runForgetCleanup({
52
52
  db: runner,
@@ -59,7 +59,7 @@ export function createRunForgetCleanupHandler(opts = {}) {
59
59
  configResolver: ctx.configResolver,
60
60
  secrets: ctx.secrets,
61
61
  db: forgetDb,
62
- userId: ctx._userId ?? SYSTEM_USER_ID,
62
+ userId: ctx.user.id,
63
63
  handlerName: "user-data-rights:run-forget-cleanup",
64
64
  }),
65
65
  ...(opts.sendDeletionExecutedEmail && {
@@ -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;