@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
@@ -1,9 +1,9 @@
1
- import { requireEntityTableMeta } from "@cosmicdrift/kumiko-framework/bun-db";
2
1
  import {
3
2
  type EntityTableMeta,
4
3
  index,
5
4
  instant,
6
5
  table as pgTable,
6
+ requireEntityTableMeta,
7
7
  serial,
8
8
  sql,
9
9
  text,
@@ -151,7 +151,7 @@ function registerLedger(
151
151
  r.queryHandler(createBalanceSheetHandler(access));
152
152
  }
153
153
 
154
- export const ledgerFeature = defineFeature(LEDGER_FEATURE_NAME, (r) =>
154
+ const defaultLedgerFeature = defineFeature(LEDGER_FEATURE_NAME, (r) =>
155
155
  registerLedger(r, DEFAULT_LEDGER_ACCESS, undefined),
156
156
  );
157
157
 
@@ -174,10 +174,13 @@ function resolveAccess(opts: LedgerFeatureOptions): AccessRule {
174
174
 
175
175
  // Options wrapper. Without options returns the module-level singleton (no
176
176
  // rebuild). access/roles/toggleable build a fresh feature-definition.
177
- export function createLedgerFeature(opts: LedgerFeatureOptions = {}): typeof ledgerFeature {
177
+ export function createLedgerFeature(opts: LedgerFeatureOptions = {}): typeof defaultLedgerFeature {
178
178
  if (opts.access === undefined && opts.roles === undefined && opts.toggleable === undefined) {
179
- return ledgerFeature;
179
+ return defaultLedgerFeature;
180
180
  }
181
181
  const access = resolveAccess(opts);
182
182
  return defineFeature(LEDGER_FEATURE_NAME, (r) => registerLedger(r, access, opts.toggleable));
183
183
  }
184
+
185
+ /** @deprecated Use createLedgerFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
186
+ export const ledgerFeature = createLedgerFeature();
@@ -39,9 +39,11 @@ import { requireDefined } from "@cosmicdrift/kumiko-bundled-features/foundation-
39
39
  import {
40
40
  access,
41
41
  type ConfigAccessor,
42
+ createSystemUser,
42
43
  createTenantConfig,
43
44
  defineFeature,
44
45
  type Registry,
46
+ type TenantId,
45
47
  } from "@cosmicdrift/kumiko-framework/engine";
46
48
 
47
49
  const FEATURE_NAME = "mail-foundation";
@@ -118,56 +120,67 @@ declare module "@cosmicdrift/kumiko-framework/engine" {
118
120
  // =============================================================================
119
121
  // Feature-definition
120
122
  // =============================================================================
123
+ export function createMailFoundationFeature() {
124
+ return defineFeature(
125
+ FEATURE_NAME,
126
+ (r) => {
127
+ r.describe(
128
+ "Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending \u2014 use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences. Pass `tenantMailTransport` as `tenantTransport` to `createChannelEmailFeature` so a tenant with a provider configured sends delivery mails through its own transport and other tenants through the app transport.",
129
+ );
130
+ r.uiHints({
131
+ displayLabel: "Mail Transport Foundation",
132
+ category: "notifications",
133
+ recommended: false,
134
+ });
135
+ r.requires({ features: ["config"] });
121
136
 
122
- export const mailFoundationFeature = defineFeature(FEATURE_NAME, (r) => {
123
- r.describe(
124
- "Defines the `mailTransport` extension point and a per-tenant `provider` config key that selects which registered transport plugin to use at runtime. Call `createTransportForTenant(ctx, tenantId)` to get an `EmailTransport` ready for sending \u2014 use this feature together with at least one `mail-transport-*` feature; use `delivery` + `channel-email` instead when you need the full notification pipeline with delivery attempts and user preferences.",
125
- );
126
- r.uiHints({
127
- displayLabel: "Mail Transport Foundation",
128
- category: "notifications",
129
- recommended: false,
130
- });
131
- r.requires({ features: ["config"] });
132
-
133
- // Plugin extension-point. Provider-features register here. The
134
- // entityName at registration time becomes the value tenants pick in
135
- // `provider` config-key (e.g. "smtp", "brevo-api").
136
- r.extendsRegistrar(MAIL_TRANSPORT_EXTENSION, {
137
- onRegister: () => {
138
- // No side-effects at register-time — the registry stores the
139
- // usage, factory looks it up at request-time. Same shape as
140
- // delivery's extendsRegistrar.
137
+ // Plugin extension-point. Provider-features register here. The
138
+ // entityName at registration time becomes the value tenants pick in
139
+ // `provider` config-key (e.g. "smtp", "brevo-api").
140
+ r.extendsRegistrar(MAIL_TRANSPORT_EXTENSION, {
141
+ onRegister: () => {
142
+ // No side-effects at register-time — the registry stores the
143
+ // usage, factory looks it up at request-time. Same shape as
144
+ // delivery's extendsRegistrar.
145
+ },
146
+ });
147
+
148
+ // Provider-selector. Default empty so the boot-validator throws if a
149
+ // tenant tries to send mail without first picking + setting up a
150
+ // provider — better than a silent fallback. The actual list of valid
151
+ // values lives in the registered plugins, not here — Designer-UI can
152
+ // render `getExtensionUsages("mailTransport").map(u => u.entityName)`
153
+ // as the option-list.
154
+ const providerConfigKey = r.config(
155
+ "provider",
156
+ createTenantConfig("text", {
157
+ default: "",
158
+ // required: without a chosen provider createTransportForTenant throws —
159
+ // readiness used to report ready:true and the first mail send
160
+ // surfaced the UnconfiguredError (280/1).
161
+ required: true,
162
+ write: access.roles("TenantAdmin", "SystemAdmin"),
163
+ read: access.roles("TenantAdmin", "SystemAdmin", "User"),
164
+ }),
165
+ );
166
+ // Readiness gating: transport-plugins' required keys/secrets count only
167
+ // while their plugin is the one this key selects.
168
+ r.extensionSelector(MAIL_TRANSPORT_EXTENSION, providerConfigKey);
169
+
170
+ return {
171
+ /** Config-key-handle for the provider-selector. */
172
+ providerConfigKey,
173
+ };
141
174
  },
142
- });
143
-
144
- // Provider-selector. Default empty so the boot-validator throws if a
145
- // tenant tries to send mail without first picking + setting up a
146
- // provider — better than a silent fallback. The actual list of valid
147
- // values lives in the registered plugins, not here — Designer-UI can
148
- // render `getExtensionUsages("mailTransport").map(u => u.entityName)`
149
- // as the option-list.
150
- const providerConfigKey = r.config(
151
- "provider",
152
- createTenantConfig("text", {
153
- default: "",
154
- // required: ohne gewählten Provider wirft createTransportForTenant —
155
- // readiness meldete vorher ready:true und der erste Mail-Send
156
- // lieferte den UnconfiguredError (280/1).
157
- required: true,
158
- write: access.roles("TenantAdmin", "SystemAdmin"),
159
- read: access.roles("TenantAdmin", "SystemAdmin", "User"),
160
- }),
175
+ { dedupeOptions: {} },
161
176
  );
162
- // Readiness gating: transport-plugins' required keys/secrets count only
163
- // while their plugin is the one this key selects.
164
- r.extensionSelector(MAIL_TRANSPORT_EXTENSION, providerConfigKey);
177
+ }
165
178
 
166
- return {
167
- /** Config-key-handle for the provider-selector. */
168
- providerConfigKey,
169
- };
170
- });
179
+ // The typed handles below come from one shared instance; each factory call builds its own handle objects.
180
+ const sharedMailFoundationFeature = createMailFoundationFeature();
181
+
182
+ /** @deprecated Use createMailFoundationFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
183
+ export const mailFoundationFeature = sharedMailFoundationFeature;
171
184
 
172
185
  // =============================================================================
173
186
  // Transport-factory — looks up the registered plugin + delegates
@@ -187,6 +200,28 @@ export async function createTransportForTenant(
187
200
  tenantId: string,
188
201
  handlerName = "mail-foundation:transport-factory",
189
202
  ): Promise<EmailTransport> {
203
+ const transport = await createTransportForTenantIfConfigured(ctx, tenantId, handlerName);
204
+ if (transport === null) {
205
+ const usages = ctx.registry?.getExtensionUsages(MAIL_TRANSPORT_EXTENSION) ?? [];
206
+ const known = usages.map((u) => u.entityName).join(", ") || "<none>";
207
+ throw new Error(
208
+ `${FEATURE_NAME}: no provider selected — set the 'provider' config-key to one of: ${known}. ` +
209
+ `Mount a mail-transport-* feature first if no plugins are registered.`,
210
+ );
211
+ }
212
+ return transport;
213
+ }
214
+
215
+ /**
216
+ * Like createTransportForTenant, but an empty `provider` key means "this tenant has no
217
+ * mail provider" and yields null. Every other problem (unknown provider, plugin build
218
+ * failure) still throws, so a configured tenant never silently falls back.
219
+ */
220
+ export async function createTransportForTenantIfConfigured(
221
+ ctx: MailTransportContext,
222
+ tenantId: string,
223
+ handlerName = "mail-foundation:transport-factory",
224
+ ): Promise<EmailTransport | null> {
190
225
  const ctxConfig = ctx.config;
191
226
  if (!ctxConfig) {
192
227
  throw new Error(
@@ -200,18 +235,11 @@ export async function createTransportForTenant(
200
235
  }
201
236
 
202
237
  const provider = requireDefined(
203
- await ctxConfig(mailFoundationFeature.exports.providerConfigKey),
238
+ await ctxConfig(sharedMailFoundationFeature.exports.providerConfigKey),
204
239
  FEATURE_NAME,
205
240
  "provider",
206
241
  ) as string; // @cast-boundary engine-payload
207
- if (provider.length === 0) {
208
- const usages = ctx.registry.getExtensionUsages(MAIL_TRANSPORT_EXTENSION);
209
- const known = usages.map((u) => u.entityName).join(", ") || "<none>";
210
- throw new Error(
211
- `${FEATURE_NAME}: no provider selected — set the 'provider' config-key to one of: ${known}. ` +
212
- `Mount a mail-transport-* feature first if no plugins are registered.`,
213
- );
214
- }
242
+ if (provider.length === 0) return null;
215
243
 
216
244
  const usages = ctx.registry.getExtensionUsages(MAIL_TRANSPORT_EXTENSION);
217
245
  const usage = usages.find((u) => u.entityName === provider);
@@ -231,3 +259,27 @@ export async function createTransportForTenant(
231
259
  }
232
260
  return withPiiCiphertextGuard(await usage.options.build(ctx, tenantId));
233
261
  }
262
+
263
+ export type TenantMailTransportScope = {
264
+ readonly tenantId: TenantId;
265
+ readonly config?: ConfigAccessor | undefined;
266
+ readonly registry: Registry;
267
+ readonly secrets?: import("@cosmicdrift/kumiko-framework/secrets").SecretsContext | undefined;
268
+ };
269
+
270
+ /** The `tenantTransport` resolver for `createChannelEmailFeature`: the tenant's configured
271
+ * provider, or null so the channel falls back to its app transport. */
272
+ export function tenantMailTransport(
273
+ scope: TenantMailTransportScope,
274
+ ): Promise<EmailTransport | null> {
275
+ return createTransportForTenantIfConfigured(
276
+ {
277
+ config: scope.config,
278
+ registry: scope.registry,
279
+ secrets: scope.secrets,
280
+ _userId: createSystemUser(scope.tenantId).id,
281
+ },
282
+ scope.tenantId,
283
+ "channel-email",
284
+ );
285
+ }
@@ -8,10 +8,14 @@
8
8
  // when registering via `r.useExtension("mailTransport", ...)`
9
9
 
10
10
  export {
11
+ createMailFoundationFeature,
11
12
  createTransportForTenant,
13
+ createTransportForTenantIfConfigured,
12
14
  isMailTransportPlugin,
13
15
  MAIL_TRANSPORT_EXTENSION,
14
16
  type MailTransportContext,
15
17
  type MailTransportPlugin,
16
18
  mailFoundationFeature,
19
+ type TenantMailTransportScope,
20
+ tenantMailTransport,
17
21
  } from "./feature.js";
@@ -75,23 +75,31 @@ export function clearInbox(tenantId: string): void {
75
75
  // =============================================================================
76
76
  // Feature-definition
77
77
  // =============================================================================
78
+ export function createMailTransportInMemoryFeature() {
79
+ return defineFeature(
80
+ FEATURE_NAME,
81
+ (r) => {
82
+ r.describe(
83
+ 'Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).',
84
+ );
85
+ // Kein requires auf "config" oder "secrets" — der
86
+ // In-Memory-Transport hat keine Config (nichts zu konfigurieren) und
87
+ // kein Secret. Der einzige hard-require ist mail-foundation, das den
88
+ // extension-point "mailTransport" definiert.
89
+ r.requires({ features: ["mail-foundation"] });
78
90
 
79
- export const mailTransportInMemoryFeature = defineFeature(FEATURE_NAME, (r) => {
80
- r.describe(
81
- 'Registers an in-process `"inmemory"` provider for `mail-foundation` that buffers sent mails per tenant instead of contacting an SMTP server. Use `getInbox(tenantId)` and `clearInbox(tenantId)` in demo apps and tests; not for production (buffer is process-memory, lost on restart).',
91
+ const plugin: MailTransportPlugin = {
92
+ build: async (_ctx: MailTransportContext, tenantId: string): Promise<EmailTransport> => {
93
+ // Returns the per-tenant buffer. Identity-stable across calls so the
94
+ // demo inbox keeps accumulating.
95
+ return getOrCreateTransportForTenant(tenantId);
96
+ }, // @wrapper-known semantic-alias
97
+ };
98
+ r.useExtension(MAIL_TRANSPORT_EXTENSION, "inmemory", plugin);
99
+ },
100
+ { dedupeOptions: {} },
82
101
  );
83
- // Kein requires auf "config" oder "secrets" — der
84
- // In-Memory-Transport hat keine Config (nichts zu konfigurieren) und
85
- // kein Secret. Der einzige hard-require ist mail-foundation, das den
86
- // extension-point "mailTransport" definiert.
87
- r.requires({ features: ["mail-foundation"] });
102
+ }
88
103
 
89
- const plugin: MailTransportPlugin = {
90
- build: async (_ctx: MailTransportContext, tenantId: string): Promise<EmailTransport> => {
91
- // Returnt den per-tenant Buffer. Identitätsstabil zwischen calls
92
- // damit die Demo-Inbox accumulated bleibt.
93
- return getOrCreateTransportForTenant(tenantId);
94
- }, // @wrapper-known semantic-alias
95
- };
96
- r.useExtension(MAIL_TRANSPORT_EXTENSION, "inmemory", plugin);
97
- });
104
+ /** @deprecated Use createMailTransportInMemoryFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
105
+ export const mailTransportInMemoryFeature = createMailTransportInMemoryFeature();
@@ -1,3 +1,8 @@
1
1
  // Public API of the mail-transport-inmemory bundled-feature.
2
2
 
3
- export { clearInbox, getInbox, mailTransportInMemoryFeature } from "./feature.js";
3
+ export {
4
+ clearInbox,
5
+ createMailTransportInMemoryFeature,
6
+ getInbox,
7
+ mailTransportInMemoryFeature,
8
+ } from "./feature.js";
@@ -75,89 +75,101 @@ export function setSmtpMailHostLookup(fn: typeof lookup | undefined): void {
75
75
  // =============================================================================
76
76
  // Feature-definition
77
77
  // =============================================================================
78
+ export function createMailTransportSmtpFeature() {
79
+ return defineFeature(
80
+ FEATURE_NAME,
81
+ (r) => {
82
+ r.describe(
83
+ 'Registers itself as the `"smtp"` provider for `mail-foundation` and owns the per-tenant config keys (`host`, `port`, `secure`, `from`, `authUser`) and the encrypted `smtp.password` secret. Tenants set `mail-foundation`\'s `provider` config key to `"smtp"` to activate it; set the SMTP credentials via the admin UI or a seed handler before sending the first mail.',
84
+ );
85
+ r.uiHints({
86
+ displayLabel: "Mail Transport · SMTP",
87
+ category: "notifications",
88
+ recommended: false,
89
+ });
90
+ r.requires({ features: ["config"] });
91
+ r.requires({ features: ["secrets"] });
92
+ r.requires({ features: ["mail-foundation"] });
93
+ r.envSchema(mailTransportSmtpEnvSchema);
78
94
 
79
- export const mailTransportSmtpFeature = defineFeature(FEATURE_NAME, (r) => {
80
- r.describe(
81
- 'Registers itself as the `"smtp"` provider for `mail-foundation` and owns the per-tenant config keys (`host`, `port`, `secure`, `from`, `authUser`) and the encrypted `smtp.password` secret. Tenants set `mail-foundation`\'s `provider` config key to `"smtp"` to activate it; set the SMTP credentials via the admin UI or a seed handler before sending the first mail.',
82
- );
83
- r.uiHints({
84
- displayLabel: "Mail Transport · SMTP",
85
- category: "notifications",
86
- recommended: false,
87
- });
88
- r.requires({ features: ["config"] });
89
- r.requires({ features: ["secrets"] });
90
- r.requires({ features: ["mail-foundation"] });
91
- r.envSchema(mailTransportSmtpEnvSchema);
95
+ // Provider-secret. Sensitive: redact-helper for admin-UI display.
96
+ const password = r.secret("smtp.password", {
97
+ label: { en: "SMTP password" },
98
+ hint: {
99
+ en: "Login password at the SMTP server. Brevo/Postmark/SES call it 'API key' or 'SMTP credentials'.",
100
+ },
101
+ redact: (plaintext) => {
102
+ if (plaintext.length < 8) return "•".repeat(plaintext.length);
103
+ return `${plaintext.slice(0, 3)}...${plaintext.slice(-2)}`;
104
+ },
105
+ scope: "tenant",
106
+ // required: true ↔ the missing-secret throw in readPassword — keep in sync.
107
+ required: true,
108
+ });
92
109
 
93
- // Provider-secret. Sensitive: redact-helper for admin-UI display.
94
- const password = r.secret("smtp.password", {
95
- label: { en: "SMTP password" },
96
- hint: {
97
- en: "Login password at the SMTP server. Brevo/Postmark/SES call it 'API key' or 'SMTP credentials'.",
98
- },
99
- redact: (plaintext) => {
100
- if (plaintext.length < 8) return "•".repeat(plaintext.length);
101
- return `${plaintext.slice(0, 3)}...${plaintext.slice(-2)}`;
102
- },
103
- scope: "tenant",
104
- // required: true ↔ the missing-secret throw in readPassword — keep in sync.
105
- required: true,
106
- });
110
+ // required: true ↔ the requireNonEmpty calls in buildSmtpTransport — keep in sync.
111
+ const configKeys = r.config({
112
+ keys: {
113
+ host: createTenantConfig("text", {
114
+ required: true,
115
+ default: "",
116
+ write: access.roles("TenantAdmin", "SystemAdmin"),
117
+ read: access.roles("TenantAdmin", "SystemAdmin"),
118
+ }),
119
+ port: createTenantConfig("number", {
120
+ default: 587,
121
+ bounds: { min: 1, max: 65535 },
122
+ write: access.roles("TenantAdmin", "SystemAdmin"),
123
+ }),
124
+ secure: createTenantConfig("boolean", {
125
+ default: false,
126
+ write: access.roles("TenantAdmin", "SystemAdmin"),
127
+ }),
128
+ from: createTenantConfig("text", {
129
+ required: true,
130
+ default: "",
131
+ write: access.roles("TenantAdmin", "SystemAdmin"),
132
+ read: access.roles("TenantAdmin", "SystemAdmin"),
133
+ }),
134
+ authUser: createTenantConfig("text", {
135
+ required: true,
136
+ default: "",
137
+ write: access.roles("TenantAdmin", "SystemAdmin"),
138
+ read: access.roles("TenantAdmin", "SystemAdmin"),
139
+ }),
140
+ },
141
+ });
107
142
 
108
- // required: true ↔ the requireNonEmpty calls in buildSmtpTransport — keep in sync.
109
- const configKeys = r.config({
110
- keys: {
111
- host: createTenantConfig("text", {
112
- required: true,
113
- default: "",
114
- write: access.roles("TenantAdmin", "SystemAdmin"),
115
- read: access.roles("TenantAdmin", "SystemAdmin"),
116
- }),
117
- port: createTenantConfig("number", {
118
- default: 587,
119
- bounds: { min: 1, max: 65535 },
120
- write: access.roles("TenantAdmin", "SystemAdmin"),
121
- }),
122
- secure: createTenantConfig("boolean", {
123
- default: false,
124
- write: access.roles("TenantAdmin", "SystemAdmin"),
125
- }),
126
- from: createTenantConfig("text", {
127
- required: true,
128
- default: "",
129
- write: access.roles("TenantAdmin", "SystemAdmin"),
130
- read: access.roles("TenantAdmin", "SystemAdmin"),
131
- }),
132
- authUser: createTenantConfig("text", {
133
- required: true,
134
- default: "",
135
- write: access.roles("TenantAdmin", "SystemAdmin"),
136
- read: access.roles("TenantAdmin", "SystemAdmin"),
137
- }),
143
+ // Plugin: register against mail-foundation's "mailTransport" extension.
144
+ // `entityName` "smtp" is what tenants set in mail-foundation's
145
+ // `provider` config-key to pick this transport.
146
+ const plugin: MailTransportPlugin = {
147
+ build: async (ctx: MailTransportContext, tenantId: string) =>
148
+ buildSmtpTransport(ctx, tenantId), // @wrapper-known semantic-alias
149
+ };
150
+ r.useExtension(MAIL_TRANSPORT_EXTENSION, "smtp", plugin);
151
+
152
+ return {
153
+ /** Config-key-handles — typed reads via `ctx.config(...)` in
154
+ * consumer handlers. */
155
+ configKeys,
156
+ /** Secret-handle for the SMTP password. */
157
+ password,
158
+ };
138
159
  },
139
- });
160
+ { dedupeOptions: {} },
161
+ );
162
+ }
140
163
 
141
- // Plugin: register against mail-foundation's "mailTransport" extension.
142
- // `entityName` "smtp" is what tenants set in mail-foundation's
143
- // `provider` config-key to pick this transport.
144
- const plugin: MailTransportPlugin = {
145
- build: async (ctx: MailTransportContext, tenantId: string) => buildSmtpTransport(ctx, tenantId), // @wrapper-known semantic-alias
146
- };
147
- r.useExtension(MAIL_TRANSPORT_EXTENSION, "smtp", plugin);
164
+ // The typed handles below come from one shared instance; each factory call builds its own handle objects.
165
+ const sharedMailTransportSmtpFeature = createMailTransportSmtpFeature();
148
166
 
149
- return {
150
- /** Config-key-handles — typed reads via `ctx.config(...)` in
151
- * consumer handlers. */
152
- configKeys,
153
- /** Secret-handle for the SMTP password. */
154
- password,
155
- };
156
- });
167
+ /** @deprecated Use createMailTransportSmtpFeature(). Run `bun kumiko-upgrade --apply`. Removed in the first release after 2026-10-29. */
168
+ export const mailTransportSmtpFeature = sharedMailTransportSmtpFeature;
157
169
 
158
170
  /** Typed handle for the SMTP password — exported so seeds + tests can
159
171
  * set it via `secrets:write:set` with the full qualified-name. */
160
- export const SMTP_PASSWORD = mailTransportSmtpFeature.exports.password;
172
+ export const SMTP_PASSWORD = sharedMailTransportSmtpFeature.exports.password;
161
173
 
162
174
  // =============================================================================
163
175
  // Internal: build the EmailTransport from tenant config + secret
@@ -188,29 +200,29 @@ async function buildSmtpTransport(
188
200
 
189
201
  const SMTP_HINT = "Set via tenant-admin UI or seed-handler before sending mail.";
190
202
  const host = requireNonEmpty(
191
- await ctxConfig(mailTransportSmtpFeature.exports.configKeys.host),
203
+ await ctxConfig(sharedMailTransportSmtpFeature.exports.configKeys.host),
192
204
  FEATURE_NAME,
193
205
  "host",
194
206
  SMTP_HINT,
195
207
  );
196
208
  const port = requireDefined(
197
- await ctxConfig(mailTransportSmtpFeature.exports.configKeys.port),
209
+ await ctxConfig(sharedMailTransportSmtpFeature.exports.configKeys.port),
198
210
  FEATURE_NAME,
199
211
  "port",
200
212
  ) as number; // @cast-boundary engine-payload
201
213
  const secure = requireDefined(
202
- await ctxConfig(mailTransportSmtpFeature.exports.configKeys.secure),
214
+ await ctxConfig(sharedMailTransportSmtpFeature.exports.configKeys.secure),
203
215
  FEATURE_NAME,
204
216
  "secure",
205
217
  ) as boolean; // @cast-boundary engine-payload
206
218
  const from = requireNonEmpty(
207
- await ctxConfig(mailTransportSmtpFeature.exports.configKeys.from),
219
+ await ctxConfig(sharedMailTransportSmtpFeature.exports.configKeys.from),
208
220
  FEATURE_NAME,
209
221
  "from",
210
222
  SMTP_HINT,
211
223
  );
212
224
  const authUser = requireNonEmpty(
213
- await ctxConfig(mailTransportSmtpFeature.exports.configKeys.authUser),
225
+ await ctxConfig(sharedMailTransportSmtpFeature.exports.configKeys.authUser),
214
226
  FEATURE_NAME,
215
227
  "authUser",
216
228
  SMTP_HINT,
@@ -1,6 +1,7 @@
1
1
  // Public API of the mail-transport-smtp bundled-feature.
2
2
 
3
3
  export {
4
+ createMailTransportSmtpFeature,
4
5
  mailTransportSmtpEnvSchema,
5
6
  mailTransportSmtpFeature,
6
7
  SMTP_PASSWORD,
@@ -1,4 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
4
  import { type PageRow, pagesTable } from "../table.js";
@@ -1,5 +1,4 @@
1
- import { selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { castTenantRows } from "@cosmicdrift/kumiko-framework/db";
1
+ import { castTenantRows, selectMany } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import * as z from "zod";
5
4
  import { type PageRow, pagesTable } from "../table.js";
@@ -1,5 +1,4 @@
1
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
- import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
1
+ import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
3
2
  import { defineWriteHandler, type TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
3
  import * as z from "zod";
5
4
  import { requireForTenant } from "../../shared/index.js";
@@ -2,15 +2,19 @@
2
2
  // Event-Store-Executor an — gleicher Pfad wie der echte set-Handler, aber
3
3
  // ohne Access-Check. Default ifExists="skip".
4
4
 
5
- import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
6
5
  import {
7
6
  createEventStoreExecutor,
8
7
  createTenantDb,
9
8
  type DbConnection,
9
+ fetchOne,
10
10
  } from "@cosmicdrift/kumiko-framework/db";
11
11
  import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
12
- import { runEventStoreSeed, type SeedIfExists } from "@cosmicdrift/kumiko-framework/seeding";
13
- import { TestUsers } from "@cosmicdrift/kumiko-framework/stack";
12
+ import {
13
+ runEventStoreSeed,
14
+ type SeedIfExists,
15
+ TestUsers,
16
+ } from "@cosmicdrift/kumiko-framework/seeding";
17
+
14
18
  import { type PageRow, pageEntity, pagesTable } from "./table.js";
15
19
 
16
20
  const executor = createEventStoreExecutor(pagesTable, pageEntity, { entityName: "page" });
@@ -33,7 +37,7 @@ export async function seedPage(db: DbConnection, opts: SeedPageOptions): Promise
33
37
  // der event-store-stream im falschen tenant-bucket → version_conflict
34
38
  // bei späteren echten writes). TestUsers.systemAdmin ist testTenantId(1).
35
39
  const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
36
- const tdb = createTenantDb(db, opts.tenantId, "system");
40
+ const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
37
41
 
38
42
  const existing = await fetchOne<PageRow>(db, pagesTable, {
39
43
  tenantId: opts.tenantId,
@@ -1,4 +1,4 @@
1
- import type { WhereObject } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import type { WhereObject } from "@cosmicdrift/kumiko-framework/db";
2
2
  import type {
3
3
  AggregateDimension,
4
4
  AggregateKey,
@@ -1,4 +1,4 @@
1
- import { extractTableInfo, type WhereObject } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { extractTableInfo, type WhereObject } from "@cosmicdrift/kumiko-framework/db";
2
2
  import type { HandlerContext } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
4
  import type { MetricDefinition, MetricFilterResolver } from "./types.js";
@@ -1,4 +1,4 @@
1
- import { extractTableInfo, isTimestamptzType } from "@cosmicdrift/kumiko-framework/bun-db";
1
+ import { extractTableInfo, isTimestamptzType } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { METRIC_RANGES } from "./constants.js";
3
3
  import { filterValueKindOf, metricFilterEntries, RESERVED_PAYLOAD_KEYS } from "./filters.js";
4
4
  import type { MetricDefinition } from "./types.js";