@cosmicdrift/kumiko-samples 0.366.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 (411) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +16 -2
  3. package/packages/bundled-features/src/audit/handlers/details.query.ts +1 -1
  4. package/packages/bundled-features/src/audit/handlers/list.query.ts +1 -1
  5. package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +5 -5
  6. package/packages/bundled-features/src/auth-email-password/bootstrap.ts +1 -1
  7. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +10 -3
  8. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +10 -3
  9. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  10. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +6 -2
  11. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +1 -1
  12. package/packages/bundled-features/src/auth-email-password/seeding.ts +2 -2
  13. package/packages/bundled-features/src/auth-foundation/feature.ts +43 -34
  14. package/packages/bundled-features/src/auth-foundation/index.ts +1 -0
  15. package/packages/bundled-features/src/auth-mfa/db/queries.ts +5 -2
  16. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
  17. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  18. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +2 -2
  19. package/packages/bundled-features/src/auth-mfa/handlers/status.query.ts +1 -1
  20. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  21. package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +1 -1
  22. package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +1 -1
  23. package/packages/bundled-features/src/auth-mfa-user-data/index.ts +19 -10
  24. package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +1 -1
  25. package/packages/bundled-features/src/billing-foundation/feature.ts +138 -135
  26. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +1 -1
  27. package/packages/bundled-features/src/billing-foundation/projection.ts +3 -2
  28. package/packages/bundled-features/src/cap-counter/calendar-cap-usage-reservation.ts +52 -1
  29. package/packages/bundled-features/src/cap-counter/cap-reservation.ts +203 -15
  30. package/packages/bundled-features/src/cap-counter/changes.json +13 -0
  31. package/packages/bundled-features/src/cap-counter/feature.ts +84 -73
  32. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +3 -4
  33. package/packages/bundled-features/src/cap-counter/index.ts +9 -1
  34. package/packages/bundled-features/src/cap-counter/tables.ts +10 -3
  35. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -2
  36. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +6 -2
  37. package/packages/bundled-features/src/cap-overview/handlers/tenant-options.query.ts +1 -1
  38. package/packages/bundled-features/src/channel-email/changes.json +6 -0
  39. package/packages/bundled-features/src/channel-email/email-channel.ts +12 -2
  40. package/packages/bundled-features/src/channel-email/feature.ts +1 -1
  41. package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +1 -1
  42. package/packages/bundled-features/src/channel-in-app/handlers/mark-all-read.write.ts +1 -1
  43. package/packages/bundled-features/src/channel-in-app/handlers/mark-read.write.ts +1 -1
  44. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +1 -1
  45. package/packages/bundled-features/src/channel-in-app/tables.ts +1 -1
  46. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +1 -1
  47. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +1 -1
  48. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +1 -2
  49. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +1 -1
  50. package/packages/bundled-features/src/compliance-profiles/seeding.ts +8 -4
  51. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +26 -17
  52. package/packages/bundled-features/src/config/db/queries/resolver.ts +1 -1
  53. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +2 -2
  54. package/packages/bundled-features/src/config/resolver.ts +1 -1
  55. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  56. package/packages/bundled-features/src/crypto-shredding/changes.json +6 -0
  57. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +9 -7
  58. package/packages/bundled-features/src/custom-fields/db/queries/field-access.ts +1 -1
  59. package/packages/bundled-features/src/custom-fields/db/queries/projection.ts +1 -1
  60. package/packages/bundled-features/src/custom-fields/db/queries/quota.ts +1 -1
  61. package/packages/bundled-features/src/custom-fields/db/queries/retention.ts +6 -2
  62. package/packages/bundled-features/src/custom-fields/db/queries/user-data-rights.ts +1 -1
  63. package/packages/bundled-features/src/custom-fields/feature.ts +11 -14
  64. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +2 -2
  65. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +2 -2
  66. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +2 -2
  67. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +2 -2
  68. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +4 -4
  69. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  70. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +16 -10
  71. package/packages/bundled-features/src/delivery/address-opt-out.ts +5 -2
  72. package/packages/bundled-features/src/delivery/attempt-log-retention.ts +1 -1
  73. package/packages/bundled-features/src/delivery/changes.json +12 -0
  74. package/packages/bundled-features/src/delivery/channel-context.ts +2 -1
  75. package/packages/bundled-features/src/delivery/db/queries/address-opt-outs.ts +1 -1
  76. package/packages/bundled-features/src/delivery/db/queries/preferences.ts +1 -1
  77. package/packages/bundled-features/src/delivery/delivery-service.ts +70 -8
  78. package/packages/bundled-features/src/delivery/feature.ts +2 -2
  79. package/packages/bundled-features/src/delivery/handlers/log.query.ts +3 -2
  80. package/packages/bundled-features/src/delivery/handlers/preferences.query.ts +1 -1
  81. package/packages/bundled-features/src/delivery/handlers/unsubscribe-address.write.ts +10 -5
  82. package/packages/bundled-features/src/delivery/index.ts +6 -0
  83. package/packages/bundled-features/src/delivery/testing.ts +2 -0
  84. package/packages/bundled-features/src/delivery/types.ts +4 -0
  85. package/packages/bundled-features/src/delivery/unsubscribe-link.ts +73 -0
  86. package/packages/bundled-features/src/delivery/unsubscribe-page-strings.ts +17 -0
  87. package/packages/bundled-features/src/delivery/unsubscribe.ts +94 -31
  88. package/packages/bundled-features/src/delivery/upsert-preference.ts +5 -2
  89. package/packages/bundled-features/src/derivatives-sharp/feature.ts +21 -12
  90. package/packages/bundled-features/src/derivatives-sharp/index.ts +1 -1
  91. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +112 -103
  92. package/packages/bundled-features/src/document-ingest-foundation/forget-extract-with-file-ref.ts +3 -3
  93. package/packages/bundled-features/src/document-ingest-foundation/index.ts +4 -1
  94. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  95. package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -5
  96. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  97. package/packages/bundled-features/src/file-derivatives/feature.ts +134 -129
  98. package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +1 -1
  99. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  100. package/packages/bundled-features/src/file-foundation/feature.ts +38 -29
  101. package/packages/bundled-features/src/file-foundation/index.ts +1 -0
  102. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +1 -1
  103. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +32 -21
  104. package/packages/bundled-features/src/file-provider-inmemory/index.ts +6 -1
  105. package/packages/bundled-features/src/file-provider-s3/changes.json +10 -1
  106. package/packages/bundled-features/src/file-provider-s3/env-feature.ts +62 -0
  107. package/packages/bundled-features/src/file-provider-s3/feature.ts +107 -73
  108. package/packages/bundled-features/src/file-provider-s3/index.ts +6 -1
  109. package/packages/bundled-features/src/file-provider-s3/lib/index.ts +3 -0
  110. package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/s3-provider.ts +19 -19
  111. package/packages/bundled-features/src/file-provider-s3-env/index.ts +7 -2
  112. package/packages/bundled-features/src/files-provider-s3/index.ts +11 -3
  113. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +1 -1
  114. package/packages/bundled-features/src/files-tenant-data/hooks.ts +1 -2
  115. package/packages/bundled-features/src/folders/feature.ts +8 -3
  116. package/packages/bundled-features/src/folders-user-data/index.ts +27 -18
  117. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
  118. package/packages/bundled-features/src/form-draft/db/queries/draft-count.ts +1 -1
  119. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +3 -2
  120. package/packages/bundled-features/src/form-draft/feature.ts +6 -1
  121. package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +2 -2
  122. package/packages/bundled-features/src/form-draft/index.ts +1 -1
  123. package/packages/bundled-features/src/form-draft/lookup.ts +1 -1
  124. package/packages/bundled-features/src/form-draft-user-data/index.ts +19 -10
  125. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +165 -154
  126. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +1 -2
  127. package/packages/bundled-features/src/inbound-mail-foundation/index.ts +1 -1
  128. package/packages/bundled-features/src/inbound-mail-foundation/oauth-access-token.ts +5 -2
  129. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +3 -2
  130. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
  131. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +22 -13
  132. package/packages/bundled-features/src/inbound-provider-imap/index.ts +6 -1
  133. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +20 -12
  134. package/packages/bundled-features/src/inbound-provider-inmemory/index.ts +1 -0
  135. package/packages/bundled-features/src/jobs/db/queries/retention.ts +1 -1
  136. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +1 -1
  137. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +1 -1
  138. package/packages/bundled-features/src/jobs/handlers/list.query.ts +7 -2
  139. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  140. package/packages/bundled-features/src/jobs/handlers/tenant-failures.query.ts +1 -1
  141. package/packages/bundled-features/src/jobs/handlers/tenant-runs.query.ts +1 -1
  142. package/packages/bundled-features/src/jobs/job-run-logger.ts +11 -10
  143. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  144. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  145. package/packages/bundled-features/src/ledger/feature.ts +6 -3
  146. package/packages/bundled-features/src/mail-foundation/feature.ts +107 -55
  147. package/packages/bundled-features/src/mail-foundation/index.ts +4 -0
  148. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +25 -17
  149. package/packages/bundled-features/src/mail-transport-inmemory/index.ts +6 -1
  150. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +91 -79
  151. package/packages/bundled-features/src/mail-transport-smtp/index.ts +1 -0
  152. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +1 -1
  153. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +1 -2
  154. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +1 -2
  155. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -4
  156. package/packages/bundled-features/src/metrics/compute.ts +1 -1
  157. package/packages/bundled-features/src/metrics/filters.ts +1 -1
  158. package/packages/bundled-features/src/metrics/validate.ts +1 -1
  159. package/packages/bundled-features/src/notes-history/feature.ts +6 -3
  160. package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
  161. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  162. package/packages/bundled-features/src/notes-history-user-data/index.ts +27 -18
  163. package/packages/bundled-features/src/personal-access-tokens/changes.json +6 -0
  164. package/packages/bundled-features/src/personal-access-tokens/feature.ts +17 -2
  165. package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
  166. package/packages/bundled-features/src/personal-access-tokens/handlers/list.query.ts +2 -2
  167. package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
  168. package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
  169. package/packages/bundled-features/src/personal-access-tokens/revoke-for-user.ts +2 -2
  170. package/packages/bundled-features/src/personal-access-tokens/roles.ts +8 -6
  171. package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -0
  172. package/packages/bundled-features/src/readiness/feature.ts +25 -16
  173. package/packages/bundled-features/src/readiness/index.ts +1 -1
  174. package/packages/bundled-features/src/secrets/db/queries/read.ts +1 -1
  175. package/packages/bundled-features/src/secrets/feature.ts +8 -3
  176. package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +2 -2
  177. package/packages/bundled-features/src/secrets/secrets-context.ts +4 -3
  178. package/packages/bundled-features/src/sessions/db/queries/cleanup.ts +1 -1
  179. package/packages/bundled-features/src/sessions/handlers/detail.query.ts +1 -1
  180. package/packages/bundled-features/src/sessions/handlers/list.query.ts +2 -2
  181. package/packages/bundled-features/src/sessions/handlers/mine.query.ts +1 -1
  182. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +1 -1
  183. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
  184. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  185. package/packages/bundled-features/src/sessions/session-callbacks.ts +14 -7
  186. package/packages/bundled-features/src/sessions/testing.ts +1 -1
  187. package/packages/bundled-features/src/tags/feature.ts +6 -3
  188. package/packages/bundled-features/src/template-resolver/api.ts +1 -1
  189. package/packages/bundled-features/src/template-resolver/changes.json +25 -0
  190. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +61 -9
  191. package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +19 -0
  192. package/packages/bundled-features/src/template-resolver/document-schema.ts +33 -0
  193. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +10 -2
  194. package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +1 -1
  195. package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +1 -2
  196. package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
  197. package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -2
  198. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +1 -1
  199. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +9 -3
  200. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +1 -1
  201. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
  202. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +9 -2
  203. package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +1 -1
  204. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +7 -2
  205. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +8 -3
  206. package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +1 -1
  207. package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +1 -1
  208. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
  209. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +22 -2
  210. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +1 -1
  211. package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +1 -1
  212. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
  213. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +1 -1
  214. package/packages/bundled-features/src/template-resolver/index.ts +4 -0
  215. package/packages/bundled-features/src/template-resolver/qualified-names.ts +1 -0
  216. package/packages/bundled-features/src/template-resolver/seeding.ts +57 -10
  217. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +1 -1
  218. package/packages/bundled-features/src/template-resolver/template-preview.ts +3 -1
  219. package/packages/bundled-features/src/template-resolver/template-resources.ts +1 -1
  220. package/packages/bundled-features/src/template-resolver/template-system-only.ts +21 -0
  221. package/packages/bundled-features/src/template-resolver/template-validation.ts +48 -24
  222. package/packages/bundled-features/src/template-resolver/testing.ts +1 -1
  223. package/packages/bundled-features/src/template-resolver/web/i18n.ts +2 -0
  224. package/packages/bundled-features/src/template-resolver-user-data/index.ts +23 -14
  225. package/packages/bundled-features/src/tenant/handlers/active-tenant-ids.query.ts +1 -1
  226. package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -2
  227. package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
  228. package/packages/bundled-features/src/tenant/handlers/invitations.query.ts +1 -1
  229. package/packages/bundled-features/src/tenant/handlers/me.query.ts +1 -1
  230. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
  231. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  232. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  233. package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -1
  234. package/packages/bundled-features/src/tenant/handlers/resolve-user-ids.query.ts +1 -1
  235. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  236. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
  237. package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -2
  238. package/packages/bundled-features/src/tenant/invited-membership.ts +2 -2
  239. package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -2
  240. package/packages/bundled-features/src/tenant/seeding.ts +12 -12
  241. package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +1 -2
  242. package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +1 -2
  243. package/packages/bundled-features/src/tenant-lifecycle/lib/revoke-tenant-sessions.ts +1 -1
  244. package/packages/bundled-features/src/tenant-lifecycle/lifecycle-gate.ts +1 -1
  245. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +3 -3
  246. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +10 -5
  247. package/packages/bundled-features/src/tenant-lifecycle/testing.ts +3 -3
  248. package/packages/bundled-features/src/tenant-settings/feature.ts +34 -29
  249. package/packages/bundled-features/src/tier-engine/feature.ts +426 -428
  250. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +2 -3
  251. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +5 -2
  252. package/packages/bundled-features/src/user/changes.json +6 -0
  253. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +1 -1
  254. package/packages/bundled-features/src/user/handlers/create.write.ts +1 -2
  255. package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +1 -1
  256. package/packages/bundled-features/src/user/handlers/list.query.ts +1 -1
  257. package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -1
  258. package/packages/bundled-features/src/user/index.ts +5 -1
  259. package/packages/bundled-features/src/user/invited-global-roles.ts +2 -2
  260. package/packages/bundled-features/src/user/principal-status.ts +13 -3
  261. package/packages/bundled-features/src/user/resolve-display-names.ts +1 -1
  262. package/packages/bundled-features/src/user/seeding.ts +5 -5
  263. package/packages/bundled-features/src/user-data-rights/audit-download.ts +2 -2
  264. package/packages/bundled-features/src/user-data-rights/changes.json +6 -0
  265. package/packages/bundled-features/src/user-data-rights/db/queries/export-jobs.ts +1 -1
  266. package/packages/bundled-features/src/user-data-rights/db/queries/forget-cleanup.ts +1 -1
  267. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +1 -1
  268. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +1 -1
  269. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +1 -1
  270. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +1 -1
  271. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +1 -1
  272. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +1 -2
  273. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +3 -3
  274. package/packages/bundled-features/src/user-data-rights/lib/deny-if-target-outside-admin-tenant.ts +1 -1
  275. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +7 -2
  276. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +7 -3
  277. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +11 -5
  278. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +10 -5
  279. package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +1 -2
  280. package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
  281. package/packages/bundled-features/src/waitlist/lib.ts +5 -2
  282. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +1 -1
  283. package/packages/bundled-features/src/workflow-runner/feature.ts +58 -47
  284. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +1 -1
  285. package/packages/bundled-features/src/workflow-runner/index.ts +1 -1
  286. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +1 -1
  287. package/samples/apps/admin-console/src/run-config.ts +2 -2
  288. package/samples/apps/cap-billing-demo/package.json +3 -0
  289. package/samples/apps/cap-billing-demo/src/feature.ts +2 -2
  290. package/samples/apps/cap-billing-demo/src/run-config.ts +8 -8
  291. package/samples/apps/marketing-demo/src/app/seed.ts +1 -1
  292. package/samples/apps/marketing-demo/src/db/queries/seed-counts.ts +1 -1
  293. package/samples/apps/showcase/package.json +3 -0
  294. package/samples/apps/showcase/src/app/seed-items.ts +1 -1
  295. package/samples/apps/styleguide/src/app/seed.ts +2 -2
  296. package/samples/apps/styleguide/src/features/ai-settings/seed.ts +2 -2
  297. package/samples/apps/ui-walkthrough/scripts/emit-e2e-data.ts +1 -1
  298. package/samples/apps/ui-walkthrough/src/app/auth-constants.ts +1 -1
  299. package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +2 -2
  300. package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +2 -0
  301. package/samples/apps/ui-walkthrough/src/app/seed-vehicles.ts +1 -1
  302. package/samples/apps/ui-walkthrough/src/app/seed.ts +1 -1
  303. package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +12 -0
  304. package/samples/apps/ui-walkthrough/src/db/queries/row-counts.ts +1 -1
  305. package/samples/apps/ui-walkthrough/src/db/queries/task-counts.ts +1 -1
  306. package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +7 -0
  307. package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +2 -0
  308. package/samples/apps/use-all-bundled/feature-manifest.json +4 -4
  309. package/samples/apps/use-all-bundled/package.json +4 -0
  310. package/samples/apps/use-all-bundled/scripts/check-coverage.ts +2 -2
  311. package/samples/apps/use-all-bundled/src/app/auth-constants.ts +1 -1
  312. package/samples/apps/use-all-bundled/src/app/cap-overview-caps.ts +2 -2
  313. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +1 -1
  314. package/samples/apps/use-all-bundled/src/app/seed-documents.ts +1 -1
  315. package/samples/apps/use-all-bundled/src/app/seed.ts +11 -5
  316. package/samples/apps/use-all-bundled/src/run-config.ts +55 -56
  317. package/samples/apps/user-data-rights-demo/README.md +2 -2
  318. package/samples/apps/user-data-rights-demo/package.json +3 -0
  319. package/samples/apps/user-data-rights-demo/src/run-config.ts +7 -7
  320. package/samples/apps/workspaces/package.json +3 -0
  321. package/samples/recipes/access-control/package.json +3 -0
  322. package/samples/recipes/anonymous-access/package.json +3 -0
  323. package/samples/recipes/anonymous-access-multitenant/package.json +3 -0
  324. package/samples/recipes/apex-landing/package.json +1 -0
  325. package/samples/recipes/apex-surface-auth/package.json +3 -0
  326. package/samples/recipes/apex-surface-auth/src/feature.ts +2 -2
  327. package/samples/recipes/api-worker-split/package.json +3 -0
  328. package/samples/recipes/api-worker-split/src/feature.ts +1 -2
  329. package/samples/recipes/auth-claims/package.json +3 -0
  330. package/samples/recipes/auth-foundation-providers/src/feature.ts +1 -1
  331. package/samples/recipes/auth-mfa/package.json +3 -0
  332. package/samples/recipes/basic-entity/package.json +3 -0
  333. package/samples/recipes/chat-channels/package.json +3 -0
  334. package/samples/recipes/compliance-profiles-demo/package.json +3 -0
  335. package/samples/recipes/cross-feature-events/package.json +3 -1
  336. package/samples/recipes/cross-feature-events/src/feature.ts +1 -1
  337. package/samples/recipes/crypto-shredding-hr/package.json +3 -0
  338. package/samples/recipes/currencies-global/package.json +3 -0
  339. package/samples/recipes/currencies-per-tenant/package.json +3 -0
  340. package/samples/recipes/custom-fields-basic/package.json +3 -0
  341. package/samples/recipes/custom-handlers/package.json +3 -0
  342. package/samples/recipes/dashboard-stats/package.json +3 -0
  343. package/samples/recipes/delivery-notifications/package.json +3 -0
  344. package/samples/recipes/e2e-generator/package.json +3 -0
  345. package/samples/recipes/embedded/package.json +3 -0
  346. package/samples/recipes/embedded-entity-form/package.json +1 -0
  347. package/samples/recipes/encrypted-tenant-config/README.md +1 -1
  348. package/samples/recipes/encrypted-tenant-config/package.json +3 -0
  349. package/samples/recipes/error-contract/package.json +3 -0
  350. package/samples/recipes/event-sourcing/package.json +3 -1
  351. package/samples/recipes/event-sourcing/src/feature.ts +16 -20
  352. package/samples/recipes/event-sourcing/tsconfig.json +2 -6
  353. package/samples/recipes/feature-toggles/package.json +3 -0
  354. package/samples/recipes/field-access/package.json +3 -0
  355. package/samples/recipes/files-post-processing/package.json +1 -0
  356. package/samples/recipes/golden-path/README.md +30 -0
  357. package/samples/recipes/golden-path/package.json +11 -0
  358. package/samples/recipes/golden-path/src/feature.ts +70 -0
  359. package/samples/recipes/idempotency/package.json +3 -0
  360. package/samples/recipes/inbound-mail-triage/package.json +3 -0
  361. package/samples/recipes/lane-routing/package.json +3 -0
  362. package/samples/recipes/ledger-banking/package.json +3 -0
  363. package/samples/recipes/ledger-invoicing/package.json +3 -0
  364. package/samples/recipes/legal-pages/package.json +3 -0
  365. package/samples/recipes/lifecycle-hooks/package.json +3 -0
  366. package/samples/recipes/managed-config/package.json +3 -0
  367. package/samples/recipes/managed-pages/package.json +3 -0
  368. package/samples/recipes/notes-history-basic/package.json +3 -0
  369. package/samples/recipes/ownership/package.json +3 -0
  370. package/samples/recipes/pdf-audit-export/package.json +1 -0
  371. package/samples/recipes/pipeline-basics/package.json +3 -0
  372. package/samples/recipes/public-share-token/package.json +3 -0
  373. package/samples/recipes/public-share-token/src/feature.ts +1 -1
  374. package/samples/recipes/rate-limiting/package.json +3 -0
  375. package/samples/recipes/realtime-sse/package.json +3 -0
  376. package/samples/recipes/record-detail-layout/package.json +1 -0
  377. package/samples/recipes/reference-data/package.json +3 -0
  378. package/samples/recipes/relations/package.json +3 -0
  379. package/samples/recipes/screens-nav/package.json +3 -0
  380. package/samples/recipes/search/package.json +3 -0
  381. package/samples/recipes/secrets-demo/package.json +3 -0
  382. package/samples/recipes/security-baseline/src/feature.ts +2 -2
  383. package/samples/recipes/session-revocation/README.md +1 -1
  384. package/samples/recipes/session-revocation/package.json +3 -0
  385. package/samples/recipes/session-revocation/src/feature.ts +1 -1
  386. package/samples/recipes/state-machine/package.json +3 -1
  387. package/samples/recipes/state-machine/src/entities/invoice.ts +2 -2
  388. package/samples/recipes/state-machine/src/events.ts +19 -0
  389. package/samples/recipes/state-machine/src/feature.ts +25 -30
  390. package/samples/recipes/state-machine/src/handlers/_helpers.ts +13 -14
  391. package/samples/recipes/state-machine/src/handlers/create.ts +1 -1
  392. package/samples/recipes/state-machine/src/handlers/transitions.ts +129 -122
  393. package/samples/recipes/state-machine/src/reducer.ts +1 -1
  394. package/samples/recipes/state-machine/tsconfig.json +2 -6
  395. package/samples/recipes/tags-basic/package.json +3 -0
  396. package/samples/recipes/tenant-isolation/package.json +3 -0
  397. package/samples/recipes/tenant-settings/package.json +3 -0
  398. package/samples/recipes/tier-admin/package.json +3 -0
  399. package/samples/recipes/timezones/package.json +3 -0
  400. package/samples/recipes/tsconfig.base.json +1 -1
  401. package/samples/recipes/user-data-rights/package.json +3 -0
  402. package/samples/recipes/user-data-rights/src/feature.ts +6 -2
  403. package/samples/recipes/user-profile/package.json +3 -0
  404. package/samples/recipes/user-profile/src/feature.ts +2 -2
  405. package/samples/recipes/webhook-step/package.json +3 -0
  406. package/samples/recipes/wizard-form/package.json +1 -0
  407. package/samples/recipes/workflow-engine/package.json +3 -0
  408. package/samples/recipes/workflow-engine/src/db/queries/suspended-runs.ts +5 -2
  409. package/samples/recipes/writeform-section/package.json +1 -0
  410. package/packages/bundled-features/src/file-provider-s3-env/feature.ts +0 -58
  411. /package/packages/bundled-features/src/{files-provider-s3 → file-provider-s3/lib}/env-helper.ts +0 -0
@@ -35,55 +35,66 @@ import { workflowRunPendingTableMeta } from "./tables.js";
35
35
  // use-all-bundled's check-coverage matches exports to mounted features by it.
36
36
  const FEATURE_NAME = "workflow-runner";
37
37
 
38
- export const workflowRunnerFeature = defineFeature(FEATURE_NAME, (r) => {
39
- r.describe(
40
- "Writes the run-envelope (`workflow.run-started` / `workflow.run-completed` / `workflow.run-failed`) for a workflow run onto its `workflow-run` aggregate stream. Provides `startAndRunWorkflow` and `registerEventTrigger` for consumer features to wire up `defineWorkflow`-based workflows against domain events. Registers no workflows itself. Runs the resume loop for suspended `wait`/`retry`/`waitForEvent` steps (`resume-due-runs` job + `resume-run` handler); `registerEventTrigger` wires an event-wakeup subscriber per workflow that declares `awaits` so a `waitForEvent` step resumes as soon as its awaited event arrives, not just on timeout.",
41
- );
42
- r.uiHints({
43
- displayLabel: "Workflow Runner",
44
- category: "infrastructure",
45
- recommended: false,
46
- });
47
- // resume-run needs a full HandlerContext + ctx.systemDb (the pending-row
48
- // scan crosses whatever tenant the row belongs to relative to the job's
49
- // own tenant loop iteration) — same reasoning as tenant/feature.ts.
50
- r.systemScope();
51
- r.storeTable(workflowRunPendingTableMeta, {
52
- reason: "resume_loop.pending_suspended_steps",
53
- });
54
- registerWorkflowRunPendingProjection(r);
55
- r.writeHandler(resumeRunHandler);
56
-
57
- r.job(
58
- "resume-due-runs",
59
- { trigger: { cron: "* * * * *" }, perTenant: true, concurrency: "skip" },
60
- async (_payload, ctx) => {
61
- if (!ctx.systemDb) {
62
- throw new Error("resume-due-runs: ctx.systemDb required (r.systemScope() feature)");
63
- }
64
- const tenantId = ctx.systemUser?.tenantId ?? ctx._tenantId;
65
- if (tenantId === undefined) {
66
- // skip: cron fired without a perTenant fan-out tenant — nothing scoped
67
- return;
68
- }
38
+ export function createWorkflowRunnerFeature() {
39
+ return defineFeature(
40
+ FEATURE_NAME,
41
+ (r) => {
42
+ r.describe(
43
+ "Writes the run-envelope (`workflow.run-started` / `workflow.run-completed` / `workflow.run-failed`) for a workflow run onto its `workflow-run` aggregate stream. Provides `startAndRunWorkflow` and `registerEventTrigger` for consumer features to wire up `defineWorkflow`-based workflows against domain events. Registers no workflows itself. Runs the resume loop for suspended `wait`/`retry`/`waitForEvent` steps (`resume-due-runs` job + `resume-run` handler); `registerEventTrigger` wires an event-wakeup subscriber per workflow that declares `awaits` so a `waitForEvent` step resumes as soon as its awaited event arrives, not just on timeout.",
44
+ );
45
+ r.uiHints({
46
+ displayLabel: "Workflow Runner",
47
+ category: "infrastructure",
48
+ recommended: false,
49
+ });
50
+ // resume-run needs a full HandlerContext + ctx.systemDb (the pending-row
51
+ // scan crosses whatever tenant the row belongs to relative to the job's
52
+ // own tenant loop iteration) — same reasoning as tenant/feature.ts.
53
+ r.systemScope();
54
+ r.storeTable(workflowRunPendingTableMeta, {
55
+ reason: "resume_loop.pending_suspended_steps",
56
+ });
57
+ registerWorkflowRunPendingProjection(r);
58
+ r.writeHandler(resumeRunHandler);
69
59
 
70
- const dueRows = await selectDueWorkflowRunPending(ctx.systemDb.assertTenantMatch(tenantId));
60
+ r.job(
61
+ "resume-due-runs",
62
+ { trigger: { cron: "* * * * *" }, perTenant: true, concurrency: "skip" },
63
+ async (_payload, ctx) => {
64
+ if (!ctx.systemDb) {
65
+ throw new Error("resume-due-runs: ctx.systemDb required (r.systemScope() feature)");
66
+ }
67
+ const tenantId = ctx.systemUser?.tenantId ?? ctx._tenantId;
68
+ if (tenantId === undefined) {
69
+ // skip: cron fired without a perTenant fan-out tenant — nothing scoped
70
+ return;
71
+ }
71
72
 
72
- for (const row of dueRows) {
73
- try {
74
- await ctx.write("workflow-runner:write:resume-run", {
75
- runId: row.runId,
76
- stepIndex: row.stepIndex,
77
- });
78
- } catch (error) {
79
- // skip: one row's dispatch failing (infra hiccup, not a business
80
- // outcome — resume-run itself never throws for expected cases)
81
- // must not stop the rest of this tenant's due rows from resuming.
82
- ctx.log.warn(
83
- `[workflow-runner:resume-due-runs] runId=${row.runId} stepIndex=${row.stepIndex} dispatch failed: ${String(error)}`,
73
+ const dueRows = await selectDueWorkflowRunPending(
74
+ ctx.systemDb.assertTenantMatch(tenantId),
84
75
  );
85
- }
86
- }
76
+
77
+ for (const row of dueRows) {
78
+ try {
79
+ await ctx.write("workflow-runner:write:resume-run", {
80
+ runId: row.runId,
81
+ stepIndex: row.stepIndex,
82
+ });
83
+ } catch (error) {
84
+ // skip: one row's dispatch failing (infra hiccup, not a business
85
+ // outcome — resume-run itself never throws for expected cases)
86
+ // must not stop the rest of this tenant's due rows from resuming.
87
+ ctx.log.warn(
88
+ `[workflow-runner:resume-due-runs] runId=${row.runId} stepIndex=${row.stepIndex} dispatch failed: ${String(error)}`,
89
+ );
90
+ }
91
+ }
92
+ },
93
+ );
87
94
  },
95
+ { dedupeOptions: {} },
88
96
  );
89
- });
97
+ }
98
+
99
+ /** @deprecated Use createWorkflowRunnerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
100
+ export const workflowRunnerFeature = createWorkflowRunnerFeature();
@@ -30,7 +30,7 @@
30
30
  // resultKey on steps/wait-for-event.ts) — pre-seeded into stepsAcc below so
31
31
  // a subsequent step's resolver can read `ctx.steps[awaits.someKey]`.
32
32
 
33
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
33
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
34
34
  import {
35
35
  buildPipelineSteps,
36
36
  computeDefinitionFingerprint,
@@ -2,7 +2,7 @@
2
2
 
3
3
  export { workflowRunAggregateId } from "./aggregate-id.js";
4
4
  export { registerEventTrigger } from "./event-trigger.js";
5
- export { workflowRunnerFeature } from "./feature.js";
5
+ export { createWorkflowRunnerFeature, workflowRunnerFeature } from "./feature.js";
6
6
  export {
7
7
  startAndRunWorkflow,
8
8
  type WorkflowRunCompletedPayload,
@@ -12,8 +12,8 @@
12
12
  // this table and dispatches the actual resume. This projection only writes
13
13
  // the rows.
14
14
 
15
- import { deleteMany, fetchOne, upsertOnConflict } from "@cosmicdrift/kumiko-framework/bun-db";
16
15
  import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
16
+ import { deleteMany, fetchOne, upsertOnConflict } from "@cosmicdrift/kumiko-framework/db";
17
17
  import type {
18
18
  FeatureRegistrar,
19
19
  MultiStreamProjectionDefinition,
@@ -14,7 +14,7 @@ import {
14
14
  tenantJobFailuresMetric,
15
15
  } from "@cosmicdrift/kumiko-bundled-features/metrics";
16
16
  import { createSecretsFeature } from "@cosmicdrift/kumiko-bundled-features/secrets";
17
- import { tierEngineFeature } from "@cosmicdrift/kumiko-bundled-features/tier-engine";
17
+ import { createTierEngineFeature } from "@cosmicdrift/kumiko-bundled-features/tier-engine";
18
18
  import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
19
19
  import { localeDe } from "@cosmicdrift/kumiko-locale-de";
20
20
 
@@ -50,7 +50,7 @@ export const APP_FEATURES = [
50
50
  createAuditFeature(),
51
51
  createDeliveryFeature(),
52
52
  createJobsFeature(),
53
- tierEngineFeature,
53
+ createTierEngineFeature(),
54
54
  createMetricsFeature({ metrics: CONSOLE_METRICS }),
55
55
  createSystemMetricsFeature({ metrics: CONSOLE_METRICS }),
56
56
  createAdminShellFeature({ metrics: CONSOLE_METRICS }),
@@ -12,5 +12,8 @@
12
12
  "@cosmicdrift/kumiko-framework": "workspace:*",
13
13
  "zod": "^4.4.3",
14
14
  "@cosmicdrift/kumiko-locale-de": "workspace:*"
15
+ },
16
+ "devDependencies": {
17
+ "@cosmicdrift/kumiko-testing": "workspace:*"
15
18
  }
16
19
  }
@@ -38,8 +38,8 @@ import {
38
38
  } from "@cosmicdrift/kumiko-bundled-features/cap-counter";
39
39
  import type { EmailMessage } from "@cosmicdrift/kumiko-bundled-features/channel-email";
40
40
  import {
41
+ createMailFoundationFeature,
41
42
  createTransportForTenant,
42
- mailFoundationFeature,
43
43
  } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
44
44
  import {
45
45
  access,
@@ -185,7 +185,7 @@ export const newsletterFeature = defineFeature(FEATURE_NAME, (r) => {
185
185
  // klarer für boot-Validator-Errors).
186
186
  r.requires({ features: ["config"] });
187
187
  r.requires({ features: ["cap-counter"] });
188
- r.requires({ features: [mailFoundationFeature.name] });
188
+ r.requires({ features: [createMailFoundationFeature().name] });
189
189
  r.requires({ features: [BILLING_FOUNDATION_FEATURE] });
190
190
 
191
191
  // Tier-config-key. Tenant-Admin setzt's; default "free".
@@ -18,11 +18,11 @@
18
18
  // der eigenen run-config.
19
19
  // - newsletter — die Demo-Domain mit cap-aware send
20
20
 
21
- import { billingFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
22
- import { capCounterFeature } from "@cosmicdrift/kumiko-bundled-features/cap-counter";
21
+ import { createBillingFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/billing-foundation";
22
+ import { createCapCounterFeature } from "@cosmicdrift/kumiko-bundled-features/cap-counter";
23
23
  import { createComplianceProfilesFeature } from "@cosmicdrift/kumiko-bundled-features/compliance-profiles";
24
- import { mailFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
25
- import { mailTransportInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-inmemory";
24
+ import { createMailFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
25
+ import { createMailTransportInMemoryFeature } from "@cosmicdrift/kumiko-bundled-features/mail-transport-inmemory";
26
26
  import { createSecretsFeature } from "@cosmicdrift/kumiko-bundled-features/secrets";
27
27
  import { createTenantLifecycleFeature } from "@cosmicdrift/kumiko-bundled-features/tenant-lifecycle";
28
28
  import { localeDe } from "@cosmicdrift/kumiko-locale-de";
@@ -39,12 +39,12 @@ import { newsletterFeature } from "./feature";
39
39
  export const APP_FEATURES = [
40
40
  localeDe(),
41
41
  createSecretsFeature(),
42
- capCounterFeature,
43
- mailFoundationFeature,
44
- mailTransportInMemoryFeature,
42
+ createCapCounterFeature(),
43
+ createMailFoundationFeature(),
44
+ createMailTransportInMemoryFeature(),
45
45
  createComplianceProfilesFeature(),
46
46
  createTenantLifecycleFeature(),
47
- billingFoundationFeature,
47
+ createBillingFoundationFeature(),
48
48
  newsletterFeature,
49
49
  ] as const;
50
50
 
@@ -9,7 +9,7 @@
9
9
  // nur Logik: Random-Generator, Datums-Helper, der eigentliche Seed.
10
10
 
11
11
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
12
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
12
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
13
13
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
14
14
  import { countAssetsForTenant, countTicketsForTenant } from "../db/queries/seed-counts";
15
15
  import { ASSET_STATUSES } from "../features/assets/schema";
@@ -1,5 +1,5 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
2
+ import { asRawClient } from "@cosmicdrift/kumiko-framework/db";
3
3
 
4
4
  export async function countAssetsForTenant(db: DbRunner, tenantId: string): Promise<number> {
5
5
  const rows = await asRawClient(db).unsafe<{ count: number }>(
@@ -19,5 +19,8 @@
19
19
  "react": "^19.2.6",
20
20
  "react-dom": "^19.2.6",
21
21
  "@cosmicdrift/kumiko-locale-de": "workspace:*"
22
+ },
23
+ "devDependencies": {
24
+ "@cosmicdrift/kumiko-testing": "workspace:*"
22
25
  }
23
26
  }
@@ -9,7 +9,7 @@
9
9
  // bei jedem Restart neu geseeded sonst.
10
10
 
11
11
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
12
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
12
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
13
13
 
14
14
  const STATUSES = ["draft", "active", "blocked", "done"] as const;
15
15
 
@@ -1,7 +1,7 @@
1
1
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
2
2
  import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { createEntityExecutor } from "@cosmicdrift/kumiko-framework/engine";
4
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
4
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
5
5
 
6
6
  import { demoEntity } from "../features/demo/feature";
7
7
 
@@ -26,7 +26,7 @@ export const seedStyleguideItems: SeedFn = async (stack) => {
26
26
  // Calling the executor directly is the framework's documented "seed
27
27
  // pattern" for a caller-chosen aggregate id (event-store-executor-write.ts).
28
28
  const { executor } = createEntityExecutor("item", demoEntity);
29
- const tenantDb = createTenantDb(stack.db, TestUsers.admin.tenantId);
29
+ const tenantDb = createTenantDb({ db: stack.db, tenantId: TestUsers.admin.tenantId });
30
30
 
31
31
  for (let i = 0; i < 8; i++) {
32
32
  const payload = {
@@ -1,14 +1,14 @@
1
1
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
2
2
  import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
3
3
  import { createEntityExecutor } from "@cosmicdrift/kumiko-framework/engine";
4
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
4
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
5
5
 
6
6
  import { ANTHROPIC_CONNECTION_ID, OPENROUTER_CONNECTION_ID } from "./catalog";
7
7
  import { connectionEntity } from "./feature";
8
8
 
9
9
  export const seedAiConnections: SeedFn = async (stack) => {
10
10
  const { executor } = createEntityExecutor("connection", connectionEntity);
11
- const tenantDb = createTenantDb(stack.db, TestUsers.admin.tenantId);
11
+ const tenantDb = createTenantDb({ db: stack.db, tenantId: TestUsers.admin.tenantId });
12
12
  const connections = [
13
13
  {
14
14
  id: ANTHROPIC_CONNECTION_ID,
@@ -7,7 +7,7 @@
7
7
  import { mkdir, writeFile } from "node:fs/promises";
8
8
  import { dirname, resolve } from "node:path";
9
9
  import { createRegistry } from "@cosmicdrift/kumiko-framework/engine";
10
- import { generateE2ESpec } from "@cosmicdrift/kumiko-framework/testing/e2e-generator";
10
+ import { generateE2ESpec } from "@cosmicdrift/kumiko-testing/helpers/e2e-generator";
11
11
  import { taskFeature } from "../src/features/tasks";
12
12
 
13
13
  const outPath = resolve(import.meta.dir, "..", "e2e", ".e2e-data.json");
@@ -3,7 +3,7 @@
3
3
  // `e2e/_helpers/login.ts` gelesen.
4
4
  //
5
5
  // Warum getrennt: e2e-Specs laufen im Playwright-Worker, der nichts aus
6
- // `@cosmicdrift/kumiko-framework/testing` (zieht `vitest`) oder
6
+ // `@cosmicdrift/kumiko-testing/helpers` (zieht `vitest`) oder
7
7
  // `@cosmicdrift/kumiko-bundled-features/.../testing` (zieht das ebenfalls) ertragen
8
8
  // kann — Vitest's expect redefined Object.prototype-Symbole und kollidiert
9
9
  // mit Playwrights expect. Diese Datei bleibt importchain-leer und ist die
@@ -3,7 +3,7 @@
3
3
 
4
4
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
5
5
  import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
6
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
6
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
7
7
  import { countRowsForTenant } from "../db/queries/row-counts";
8
8
  import { leaseExecutor, partyExecutor, positionExecutor } from "../features/rental/lease-support";
9
9
 
@@ -214,7 +214,7 @@ function generatedLease(index: number): BoardLease & { readonly terminated: bool
214
214
  export const seedRental: SeedFn = async (stack) => {
215
215
  const { tenantId } = TestUsers.admin;
216
216
  if ((await countRowsForTenant(stack.db, "read_ui_walkthrough_leases", tenantId)) > 0) return;
217
- const db = createTenantDb(stack.db, tenantId);
217
+ const db = createTenantDb({ db: stack.db, tenantId });
218
218
 
219
219
  const createLease = async (lease: BoardLease, terminated: boolean, id?: string) => {
220
220
  const result = await leaseExecutor.create(
@@ -32,6 +32,7 @@ import {
32
32
  SYSTEM_INVOICE_ISSUED,
33
33
  SYSTEM_PDF_LAYOUT,
34
34
  SYSTEM_TENANCY_CERTIFICATE,
35
+ SYSTEM_TERMS_CHANGED,
35
36
  TENANT_INVOICE_OVERRIDES,
36
37
  TENANT_MAIL_LAYOUT_VERSIONS,
37
38
  TENANT_UTILITY_STATEMENT,
@@ -165,6 +166,7 @@ export const seedTemplates: SeedFn = async (stack) => {
165
166
  await upsertSystem(SYSTEM_PDF_LAYOUT);
166
167
  for (const mail of SYSTEM_AUTH_MAILS) await upsertSystem(mail);
167
168
  await upsertSystem(SYSTEM_INVOICE_ISSUED);
169
+ await upsertSystem(SYSTEM_TERMS_CHANGED);
168
170
  for (const document of SYSTEM_INVOICE_DOCUMENTS) await upsertSystem(document);
169
171
  const certificate = await upsertSystem(SYSTEM_TENANCY_CERTIFICATE);
170
172
  await stack.http.writeOk(
@@ -1,5 +1,5 @@
1
1
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
2
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
2
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
3
3
  import { countRowsForTenant } from "../db/queries/row-counts";
4
4
 
5
5
  const OCTAVIA_DESCRIPTION = [
@@ -5,7 +5,7 @@
5
5
  // tenant already has tasks (persistent KUMIKO_DEV_DB_NAME survives reboots).
6
6
 
7
7
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
8
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
8
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
9
9
  import { countTasksForTenant } from "../db/queries/task-counts";
10
10
 
11
11
  const DEMO_TASKS = [
@@ -276,6 +276,18 @@ export const INVOICE_CORRECTED_DRAFT: SeedTemplate = {
276
276
  meta: invoiceIssuedMeta("Ihre Rechnung {{invoiceNumber}} von {{tenantName}}"),
277
277
  };
278
278
 
279
+ export const SYSTEM_TERMS_CHANGED: SeedTemplate = {
280
+ slug: "billing:notify:terms-changed",
281
+ kind: "mail",
282
+ locale: "de",
283
+ title: "AGB-Änderung",
284
+ content: [
285
+ `<p>Guten Tag ${v("customerName")},</p>`,
286
+ `<p>zum ${v("effectiveDate")} ändern sich die Allgemeinen Geschäftsbedingungen des Mieterportals.</p>`,
287
+ ].join(""),
288
+ meta: { subject: "Änderung der Geschäftsbedingungen" },
289
+ };
290
+
279
291
  export const PAYMENT_REMINDER_TEMPLATES: readonly SeedTemplate[] = [
280
292
  {
281
293
  slug: "billing:notify:payment-reminder",
@@ -1,5 +1,5 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
2
+ import { asRawClient } from "@cosmicdrift/kumiko-framework/db";
3
3
 
4
4
  type CountedTable = "read_ui_walkthrough_leases" | "read_ui_walkthrough_vehicles";
5
5
 
@@ -1,5 +1,5 @@
1
- import { asRawClient } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
2
+ import { asRawClient } from "@cosmicdrift/kumiko-framework/db";
3
3
 
4
4
  export async function countTasksForTenant(db: DbRunner, tenantId: string): Promise<number> {
5
5
  const rows = await asRawClient(db).unsafe<{ count: number }>(
@@ -63,10 +63,17 @@ const PAYMENT_REMINDER_VARIABLES = {
63
63
  invoiceUrl: templateVariable.link({ required: true }),
64
64
  } as const;
65
65
 
66
+ const TERMS_CHANGED_VARIABLES = {
67
+ customerName: templateVariable.text({ required: true, example: "Familie Yilmaz" }),
68
+ effectiveDate: templateVariable.date({ required: true, example: "2026-12-01" }),
69
+ } as const;
70
+
66
71
  export const billingFeature = defineFeature("billing", (r) => {
67
72
  r.translations({ keys: toKeyFirst(billingTranslations) });
68
73
 
69
74
  r.notification("invoice-issued", { variables: INVOICE_ISSUED_VARIABLES });
70
75
  r.notification("invoice-corrected", { variables: INVOICE_ISSUED_VARIABLES });
71
76
  r.notification("payment-reminder", { variables: PAYMENT_REMINDER_VARIABLES });
77
+ // Legal wording the platform owns: tenant admins neither see nor override it.
78
+ r.notification("terms-changed", { variables: TERMS_CHANGED_VARIABLES, systemOnly: true });
72
79
  });
@@ -8,11 +8,13 @@ export const billingTranslations: TranslationsByLocale = {
8
8
  "billing:notify.invoice-issued.label": "Rechnung gestellt",
9
9
  "billing:notify.invoice-corrected.label": "Rechnung korrigiert",
10
10
  "billing:notify.payment-reminder.label": "Mahnlauf",
11
+ "billing:notify.terms-changed.label": "AGB-Änderung",
11
12
  },
12
13
  en: {
13
14
  "billing:feature.label": "Invoices",
14
15
  "billing:notify.invoice-issued.label": "Invoice issued",
15
16
  "billing:notify.invoice-corrected.label": "Invoice corrected",
16
17
  "billing:notify.payment-reminder.label": "Dunning run",
18
+ "billing:notify.terms-changed.label": "Terms update",
17
19
  },
18
20
  };
@@ -407,7 +407,7 @@
407
407
  },
408
408
  {
409
409
  "name": "channel-email",
410
- "description": "Wires an `EmailTransport` (typically `mail-transport-smtp` in production, `createInMemoryTransport()` in tests) into the delivery system as the `email` channel. Requires `delivery`; pass an `EmailChannelOptions` with a `transport` and a `resolveEmail` function that maps a user ID to their email address. Mails render from stored templates (`renderer-mail-html`): a notification routed to this channel needs `template` + `meta` on `r.notification`, otherwise its delivery fails.",
410
+ "description": "Wires an `EmailTransport` (typically `mail-transport-smtp` in production, `createInMemoryTransport()` in tests) into the delivery system as the `email` channel. Requires `delivery`; pass an `EmailChannelOptions` with a `transport` and a `resolveEmail` function that maps a user ID to their email address. Mails render from stored templates (`renderer-mail-html`): a notification routed to this channel needs `template` + `meta` on `r.notification`, otherwise its delivery fails. Pass `tenantTransport: tenantMailTransport` (from `mail-foundation`) to send each tenant's mail through its own configured provider: a broken provider fails the send, a tenant without one uses the app `transport`. Notifications declared with `unsubscribe: true` get a signed `data.unsubscribeUrl` from delivery, which turns into the `List-Unsubscribe` headers.",
411
411
  "toggleableDefault": null,
412
412
  "requires": [
413
413
  "delivery"
@@ -725,7 +725,7 @@
725
725
  },
726
726
  {
727
727
  "name": "delivery",
728
- "description": "The notification dispatch core: call `ctx.notify(notificationType, { to, route, data, priority, idempotencyKey })` from any handler to fan out a notification across all registered channels (email, in-app, push). Inside a write handler the delivery runs after the write has committed (the call returns `{ kind: \"deferred\" }`, a rolled-back write sends nothing); `immediate: true` delivers synchronously and returns `{ kind: \"dispatched\", deliveries }`. It stores per-user channel preferences in the `notification-preference` entity, opt-outs for no-account recipient addresses in `notification-address-opt-out` (keyed by a blind-index hash, never the plaintext address), logs every attempt to `store_delivery_attempts`, and enforces idempotency and rate-limiting — add `channel-email`, `channel-in-app`, or `channel-push` on top to actually send anything. Unsubscribe/resubscribe links are served by `createUnsubscribeRoutes({ secret })` mounted via the app's `extraRoutes` at `/api/delivery/unsubscribe` and `/api/delivery/resubscribe`: `GET /unsubscribe?token=` renders a confirmation page (no write), `POST /unsubscribe` performs the opt-out (RFC 8058 one-click, token from the form body or query), `POST /resubscribe` undoes it (JSON `{token}` or form body only, never the query — reachable by a mail-client link prefetcher) — sign links with `signUnsubscribeToken` / `signAddressUnsubscribeToken` using the same secret. `channel-email` sets `List-Unsubscribe` / `List-Unsubscribe-Post` automatically when a message's `data.unsubscribeUrl` points at the unsubscribe route.",
728
+ "description": "The notification dispatch core: call `ctx.notify(notificationType, { to, route, data, priority, idempotencyKey })` from any handler to fan out a notification across all registered channels (email, in-app, push). Inside a write handler the delivery runs after the write has committed (the call returns `{ kind: \"deferred\" }`, a rolled-back write sends nothing); `immediate: true` delivers synchronously and returns `{ kind: \"dispatched\", deliveries }`. It stores per-user channel preferences in the `notification-preference` entity, opt-outs for no-account recipient addresses in `notification-address-opt-out` (keyed by a blind-index hash, never the plaintext address), logs every attempt to `store_delivery_attempts`, and enforces idempotency and rate-limiting — add `channel-email`, `channel-in-app`, or `channel-push` on top to actually send anything. Unsubscribe/resubscribe links are served by `createUnsubscribeRoutes({ secret })` mounted via the app's `extraRoutes` at `/api/delivery/unsubscribe` and `/api/delivery/resubscribe`: `GET /unsubscribe?token=` renders a confirmation page (no write), `POST /unsubscribe` performs the opt-out (RFC 8058 one-click, token from the form body or query), `POST /resubscribe` undoes it (JSON `{token}` or form body only, never the query — reachable by a mail-client link prefetcher) — sign links with `signUnsubscribeToken` / `signAddressUnsubscribeToken` using the same secret. `channel-email` sets `List-Unsubscribe` / `List-Unsubscribe-Post` automatically when a message's `data.unsubscribeUrl` points at the unsubscribe route. A notification declared with `unsubscribe: true` gets that link from delivery itself when the service has `unsubscribeLinks` (`runProdApp` option `unsubscribe: { secret }` mounts the routes and wires it; base URL from `auth.publicOrigin`, `auth.mail.baseUrl` or `APP_BASE_URL`): user recipients get a user token, `route` recipients an address token (needs a blind-index key, otherwise no link); a `data.unsubscribeUrl` from the caller wins. `unsubscribe.tenantOrigin: (ctx) => origin | null` points the link at the tenant's own host (subdomain or custom domain, must serve this app's `/api`); null, a throw or a non-https value fall back to the app origin. The token carries the mail's locale, so the confirmation and result pages render in the mail's language. To react to a no-account opt-out (e.g. remove the app's own subscriber row), declare `r.job(name, { trigger: { on: DeliveryHandlers.unsubscribeAddress } }, handler)` on a lane the app consumes: it runs after each committed opt-out, also an idempotent repeat, with `unsubscribeAddressPayloadSchema` (`addressHash`, `notificationType`, `channel`) as payload and the tenant in `ctx.triggeredBy.tenantId`; match the subscriber via `hashUnsubscribeAddress(email)`. Declare `unsubscribeUrl` as an optional template variable if the mail body shows it.",
729
729
  "toggleableDefault": null,
730
730
  "requires": [
731
731
  "tenant"
@@ -1507,7 +1507,7 @@
1507
1507
  },
1508
1508
  {
1509
1509
  "name": "mail-foundation",
1510
- "description": "Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending — use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences.",
1510
+ "description": "Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending — use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences. Pass `tenantMailTransport` as `tenantTransport` to `createChannelEmailFeature` so a tenant with a provider configured sends delivery mails through its own transport and other tenants through the app transport.",
1511
1511
  "toggleableDefault": null,
1512
1512
  "requires": [
1513
1513
  "config"
@@ -2122,7 +2122,7 @@
2122
2122
  },
2123
2123
  {
2124
2124
  "name": "renderer-mail-html",
2125
- "description": "A `renderer-foundation` plugin that handles `RenderRequest { kind: \"mail\" }` and returns `{ subject, html, text, previewText? }` suitable for sending via `channel-email`. The mail template (`kind: \"mail\"`, document HTML, subject in `meta`) resolves through `template-resolver`'s DB fallback, its body is compiled to Handlebars by template-resolver and rendered with escaping, then placed into an MJML layout (`kind: \"mail-layout\"`, slug `default` unless `meta.layoutSlug` says otherwise, an in-code structured layout with the tenant branding logo and accent color as last resort) that `mjml()` compiles to email-safe table HTML, with `html-to-text` producing the plain-text alternative. An optional `footer` resolver adds the platform imprint, privacy link and footer text below every structured layout, and an optional `brandSuffix` resolver adds a word after the tenant name in the brand row of the in-code layout. Mail meta `headerChip`, `tone` and `footerNote` add a chip beside the brand, the tone of the top line and chip, and a note above the site and unsubscribe links of the card. Seed an editable system layout with `seedSystemMailLayout(db)`. Requires `renderer-foundation` + `template-resolver`.",
2125
+ "description": "A `renderer-foundation` plugin that handles `RenderRequest { kind: \"mail\" }` and returns `{ subject, html, text, previewText? }` suitable for sending via `channel-email`. The mail template (`kind: \"mail\"`, document HTML, subject in `meta`) resolves through `template-resolver`'s DB fallback, its body is compiled to Handlebars by template-resolver and rendered with escaping, then placed into an MJML layout (`kind: \"mail-layout\"`, slug `default` unless `meta.layoutSlug` says otherwise, an in-code structured layout with the tenant branding logo and accent color as last resort) that `mjml()` compiles to email-safe table HTML, with `html-to-text` producing the plain-text alternative. An optional `footer` resolver adds the platform imprint, privacy link and footer text below every structured layout, an optional `brandSuffix` resolver adds a word after the tenant name in the brand row of the in-code layout, and an optional `siteUrl` resolver supplies the site link of the card when the tenant branding has no site URL (without either, the link is left out). The brand row and `data-resource=\"logo\"` images use the branding logo upload, or the branding logo https address when no file is uploaded. Mail meta `headerChip`, `tone` and `footerNote` add a chip beside the brand, the tone of the top line and chip, and a note above the site and unsubscribe links of the card. Seed an editable system layout with `seedSystemMailLayout(db)`. Requires `renderer-foundation` + `template-resolver`.",
2126
2126
  "toggleableDefault": null,
2127
2127
  "requires": [
2128
2128
  "renderer-foundation",
@@ -21,6 +21,7 @@
21
21
  "@cosmicdrift/kumiko-document-designer": "workspace:*",
22
22
  "@cosmicdrift/kumiko-framework": "workspace:*",
23
23
  "@cosmicdrift/kumiko-headless": "workspace:*",
24
+ "@cosmicdrift/kumiko-renderer-mail-html": "workspace:*",
24
25
  "@cosmicdrift/kumiko-renderer-puppeteer-client": "workspace:*",
25
26
  "@cosmicdrift/kumiko-renderer-web": "workspace:*",
26
27
  "@cosmicdrift/kumiko-server-runtime": "workspace:*",
@@ -30,5 +31,8 @@
30
31
  "zod": "^4.4.3",
31
32
  "@cosmicdrift/kumiko-locale-de": "workspace:*",
32
33
  "@cosmicdrift/kumiko-locale-es": "workspace:*"
34
+ },
35
+ "devDependencies": {
36
+ "@cosmicdrift/kumiko-testing": "workspace:*"
33
37
  }
34
38
  }
@@ -23,10 +23,10 @@ const FRAMEWORK_ROOT = resolve(ROOT, "..", "..", "..");
23
23
  // Held-back exports: existieren in bundled-features, sind aber nicht
24
24
  // als runtime-feature in use-all-bundled mountbar.
25
25
  //
26
- // Nur Utilities ohne defineFeature (foundation-shared, files-provider-s3 sind pure helpers)
26
+ // Nur Utilities ohne defineFeature (foundation-shared sowie files-provider-s3, der deprecated Alias von file-provider-s3/lib, sind pure helpers)
27
27
  // und scaffold-only Features. Gemountete Features gehören nicht hierher.
28
28
  const EXPECTED_HELD_BACK = new Set([
29
- "files-provider-s3", // utility (createS3Provider helpers), kein defineFeature
29
+ "files-provider-s3", // deprecated alias of file-provider-s3/lib (createS3Provider helpers), kein defineFeature
30
30
  "foundation-shared", // utilities (requireDefined/requireNonEmpty), kein feature
31
31
  "page-render", // shared HTML render/cache helpers (legal/managed-pages), kein defineFeature
32
32
  "presets", // feature-bundle helpers (dsgvoSelfServiceFeatures, securityBaselineFeatures), kein defineFeature
@@ -1,6 +1,6 @@
1
1
  // Reine Konstanten — kein Framework-Import, damit der E2E-Login-Helper
2
2
  // (Playwright-Worker) sie lesen kann, ohne die vitest-Importchain aus
3
- // `@cosmicdrift/kumiko-framework/testing` mitzuziehen (kollidiert mit
3
+ // `@cosmicdrift/kumiko-testing/helpers` mitzuziehen (kollidiert mit
4
4
  // Playwrights expect über Object.prototype-Symbole).
5
5
 
6
6
  export const ADMIN_EMAIL = "admin@kumiko.dev";
@@ -2,8 +2,8 @@ import type { CapSpec } from "@cosmicdrift/kumiko-bundled-features/cap-overview"
2
2
  import { noteEntryTable } from "@cosmicdrift/kumiko-bundled-features/notes-history";
3
3
  import { tagEntity } from "@cosmicdrift/kumiko-bundled-features/tags";
4
4
  import { tenantMembershipsTable } from "@cosmicdrift/kumiko-bundled-features/tenant";
5
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
6
- import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
5
+
6
+ import { buildEntityTable, selectMany } from "@cosmicdrift/kumiko-framework/db";
7
7
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
8
8
 
9
9
  const tagTable = buildEntityTable("tag", tagEntity);
@@ -19,7 +19,7 @@ import { notesFeature } from "./notes-feature";
19
19
  import { appScreensFeature } from "./screens-feature";
20
20
  import { seedScreenshotData } from "./seed";
21
21
 
22
- // tier-admin rendert mit dem bare tierEngineFeature (aus APP_FEATURES) den
22
+ // tier-admin rendert mit dem bare createTierEngineFeature() (aus APP_FEATURES) den
23
23
  // ehrlichen Empty-State ("no TierMap configured"). Eine konfigurierte tierMap
24
24
  // würde den Resolver auf jedem Write aktivieren (inkl. Login) und braucht
25
25
  // per-Tenant Tier-Assignments — disproportional für einen Preview-Screenshot.
@@ -9,7 +9,7 @@ import { TemplateResolverHandlers } from "@cosmicdrift/kumiko-bundled-features/t
9
9
  import { seedSystemTemplate } from "@cosmicdrift/kumiko-bundled-features/template-resolver/seeding";
10
10
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
11
11
  import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
12
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
12
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
13
13
  import { BETA_TENANT_ID, DEV_TENANT_ID, INVOICE_TEMPLATE_SLUG } from "./auth-constants";
14
14
 
15
15
  type Stack = Parameters<SeedFn>[0];
@@ -24,16 +24,22 @@ import {
24
24
  } from "@cosmicdrift/kumiko-bundled-features/tier-engine";
25
25
  import { userTable } from "@cosmicdrift/kumiko-bundled-features/user";
26
26
  import type { SeedFn } from "@cosmicdrift/kumiko-dev-server";
27
- import { fetchOne, insertOne } from "@cosmicdrift/kumiko-framework/bun-db";
28
- import { createTenantDb, type DbConnection } from "@cosmicdrift/kumiko-framework/db";
27
+
28
+ import {
29
+ createTenantDb,
30
+ type DbConnection,
31
+ fetchOne,
32
+ insertOne,
33
+ } from "@cosmicdrift/kumiko-framework/db";
29
34
  import {
30
35
  createEntityExecutor,
31
36
  type SessionUser,
32
37
  SYSTEM_TENANT_ID,
33
38
  type TenantId,
34
39
  } from "@cosmicdrift/kumiko-framework/engine";
35
- import { TestUsers, unsafeCreateEntityTable } from "@cosmicdrift/kumiko-framework/stack";
40
+ import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
36
41
  import { generateId } from "@cosmicdrift/kumiko-framework/utils";
42
+ import { unsafeCreateEntityTable } from "@cosmicdrift/kumiko-testing/stack";
37
43
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
38
44
  import { ADMIN_EMAIL, BETA_TENANT_ID, DEMO_NOTE_ID, DEV_TENANT_ID } from "./auth-constants";
39
45
  import { noteEntity } from "./notes-feature";
@@ -80,7 +86,7 @@ async function seedTierAssignment(
80
86
  adminUserId: string,
81
87
  ): Promise<void> {
82
88
  const by: SessionUser = { ...TestUsers.systemAdmin, tenantId, id: adminUserId };
83
- const tdb = createTenantDb(db, tenantId, "system");
89
+ const tdb = createTenantDb({ db, tenantId, mode: "system" });
84
90
  const result = await tierAssignmentExecutor.create(
85
91
  { id: tierAssignmentAggregateId(tenantId), tier, source: "manual", tenantId },
86
92
  by,
@@ -104,7 +110,7 @@ async function seedTagsAndNotes(
104
110
  adminUserId: string,
105
111
  ): Promise<void> {
106
112
  const by: SessionUser = { ...TestUsers.systemAdmin, tenantId, id: adminUserId };
107
- const tdb = createTenantDb(db, tenantId, "system");
113
+ const tdb = createTenantDb({ db, tenantId, mode: "system" });
108
114
 
109
115
  const created = async (
110
116
  label: string,