@cosmicdrift/kumiko-samples 0.389.0 → 0.390.1

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 (301) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +27 -15
  3. package/packages/bundled-features/src/audit/feature.ts +1 -1
  4. package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +1 -1
  5. package/packages/bundled-features/src/auth-email-password/bootstrap.ts +13 -1
  6. package/packages/bundled-features/src/auth-email-password/changes.json +6 -0
  7. package/packages/bundled-features/src/auth-email-password/feature.ts +2 -2
  8. package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +7 -7
  9. package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts +3 -3
  10. package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
  11. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +9 -7
  12. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +11 -7
  13. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +4 -4
  14. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +2 -2
  15. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +9 -7
  16. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +23 -16
  17. package/packages/bundled-features/src/auth-email-password/handlers/reset-password.write.ts +3 -2
  18. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +12 -12
  19. package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +12 -8
  20. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +4 -2
  21. package/packages/bundled-features/src/auth-email-password/handlers/token-request-handler.ts +2 -2
  22. package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +3 -2
  23. package/packages/bundled-features/src/auth-email-password/seeding.ts +14 -9
  24. package/packages/bundled-features/src/auth-foundation/feature.ts +13 -4
  25. package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +5 -5
  26. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +24 -14
  27. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +9 -3
  28. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +6 -1
  29. package/packages/bundled-features/src/auth-mfa/handlers/enable-start.write.ts +3 -1
  30. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +14 -9
  31. package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -4
  32. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +25 -14
  33. package/packages/bundled-features/src/auth-mfa/mfa-code-verifier.ts +10 -4
  34. package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +9 -3
  35. package/packages/bundled-features/src/auth-mfa/verify-factor.ts +1 -1
  36. package/packages/bundled-features/src/billing-foundation/billing-info-query.ts +2 -2
  37. package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
  38. package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-gate.ts +1 -1
  39. package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +5 -5
  40. package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +10 -7
  41. package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +15 -12
  42. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-open-cancels.ts +22 -0
  43. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-provider-lock.ts +4 -0
  44. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-receipt-limit.ts +4 -4
  45. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +17 -58
  46. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +10 -8
  47. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +18 -15
  48. package/packages/bundled-features/src/billing-foundation/events.ts +1 -1
  49. package/packages/bundled-features/src/billing-foundation/feature.ts +8 -3
  50. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +1 -1
  51. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +5 -5
  52. package/packages/bundled-features/src/billing-foundation/handlers/process-payment-event.write.ts +3 -3
  53. package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +2 -2
  54. package/packages/bundled-features/src/billing-foundation/projection.ts +1 -1
  55. package/packages/bundled-features/src/billing-foundation/types.ts +1 -1
  56. package/packages/bundled-features/src/cap-counter/aggregate-id.ts +1 -1
  57. package/packages/bundled-features/src/cap-counter/book-cap-usage.ts +5 -4
  58. package/packages/bundled-features/src/cap-counter/cap-reservation.ts +1 -1
  59. package/packages/bundled-features/src/cap-counter/constants.ts +1 -1
  60. package/packages/bundled-features/src/cap-counter/feature.ts +2 -2
  61. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +1 -1
  62. package/packages/bundled-features/src/cap-counter/reservation-chain.ts +1 -1
  63. package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +4 -4
  64. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -1
  65. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  66. package/packages/bundled-features/src/compliance-profiles/seeding.ts +12 -7
  67. package/packages/bundled-features/src/config/feature.ts +6 -6
  68. package/packages/bundled-features/src/config/handlers/cascade.query.ts +1 -1
  69. package/packages/bundled-features/src/config/handlers/readiness.query.ts +1 -1
  70. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +23 -13
  71. package/packages/bundled-features/src/config/handlers/reset.write.ts +3 -3
  72. package/packages/bundled-features/src/config/handlers/selected-extensions.query.ts +1 -1
  73. package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
  74. package/packages/bundled-features/src/config/handlers/values.query.ts +1 -1
  75. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +8 -8
  76. package/packages/bundled-features/src/crypto-shredding/resolve-file-bytes-deleter.ts +3 -3
  77. package/packages/bundled-features/src/custom-fields/changes.json +6 -0
  78. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +1 -1
  79. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +1 -1
  80. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +1 -1
  81. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
  82. package/packages/bundled-features/src/custom-fields/index.ts +4 -0
  83. package/packages/bundled-features/src/data-retention/feature.ts +1 -1
  84. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +12 -2
  85. package/packages/bundled-features/src/delivery/attempt-log.ts +1 -1
  86. package/packages/bundled-features/src/delivery/delivery-service.ts +6 -5
  87. package/packages/bundled-features/src/delivery/feature.ts +2 -2
  88. package/packages/bundled-features/src/delivery/jobs.ts +11 -11
  89. package/packages/bundled-features/src/delivery/testing.ts +1 -1
  90. package/packages/bundled-features/src/document-ingest-foundation/events.ts +1 -1
  91. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +1 -1
  92. package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +1 -1
  93. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
  94. package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
  95. package/packages/bundled-features/src/file-derivatives/handlers/public-variant-by-file-ref.query.ts +5 -1
  96. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +7 -5
  97. package/packages/bundled-features/src/file-foundation/feature.ts +1 -1
  98. package/packages/bundled-features/src/file-foundation/read-file-ref-content.ts +7 -5
  99. package/packages/bundled-features/src/file-provider-s3/feature.ts +4 -1
  100. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +8 -8
  101. package/packages/bundled-features/src/form-draft/feature.ts +1 -1
  102. package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +22 -12
  103. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +3 -3
  104. package/packages/bundled-features/src/form-draft/handlers/get.query.ts +1 -1
  105. package/packages/bundled-features/src/foundation-shared/config-helpers.ts +1 -1
  106. package/packages/bundled-features/src/inbound-mail-foundation/events.ts +1 -1
  107. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +1 -1
  108. package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +2 -2
  109. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +1 -1
  110. package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +1 -1
  111. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +10 -10
  112. package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +1 -1
  113. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +1 -1
  114. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +1 -1
  115. package/packages/bundled-features/src/inbound-provider-imap/changes.json +6 -0
  116. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +4 -1
  117. package/packages/bundled-features/src/jobs/changes.json +6 -0
  118. package/packages/bundled-features/src/jobs/events.ts +1 -1
  119. package/packages/bundled-features/src/jobs/handlers/consumer.write.ts +7 -4
  120. package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  121. package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +11 -5
  122. package/packages/bundled-features/src/jobs/handlers/retention-cleanup.job.ts +1 -1
  123. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  124. package/packages/bundled-features/src/jobs/handlers/stale-run-sweep.job.ts +1 -1
  125. package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +2 -2
  126. package/packages/bundled-features/src/jobs/job-run-logger.ts +139 -90
  127. package/packages/bundled-features/src/legal-pages/README.md +1 -1
  128. package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +12 -8
  129. package/packages/bundled-features/src/mail-foundation/feature.ts +2 -2
  130. package/packages/bundled-features/src/mail-transport-smtp/changes.json +6 -0
  131. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +4 -1
  132. package/packages/bundled-features/src/managed-pages/seeding.ts +13 -8
  133. package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
  134. package/packages/bundled-features/src/personal-access-tokens/feature.ts +1 -1
  135. package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +2 -2
  136. package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
  137. package/packages/bundled-features/src/rate-limiting/handlers/status.query.ts +2 -2
  138. package/packages/bundled-features/src/readiness/handlers/status.query.ts +4 -1
  139. package/packages/bundled-features/src/renderer-foundation/api.ts +3 -3
  140. package/packages/bundled-features/src/secrets/announce-secret-change.ts +4 -4
  141. package/packages/bundled-features/src/secrets/feature.ts +9 -9
  142. package/packages/bundled-features/src/secrets/handlers/delete.write.ts +4 -3
  143. package/packages/bundled-features/src/secrets/handlers/rotate.job.ts +13 -8
  144. package/packages/bundled-features/src/secrets/handlers/set.write.ts +4 -3
  145. package/packages/bundled-features/src/secrets/secrets-context.ts +16 -6
  146. package/packages/bundled-features/src/secrets/write-gate.ts +1 -1
  147. package/packages/bundled-features/src/seo/feature.ts +1 -1
  148. package/packages/bundled-features/src/sessions/changes.json +12 -0
  149. package/packages/bundled-features/src/sessions/feature.ts +1 -1
  150. package/packages/bundled-features/src/sessions/handlers/cleanup.job.ts +2 -2
  151. package/packages/bundled-features/src/sessions/handlers/detail.query.ts +5 -2
  152. package/packages/bundled-features/src/sessions/handlers/list.query.ts +5 -2
  153. package/packages/bundled-features/src/sessions/handlers/mine.query.ts +5 -2
  154. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +3 -3
  155. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +1 -1
  156. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  157. package/packages/bundled-features/src/sessions/screens.ts +8 -4
  158. package/packages/bundled-features/src/sessions/session-revoked-event.ts +1 -1
  159. package/packages/bundled-features/src/sessions/web/session-device-cell.tsx +10 -12
  160. package/packages/bundled-features/src/sessions/web/user-agent.ts +12 -0
  161. package/packages/bundled-features/src/shared/index.ts +15 -0
  162. package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +12 -2
  163. package/packages/bundled-features/src/shared/require-for-tenant.ts +7 -5
  164. package/packages/bundled-features/src/shared/stream-tenant-backfill.ts +201 -0
  165. package/packages/bundled-features/src/shared/stream-tenant-derived-state.ts +107 -0
  166. package/packages/bundled-features/src/step-dispatcher/feature.ts +1 -1
  167. package/packages/bundled-features/src/subscription-dodo/plugin-methods.ts +1 -1
  168. package/packages/bundled-features/src/subscription-dodo/runtime.ts +7 -7
  169. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +5 -3
  170. package/packages/bundled-features/src/subscription-stripe/runtime.ts +7 -7
  171. package/packages/bundled-features/src/template-resolver/api.ts +3 -3
  172. package/packages/bundled-features/src/template-resolver/changes.json +18 -0
  173. package/packages/bundled-features/src/template-resolver/handlers/bundle-import.ts +5 -4
  174. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +2 -2
  175. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +1 -1
  176. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +2 -2
  177. package/packages/bundled-features/src/template-resolver/handlers/send-test-shared.ts +1 -1
  178. package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +2 -2
  179. package/packages/bundled-features/src/template-resolver/handlers/tenant-override-selection.ts +6 -2
  180. package/packages/bundled-features/src/template-resolver/handlers/tenant-overrides.query.ts +4 -2
  181. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +1 -1
  182. package/packages/bundled-features/src/template-resolver/seeding.ts +12 -2
  183. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +18 -13
  184. package/packages/bundled-features/src/template-resolver/template-resources.ts +4 -4
  185. package/packages/bundled-features/src/template-resolver/testing.ts +2 -2
  186. package/packages/bundled-features/src/template-resolver/web/document-insert-fields.tsx +222 -0
  187. package/packages/bundled-features/src/template-resolver/web/document-insert-model.ts +164 -0
  188. package/packages/bundled-features/src/template-resolver/web/document-insert-panel.tsx +115 -0
  189. package/packages/bundled-features/src/template-resolver/web/document-tiptap-bubble.tsx +177 -0
  190. package/packages/bundled-features/src/template-resolver/web/document-tiptap-content.tsx +38 -0
  191. package/packages/bundled-features/src/template-resolver/web/document-tiptap-context.ts +119 -0
  192. package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +51 -1098
  193. package/packages/bundled-features/src/template-resolver/web/document-tiptap-helpers.ts +161 -0
  194. package/packages/bundled-features/src/template-resolver/web/document-tiptap-layout.tsx +83 -0
  195. package/packages/bundled-features/src/template-resolver/web/document-tiptap-toolbar-groups.tsx +153 -0
  196. package/packages/bundled-features/src/template-resolver/web/document-tiptap-toolbar.tsx +182 -0
  197. package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +18 -0
  198. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +19 -6
  199. package/packages/bundled-features/src/template-resolver/web/use-document-tiptap-model.ts +138 -0
  200. package/packages/bundled-features/src/tenant/changes.json +19 -0
  201. package/packages/bundled-features/src/tenant/handlers/cancel-invitation.write.ts +1 -1
  202. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  203. package/packages/bundled-features/src/tenant/handlers/remove-member.write.ts +2 -2
  204. package/packages/bundled-features/src/tenant/handlers/update-member-roles.write.ts +1 -1
  205. package/packages/bundled-features/src/tenant/index.ts +5 -0
  206. package/packages/bundled-features/src/tenant/invited-membership.ts +6 -1
  207. package/packages/bundled-features/src/tenant/schema/tenant.ts +4 -1
  208. package/packages/bundled-features/src/tenant/seeding.ts +65 -62
  209. package/packages/bundled-features/src/tenant/stream-tenant-backfill.ts +115 -0
  210. package/packages/bundled-features/src/tenant/testing.ts +77 -0
  211. package/packages/bundled-features/src/tenant-handover/events.ts +1 -1
  212. package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
  213. package/packages/bundled-features/src/tenant-lifecycle/feature.ts +5 -5
  214. package/packages/bundled-features/src/tenant-lifecycle/handlers/cancel-destruction.write.ts +22 -10
  215. package/packages/bundled-features/src/tenant-lifecycle/handlers/request-destruction.write.ts +22 -11
  216. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +23 -12
  217. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +7 -3
  218. package/packages/bundled-features/src/tenant-lifecycle/testing.ts +9 -8
  219. package/packages/bundled-features/src/tier-engine/entity.ts +1 -1
  220. package/packages/bundled-features/src/tier-engine/feature.ts +8 -3
  221. package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +3 -3
  222. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +7 -1
  223. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +3 -3
  224. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +71 -97
  225. package/packages/bundled-features/src/user/handlers/find-for-auth.query.ts +2 -2
  226. package/packages/bundled-features/src/user/handlers/update-roles.ts +2 -2
  227. package/packages/bundled-features/src/user/index.ts +2 -0
  228. package/packages/bundled-features/src/user/invited-global-roles.ts +6 -1
  229. package/packages/bundled-features/src/user/principal-status.ts +1 -1
  230. package/packages/bundled-features/src/user/seeding.ts +24 -6
  231. package/packages/bundled-features/src/user/testing.ts +22 -0
  232. package/packages/bundled-features/src/user-data-rights/COMPLIANCE.md +1 -1
  233. package/packages/bundled-features/src/user-data-rights/README.md +1 -1
  234. package/packages/bundled-features/src/user-data-rights/audit-download.ts +12 -2
  235. package/packages/bundled-features/src/user-data-rights/changes.json +24 -0
  236. package/packages/bundled-features/src/user-data-rights/feature.ts +29 -24
  237. package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +1 -1
  238. package/packages/bundled-features/src/user-data-rights/handlers/deletion-grace-period.ts +1 -1
  239. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +2 -2
  240. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +2 -2
  241. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +1 -1
  242. package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +4 -4
  243. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +12 -6
  244. package/packages/bundled-features/src/user-data-rights/index.ts +2 -0
  245. package/packages/bundled-features/src/user-data-rights/lib/mail-transport-resolver.ts +1 -1
  246. package/packages/bundled-features/src/user-data-rights/lib/storage-provider-resolver.ts +1 -1
  247. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +6 -1
  248. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +8 -2
  249. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +14 -3
  250. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +11 -1
  251. package/packages/bundled-features/src/user-data-rights/web/constants.ts +10 -0
  252. package/packages/bundled-features/src/user-data-rights/web/index.ts +6 -1
  253. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +8 -6
  254. package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +1 -1
  255. package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +2 -2
  256. package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
  257. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +9 -4
  258. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +6 -1
  259. package/packages/bundled-features/src/waitlist/link-on-signup.ts +7 -1
  260. package/packages/bundled-features/src/workflow-runner/changes.json +6 -0
  261. package/packages/bundled-features/src/workflow-runner/db/queries/due-runs.ts +1 -1
  262. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -3
  263. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +2 -1
  264. package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
  265. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +8 -8
  266. package/packages/bundled-features/src/workflow-runner/runner.ts +6 -4
  267. package/samples/apps/cap-billing-demo/package.json +1 -1
  268. package/samples/apps/cap-billing-demo/src/feature.ts +19 -5
  269. package/samples/apps/config-demo/src/app/server.ts +1 -1
  270. package/samples/apps/styleguide/src/app/server.ts +2 -2
  271. package/samples/apps/ui-walkthrough/package.json +1 -1
  272. package/samples/apps/use-all-bundled/feature-manifest.json +1 -1
  273. package/samples/apps/use-all-bundled/package.json +1 -1
  274. package/samples/apps/use-all-bundled/src/app/seed.ts +12 -2
  275. package/samples/apps/user-data-rights-demo/README.md +1 -1
  276. package/samples/apps/user-data-rights-demo/package.json +1 -1
  277. package/samples/apps/user-data-rights-demo/src/feature.ts +3 -2
  278. package/samples/recipes/api-worker-split/README.md +2 -1
  279. package/samples/recipes/api-worker-split/src/feature.ts +2 -1
  280. package/samples/recipes/cross-feature-events/README.md +5 -5
  281. package/samples/recipes/cross-feature-events/package.json +1 -1
  282. package/samples/recipes/cross-feature-events/src/feature.ts +4 -4
  283. package/samples/recipes/event-sourcing/README.md +5 -5
  284. package/samples/recipes/event-sourcing/package.json +1 -1
  285. package/samples/recipes/event-sourcing/src/feature.ts +15 -15
  286. package/samples/recipes/files-post-processing/README.md +1 -1
  287. package/samples/recipes/files-post-processing/package.json +1 -1
  288. package/samples/recipes/files-post-processing/src/feature.ts +6 -4
  289. package/samples/recipes/lane-routing/package.json +1 -1
  290. package/samples/recipes/legal-pages/README.md +2 -2
  291. package/samples/recipes/lifecycle-hooks/README.md +2 -2
  292. package/samples/recipes/lifecycle-hooks/src/feature.ts +1 -1
  293. package/samples/recipes/managed-config/README.md +3 -3
  294. package/samples/recipes/search/README.md +1 -1
  295. package/samples/recipes/search/src/feature.ts +3 -3
  296. package/samples/recipes/secrets-demo/README.md +1 -1
  297. package/samples/recipes/secrets-demo/src/feature.ts +5 -2
  298. package/samples/recipes/state-machine/src/events.ts +1 -1
  299. package/samples/recipes/state-machine/src/reducer.ts +1 -1
  300. package/samples/recipes/workflow-engine/src/resume-loop.ts +4 -4
  301. package/samples/recipes/workflow-engine/src/workflow-runner.ts +2 -2
@@ -40,18 +40,32 @@ import type { EmailMessage } from "@cosmicdrift/kumiko-bundled-features/channel-
40
40
  import {
41
41
  createMailFoundationFeature,
42
42
  createTransportForTenant,
43
+ type MailTransportContext,
43
44
  } from "@cosmicdrift/kumiko-bundled-features/mail-foundation";
44
45
  import {
45
46
  access,
46
47
  createTenantConfig,
47
48
  defineFeature,
48
- type HandlerContext,
49
+ type ReservationContext,
49
50
  type WriteHandlerDef,
50
51
  } from "@cosmicdrift/kumiko-framework/engine";
51
52
  import { z } from "zod";
52
53
  import { DEMO_TIER_MAP, TIER_NAMES, type TierName } from "./tier-map";
53
54
 
54
55
  const FEATURE_NAME = "newsletter";
56
+
57
+ // The transport factory takes a narrow context (it also runs in the worker), so the handler's
58
+ // secrets live under services and are handed over explicitly.
59
+ function mailContextOf(
60
+ ctx: Pick<ReservationContext, "config" | "registry" | "services" | "user">,
61
+ ): MailTransportContext {
62
+ return {
63
+ config: ctx.config,
64
+ registry: ctx.registry,
65
+ secrets: ctx.services.secrets,
66
+ auditUserId: ctx.user.id,
67
+ };
68
+ }
55
69
  const NEWSLETTER_CAP = "newsletters-per-month";
56
70
 
57
71
  // =============================================================================
@@ -71,7 +85,7 @@ const innerSendHandler: WriteHandlerDef = {
71
85
  handler: async (event, ctx) => {
72
86
  const payload = event.payload as z.infer<typeof sendSchema>;
73
87
  const transport = await createTransportForTenant(
74
- ctx,
88
+ mailContextOf(ctx),
75
89
  event.user.tenantId,
76
90
  "newsletter:write:send",
77
91
  );
@@ -108,7 +122,7 @@ function isValidTierName(value: string): value is TierName {
108
122
  return (TIER_NAMES as readonly string[]).includes(value);
109
123
  }
110
124
 
111
- async function resolveTier(ctx: HandlerContext): Promise<TierName> {
125
+ async function resolveTier(ctx: ReservationContext): Promise<TierName> {
112
126
  const tenantId = ctx.user?.tenantId;
113
127
  if (tenantId) {
114
128
  const sub = await getSubscriptionForTenant(ctx, tenantId);
@@ -131,10 +145,10 @@ async function resolveTier(ctx: HandlerContext): Promise<TierName> {
131
145
 
132
146
  /** Notifier-Factory: bauen einen SoftHitNotifier der die Warnung über
133
147
  * dieselbe mail-foundation an den Tenant-Admin schickt. */
134
- function buildSoftHitNotifier(ctx: HandlerContext): SoftHitNotifier {
148
+ function buildSoftHitNotifier(ctx: ReservationContext): SoftHitNotifier {
135
149
  return async (info) => {
136
150
  const transport = await createTransportForTenant(
137
- ctx,
151
+ mailContextOf(ctx),
138
152
  info.tenantId,
139
153
  "newsletter:soft-hit-notifier",
140
154
  );
@@ -26,6 +26,6 @@ await runDevApp({
26
26
  watchDirs: ["./src", "../../../packages/*/src"],
27
27
  extraContext: ({ registry }) => ({
28
28
  configResolver: resolver,
29
- _configAccessorFactory: createConfigAccessorFactory(registry, resolver),
29
+ configAccessorFactory: createConfigAccessorFactory(registry, resolver),
30
30
  }),
31
31
  });
@@ -39,7 +39,7 @@ await runDevApp({
39
39
  aiSettingsFeature,
40
40
  workboardFeature,
41
41
  ],
42
- // Aktiviert die Upload-Routes (/api/files) + ctx.files für den Avatar-
42
+ // Aktiviert die Upload-Routes (/api/files) + ctx.services.files für den Avatar-
43
43
  // Stresstest. In-Memory reicht für die Demo (nicht-persistent).
44
44
  files: { storageProvider: createInMemoryFileProvider() },
45
45
  port: Number.parseInt(process.env["PORT"] ?? "4180", 10),
@@ -49,6 +49,6 @@ await runDevApp({
49
49
  seeds: [seedStyleguideItems, seedAiConnections, seedWorkboardTasks],
50
50
  extraContext: ({ registry }) => ({
51
51
  configResolver,
52
- _configAccessorFactory: createConfigAccessorFactory(registry, configResolver),
52
+ configAccessorFactory: createConfigAccessorFactory(registry, configResolver),
53
53
  }),
54
54
  });
@@ -18,7 +18,7 @@
18
18
  "@cosmicdrift/kumiko-server-runtime": "workspace:*",
19
19
  "react": "^19.2.6",
20
20
  "react-dom": "^19.2.6",
21
- "zod": "^4.4.3",
21
+ "zod": "^4.6.7",
22
22
  "@cosmicdrift/kumiko-locale-de": "workspace:*",
23
23
  "@cosmicdrift/kumiko-locale-es": "workspace:*"
24
24
  },
@@ -920,7 +920,7 @@
920
920
  },
921
921
  {
922
922
  "name": "file-derivatives",
923
- "description": "Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: \"ip\"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: \"fileRef\"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.",
923
+ "description": "Declares the `derivativeRenderer` extension point. `ctx.services.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: \"ip\"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: \"fileRef\"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.",
924
924
  "toggleableDefault": null,
925
925
  "requires": [
926
926
  "file-foundation",
@@ -26,7 +26,7 @@
26
26
  "@cosmicdrift/kumiko-types": "workspace:*",
27
27
  "react": "^19.2.6",
28
28
  "react-dom": "^19.2.6",
29
- "zod": "^4.4.3",
29
+ "zod": "^4.6.7",
30
30
  "@cosmicdrift/kumiko-locale-de": "workspace:*",
31
31
  "@cosmicdrift/kumiko-locale-es": "workspace:*",
32
32
  "@cosmicdrift/kumiko-locale-fr": "workspace:*",
@@ -93,7 +93,12 @@ async function seedTierAssignment(
93
93
  adminUserId: string,
94
94
  ): Promise<void> {
95
95
  const by: SessionUser = { ...TestUsers.systemAdmin, tenantId, id: adminUserId };
96
- const tdb = createTenantDb({ db, tenantId, mode: "system" });
96
+ const tdb = createTenantDb({
97
+ db,
98
+ tenantId,
99
+ mode: "system",
100
+ reason: "demo seed writes tier assignments for the tenant being provisioned",
101
+ });
97
102
  const result = await tierAssignmentExecutor.create(
98
103
  { id: tierAssignmentAggregateId(tenantId), tier, source: "manual", tenantId },
99
104
  by,
@@ -117,7 +122,12 @@ async function seedTagsAndNotes(
117
122
  adminUserId: string,
118
123
  ): Promise<void> {
119
124
  const by: SessionUser = { ...TestUsers.systemAdmin, tenantId, id: adminUserId };
120
- const tdb = createTenantDb({ db, tenantId, mode: "system" });
125
+ const tdb = createTenantDb({
126
+ db,
127
+ tenantId,
128
+ mode: "system",
129
+ reason: "demo seed writes tier assignments for the tenant being provisioned",
130
+ });
121
131
 
122
132
  const created = async (
123
133
  label: string,
@@ -16,7 +16,7 @@ DSGVO requests work end-to-end:
16
16
 
17
17
  | Article | Endpoint / Runner | What it does |
18
18
  |---------|-----------|----------------|
19
- | **Art. 15** | `user-data-rights:query:my-audit-log` | User sees own framework events (auth, deletion-request, restriction). Domain entities like todos appear in the **export bundle** (Art. 20), not the audit-log — only handlers using `ctx.appendEvent` show up here. |
19
+ | **Art. 15** | `user-data-rights:query:my-audit-log` | User sees own framework events (auth, deletion-request, restriction). Domain entities like todos appear in the **export bundle** (Art. 20), not the audit-log — only handlers using `ctx.events.append` show up here. |
20
20
  | **Art. 15+20** | `user-data-rights:write:request-export` | ZIP with user-profile + fileRefs + todos + signed download magic-link |
21
21
  | **Art. 17** | `user-data-rights:write:request-deletion` | Soft-delete with grace period; cron anonymizes user + deletes todos |
22
22
  | **Art. 18** | `user-data-rights:write:restrict-account` | Auth-middleware blocks logins until lift-restriction |
@@ -10,7 +10,7 @@
10
10
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",
11
11
  "@cosmicdrift/kumiko-dev-server": "workspace:*",
12
12
  "@cosmicdrift/kumiko-framework": "workspace:*",
13
- "zod": "^4.4.3",
13
+ "zod": "^4.6.7",
14
14
  "@cosmicdrift/kumiko-locale-de": "workspace:*"
15
15
  },
16
16
  "devDependencies": {
@@ -25,6 +25,7 @@
25
25
  // 3. todoDeleteHook DELETEt alle Rows mit author_id = userId
26
26
  // 4. user wird anonymisiert (display_name="(deleted)", email=null)
27
27
 
28
+ import { UserDataRightsScreens } from "@cosmicdrift/kumiko-bundled-features/user-data-rights";
28
29
  import {
29
30
  deleteMany,
30
31
  deriveEntityTableMeta,
@@ -182,7 +183,7 @@ export const todosFeature = defineFeature(FEATURE_NAME, (r) => {
182
183
  id: "gdpr-export-jobs",
183
184
  label: "GDPR · Export Jobs",
184
185
  icon: "shield",
185
- screen: "user-data-rights:screen:export-job-list",
186
+ screen: UserDataRightsScreens.exportJobList,
186
187
  access: { roles: ["SystemAdmin"] },
187
188
  order: 90,
188
189
  });
@@ -190,7 +191,7 @@ export const todosFeature = defineFeature(FEATURE_NAME, (r) => {
190
191
  id: "gdpr-download-attempts",
191
192
  label: "GDPR · Download Attempts",
192
193
  icon: "download",
193
- screen: "user-data-rights:screen:download-attempt-list",
194
+ screen: UserDataRightsScreens.downloadAttemptList,
194
195
  access: { roles: ["SystemAdmin"] },
195
196
  order: 91,
196
197
  });
@@ -60,7 +60,8 @@ row and the `read_fulfillments` row appear.
60
60
  is re-run after `ms` on the same queue job: no retry attempt is used, no failure is logged
61
61
  or recorded, and the run log shows only the runs that actually executed. `maxDefers`
62
62
  (default 100) bounds it; beyond that the run fails. It needs a queued run: an inline boot
63
- gate throws.
63
+ gate throws. `context.canDefer` is false in both cases, so the job checks it and calls the
64
+ carrier anyway instead of failing.
64
65
 
65
66
  ## Test
66
67
 
@@ -131,8 +131,9 @@ export function createApiWorkerSplitFeature() {
131
131
  }
132
132
  const { customerName } = processOrderPayloadSchema.parse(payload);
133
133
  // Busy is not a failure: ctx.defer re-runs the job later without burning a retry.
134
+ // Once the defer budget is used up (or the run is inline), try anyway and let a failure retry.
134
135
  const retryAfterMs = carrierRetryAfterMs();
135
- if (retryAfterMs > 0) return context.defer(retryAfterMs);
136
+ if (retryAfterMs > 0 && context.canDefer) return context.defer(retryAfterMs);
136
137
  const result = await fulfillWrite({
137
138
  handlerQn: "orders:write:fulfillment:create",
138
139
  payload: {
@@ -11,10 +11,10 @@ Three building blocks:
11
11
 
12
12
  - **`r.defineEvent("name", zodSchema)`** declares the name and payload.
13
13
  The qualified name (e.g. `pubsub-orders:event:order-placed`) comes
14
- back as `.name` — pass it directly to `ctx.appendEvent`. Events that
15
- aren't registered are rejected by `ctx.appendEvent` at the emit site.
14
+ back as `.name` — pass it directly to `ctx.events.append`. Events that
15
+ aren't registered are rejected by `ctx.events.append` at the emit site.
16
16
 
17
- - **`ctx.appendEvent({ aggregateId, aggregateType, type, payload })`**
17
+ - **`ctx.events.append({ aggregateId, aggregateType, type, payload })`**
18
18
  appends the event onto the aggregate stream within the same TX.
19
19
  Version lineage is continued automatically — no synthetic
20
20
  `"pubsub"` stream anymore, the event truly lives on the aggregate.
@@ -32,7 +32,7 @@ Three building blocks:
32
32
  HTTP → writeHandler
33
33
  ↓ TX begin
34
34
  orderExecutor.create(...) ← business row + auto-event (pubsubOrder.created, v1)
35
- ctx.appendEvent({...}) ← domain event (pubsub-orders:event:order-placed, v2)
35
+ ctx.events.append({...}) ← domain event (pubsub-orders:event:order-placed, v2)
36
36
  ↓ TX commit
37
37
  (async, post-commit)
38
38
  event-dispatcher runOnce
@@ -42,7 +42,7 @@ HTTP → writeHandler
42
42
 
43
43
  ## Migration note
44
44
 
45
- `r.postEvent` was removed in Sprint E.2. `ctx.appendEvent` +
45
+ `r.postEvent` was removed in Sprint E.2. `ctx.events.append` +
46
46
  `r.multiStreamProjection` is the unified Marten API for CRUD events,
47
47
  domain events, and cross-feature reactions.
48
48
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-sample-cross-feature-events",
3
- "description": "Feature appends a typed domain event via ctx.appendEvent; a r.multiStreamProjection reacts asynchronously.",
3
+ "description": "Feature appends a typed domain event via ctx.events.append; a r.multiStreamProjection reacts asynchronously.",
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@cosmicdrift/kumiko-framework": "workspace:*"
@@ -1,7 +1,7 @@
1
1
  // Cross-Feature Reactions Sample (Marten gold-standard path)
2
2
  //
3
3
  // Demonstrates the Sprint-E pattern for reacting to events across features:
4
- // a writeHandler emits a DOMAIN event via `ctx.appendEvent(...)` onto the
4
+ // a writeHandler emits a DOMAIN event via `ctx.events.append(...)` onto the
5
5
  // aggregate's own stream, and a `r.multiStreamProjection` picks it up
6
6
  // asynchronously through the event-dispatcher.
7
7
  //
@@ -9,11 +9,11 @@
9
9
  //
10
10
  // 1. `r.defineEvent("short-name", zodSchema)` declares the event shape.
11
11
  // Returns a def whose `.name` is the fully-qualified event name —
12
- // pass that straight to `ctx.appendEvent` so there's no string to
12
+ // pass that straight to `ctx.events.append` so there's no string to
13
13
  // hand-type (and no way to emit an unregistered event: appendEvent
14
14
  // rejects at the emit site).
15
15
  //
16
- // 2. `ctx.appendEvent({ aggregateId, aggregateType, type, payload })`
16
+ // 2. `ctx.events.append({ aggregateId, aggregateType, type, payload })`
17
17
  // writes the event onto the aggregate's own stream inside the same
18
18
  // transaction as the business write. Commit both or roll back both —
19
19
  // no lost events, no orphan events. The event carries real
@@ -67,7 +67,7 @@ export const pubsubOrderFeature = defineFeature("pubsubOrders", (r) => {
67
67
  r.entity({ name: "pubsub-order", ...orderEntity });
68
68
 
69
69
  // Define the event shape once. The returned `.name` is the qualified
70
- // name ("pubsub-orders:event:order-placed") — pass it to ctx.appendEvent.
70
+ // name ("pubsub-orders:event:order-placed") — pass it to ctx.events.append.
71
71
  const orderPlaced = r.defineEvent(
72
72
  "order-placed",
73
73
  z.object({ id: z.string(), customer: z.string(), product: z.string() }),
@@ -9,12 +9,12 @@ blocks Kumiko provides.
9
9
  | API | Purpose |
10
10
  |---|---|
11
11
  | `r.defineEvent(name, schema, { version, migrations })` | Event schema with version number + upcaster chain |
12
- | `ctx.appendEvent({ aggregateId, aggregateType, type, payload })` | Domain event on aggregate stream |
12
+ | `ctx.events.append({ aggregateId, aggregateType, type, payload })` | Domain event on aggregate stream |
13
13
  | `r.projection(...)` | Single-stream read model, inline in the write TX |
14
14
  | `r.multiStreamProjection(...)` | Cross-aggregate read model, async via dispatcher |
15
- | `ctx.loadAggregate(id, { asOf })` | Live aggregation with point-in-time |
16
- | `ctx.archiveStream(id, { aggregateType })` | Archive a stream (Marten `ArchiveStream`) |
17
- | `ctx.queryProjection(name)` | Tenant-scoped read-model query |
15
+ | `ctx.events.load(id, { asOf })` | Live aggregation with point-in-time |
16
+ | `ctx.events.archive(id, { aggregateType })` | Archive a stream (Marten `ArchiveStream`) |
17
+ | `ctx.dispatch.queryProjection(name)` | Tenant-scoped read-model query |
18
18
 
19
19
  ## Domain
20
20
 
@@ -45,7 +45,7 @@ HTTP POST /api/write { type: "showcase:write:invoice:approve", ... }
45
45
  ↓
46
46
  writeHandler("invoice:approve")
47
47
  ↓ TX begin
48
- ctx.appendEvent({ type: "showcase:event:invoice-approved", ... })
48
+ ctx.events.append({ type: "showcase:event:invoice-approved", ... })
49
49
  r.projection("invoice-detail") ← updates status = "approved"
50
50
  ↓ TX commit
51
51
  (async)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-sample-event-sourcing",
3
- "description": "Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.appendEvent + r.projection + r.multiStreamProjection + ctx.loadAggregate (asOf) + ctx.archiveStream + ctx.queryProjection.",
3
+ "description": "Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.events.append + r.projection + r.multiStreamProjection + ctx.events.load (asOf) + ctx.events.archive + ctx.dispatch.queryProjection.",
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@cosmicdrift/kumiko-framework": "workspace:*"
@@ -9,10 +9,10 @@
9
9
  // - emitEvent with headers — Marten free key/value metadata
10
10
  // - r.projection — single-stream read model (inline in the write TX)
11
11
  // - r.multiStreamProjection — cross-aggregate async read model
12
- // - ctx.loadAggregate with { asOf } — point-in-time aggregate state
13
- // - ctx.archiveStream / ctx.restoreStream — Marten ArchiveStream
14
- // - ctx.queryProjection — tenant-scoped read of a projection table
15
- // - ctx.snapshotAggregate + ctx.loadAggregateWithSnapshot — perf path
12
+ // - ctx.events.load with { asOf } — point-in-time aggregate state
13
+ // - ctx.events.archive / ctx.events.restore — Marten ArchiveStream
14
+ // - ctx.dispatch.queryProjection — tenant-scoped read of a projection table
15
+ // - ctx.events.snapshot + ctx.events.loadWithSnapshot — perf path
16
16
  // for aggregates with long event tails (O(1) vs O(N) reduce), incl.
17
17
  // the auto-snapshot policy ({ snapshotEvery, snapshotVersion })
18
18
  // - streamAllEventsByType — memory-bounded iteration for ops/export jobs
@@ -339,7 +339,7 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
339
339
  name: "invoice:archive",
340
340
  schema: z.object({ id: z.uuid() }),
341
341
  handler: async (event, ctx) => {
342
- await ctx.archiveStream(event.payload.id, { aggregateType: "showcase-invoice" });
342
+ await ctx.events.archive(event.payload.id, { aggregateType: "showcase-invoice" });
343
343
  return { isSuccess: true as const, data: { id: event.payload.id } };
344
344
  },
345
345
  access: { roles: ["Admin"] },
@@ -354,14 +354,14 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
354
354
  handler: async (event, ctx) => {
355
355
  // Rebuild the state from the current stream so the snapshot reflects
356
356
  // the committed event log, not an in-memory guess. Use the upcaster-
357
- // aware ctx.loadAggregate to stay consistent with read-time semantics.
358
- const events = await ctx.loadAggregate(event.payload.id);
357
+ // aware ctx.events.load to stay consistent with read-time semantics.
358
+ const events = await ctx.events.load(event.payload.id);
359
359
  const state: InvoiceState = { ...initialInvoiceState };
360
360
  for (const evt of events) {
361
361
  reduceInvoice(state, evt);
362
362
  }
363
363
  const version = events.length > 0 ? (events[events.length - 1]?.version ?? 0) : 0;
364
- await ctx.snapshotAggregate({
364
+ await ctx.events.snapshot({
365
365
  aggregateId: event.payload.id,
366
366
  aggregateType: "showcase-invoice",
367
367
  version,
@@ -374,13 +374,13 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
374
374
 
375
375
  // --- Query handlers ---
376
376
 
377
- // Live aggregation via ctx.loadAggregate — reduces events into a state
377
+ // Live aggregation via ctx.events.load — reduces events into a state
378
378
  // snapshot. Supports asOf for point-in-time reads.
379
379
  r.queryHandler({
380
380
  name: "invoice:state",
381
381
  schema: z.object({ id: z.uuid(), asOf: z.iso.datetime().optional() }),
382
382
  handler: async (query, ctx) => {
383
- const events = await ctx.loadAggregate(query.payload.id, {
383
+ const events = await ctx.events.load(query.payload.id, {
384
384
  ...(query.payload.asOf ? { asOf: Temporal.Instant.from(query.payload.asOf) } : {}),
385
385
  });
386
386
  const state: InvoiceState = { ...initialInvoiceState };
@@ -405,7 +405,7 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
405
405
  name: "invoice:fast-state",
406
406
  schema: z.object({ id: z.uuid() }),
407
407
  handler: async (query, ctx) => {
408
- const result = await ctx.loadAggregateWithSnapshot<InvoiceStateRecord>(
408
+ const result = await ctx.events.loadWithSnapshot<InvoiceStateRecord>(
409
409
  query.payload.id,
410
410
  (state, evt) => {
411
411
  const next: InvoiceStateRecord = { ...state };
@@ -434,7 +434,7 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
434
434
  },
435
435
  });
436
436
 
437
- // Read-model query via ctx.queryProjection — auto-tenant-scoped. The
437
+ // Read-model query via ctx.dispatch.queryProjection — auto-tenant-scoped. The
438
438
  // helper collapses the zero-argument "return this projection" pattern
439
439
  // into a single call; returns { rows } so the response shape stays
440
440
  // consistent with other list handlers.
@@ -450,11 +450,11 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
450
450
  }),
451
451
  );
452
452
 
453
- // Slow synthetic export — demonstrates ctx.signal honouring inside a
453
+ // Slow synthetic export — demonstrates ctx.lifecycle.signal honouring inside a
454
454
  // long-running handler loop. Real-world equivalents: PDF batch export,
455
455
  // bulk CSV download, multi-stream audit walk. Mobile clients that
456
456
  // navigate away mid-export should NOT keep the server busy producing
457
- // bytes nobody will read. The handler checks ctx.signal at every
457
+ // bytes nobody will read. The handler checks ctx.lifecycle.signal at every
458
458
  // iteration; on abort, throws and the dispatcher returns an error to
459
459
  // the (already-disconnected) client.
460
460
  r.queryHandler({
@@ -463,7 +463,7 @@ export const invoiceFeature = defineFeature("showcase", (r) => {
463
463
  handler: async (query, ctx) => {
464
464
  const accumulated: number[] = [];
465
465
  for (let i = 0; i < query.payload.chunks; i++) {
466
- ctx.signal?.throwIfAborted();
466
+ ctx.lifecycle.signal?.throwIfAborted();
467
467
  // Fake "work per chunk". Realistic handler would assemble a row,
468
468
  // hit a remote service, etc.
469
469
  await new Promise((resolve) => setTimeout(resolve, 10));
@@ -5,7 +5,7 @@ File upload plus post-processing hooks.
5
5
  ## What it shows
6
6
 
7
7
  - Declarative `variants` on `createImageField` (file-derivatives)
8
- - Imperative `ctx.derivatives.variant()` path and the public variant route (`EXT_DERIVATIVE_PUBLIC_PREDICATE`)
8
+ - Imperative `ctx.services.derivatives.variant()` path and the public variant route (`EXT_DERIVATIVE_PUBLIC_PREDICATE`)
9
9
 
10
10
  ## Source
11
11
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-sample-files-post-processing",
3
- "description": "The three ways to generate an image variant: declarative field variants, imperative ctx.derivatives.variant() with region-blur, and the public route behind a default-deny predicate.",
3
+ "description": "The three ways to generate an image variant: declarative field variants, imperative ctx.services.derivatives.variant() with region-blur, and the public route behind a default-deny predicate.",
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@cosmicdrift/kumiko-bundled-features": "workspace:*",
@@ -9,7 +9,7 @@
9
9
  // resolves + caches the variant behind the auth-gated
10
10
  // `GET /api/files/:id/variant/:name` route, no handler code needed.
11
11
  // 2. Imperative — the `set-cover` write-handler calls
12
- // `ctx.derivatives.variant()` directly. This is for apps that track
12
+ // `ctx.services.derivatives.variant()` directly. This is for apps that track
13
13
  // images as their own records (ordering, a chosen cover image) and for
14
14
  // region-blur, whose coordinates are runtime data that can't live in a
15
15
  // static field declaration.
@@ -88,13 +88,15 @@ export const filesPostProcessingFeature = defineFeature("files-post-processing",
88
88
  .optional(),
89
89
  }),
90
90
  handler: async (event, ctx) => {
91
- if (!ctx.derivatives) {
91
+ if (!ctx.services.derivatives) {
92
92
  return writeFailure(
93
- new InternalError({ message: "ctx.derivatives missing — is file-derivatives mounted?" }),
93
+ new InternalError({
94
+ message: "ctx.services.derivatives missing — is file-derivatives mounted?",
95
+ }),
94
96
  );
95
97
  }
96
98
  const { fileRefId, blurRegion } = event.payload;
97
- const result = await ctx.derivatives.variant(
99
+ const result = await ctx.services.derivatives.variant(
98
100
  fileRefId,
99
101
  {
100
102
  maxEdge: 800,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-sample-lane-routing",
3
- "description": "runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.appendEvent, verified end-to-end through createAllInOneEntrypoint.",
3
+ "description": "runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.events.append, verified end-to-end through createAllInOneEntrypoint.",
4
4
  "private": true,
5
5
  "dependencies": {
6
6
  "@cosmicdrift/kumiko-framework": "workspace:*"
@@ -100,9 +100,9 @@ A one-shot setup routine that runs on first boot or via the CLI:
100
100
  // bin/seed-legal.ts
101
101
  import { seedTextBlock } from "@cosmicdrift/kumiko-bundled-features/template-resolver/seeding";
102
102
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
103
- import { createDb } from "@cosmicdrift/kumiko-framework/db";
103
+ import { createDbConnection } from "@cosmicdrift/kumiko-framework/db";
104
104
 
105
- const db = createDb(process.env.DATABASE_URL!);
105
+ const { db } = createDbConnection({ url: process.env.DATABASE_URL! });
106
106
 
107
107
  await seedTextBlock(db, {
108
108
  tenantId: SYSTEM_TENANT_ID,
@@ -27,8 +27,8 @@ back.
27
27
  - **`r.hook({ type: "postDelete", target: { allOf: entityRef }, handler })`** — fires after commit.
28
28
  External side effects (logs, notifications) belong here because
29
29
  failures cannot roll the delete back.
30
- - **`ctx.scheduleAfterRollback(fn)`** — the counterpart of `scheduleAfterCommit`: runs `fn` when
31
- the handler transaction (or the enclosing savepoint of a nested `ctx.write`) does not commit.
30
+ - **`ctx.lifecycle.afterRollback(fn)`** — the counterpart of `ctx.lifecycle.afterCommit`: runs `fn` when
31
+ the handler transaction (or the enclosing savepoint of a nested `ctx.dispatch.write`) does not commit.
32
32
  Use it to give back something reserved outside the transaction, like the slot in
33
33
  `article:reserve-slot`. A failed COMMIT triggers it too, so write the callback idempotent.
34
34
 
@@ -65,7 +65,7 @@ export const articlesFeature = defineFeature("blog", (r) => {
65
65
  handler: async (event, ctx) => {
66
66
  const { slot, reject } = event.payload;
67
67
  reservedSlots.add(slot);
68
- ctx.scheduleAfterRollback?.(async () => {
68
+ ctx.lifecycle.afterRollback?.(async () => {
69
69
  reservedSlots.delete(slot);
70
70
  });
71
71
  if (reject) return writeFailure(new UnprocessableError("slot_rejected"));
@@ -43,7 +43,7 @@ r.config({
43
43
 
44
44
  - **`backing: "secrets"`** — the value lives in the secrets store (envelope
45
45
  encryption, KEK rotation, audit-on-read) instead of `config_values`. Set/read/
46
- reset dispatch through `ctx.secrets`; the query handlers mask the value while
46
+ reset dispatch through `ctx.services.secrets`; the query handlers mask the value while
47
47
  the owning feature still reads the revealed plaintext via `ctx.config`. Only
48
48
  valid for `scope: "system"` — secrets are flat per `(tenant, key)` with no
49
49
  cascade, so a tenant override would be incoherent and is rejected at boot.
@@ -72,7 +72,7 @@ await runProdApp({
72
72
  envSchema, // composeEnvSchema({ core: frameworkCoreEnvSchema, features })
73
73
  extraContext: ({ db, registry }) => ({
74
74
  configResolver: resolver,
75
- _configAccessorFactory: createConfigAccessorFactory(registry, resolver),
75
+ configAccessorFactory: createConfigAccessorFactory(registry, resolver),
76
76
  // Required whenever a key declares backing:"secrets" — without it the set
77
77
  // and read paths fail loud, never silently miss.
78
78
  secrets: createSecretsContext({ db, masterKeyProvider, registry }),
@@ -82,7 +82,7 @@ await runProdApp({
82
82
  ```
83
83
 
84
84
  Register the `secrets` feature too so its `tenant_secrets` table is migrated;
85
- the config backing only needs the `ctx.secrets` context shown above.
85
+ the config backing only needs the `ctx.services.secrets` context shown above.
86
86
 
87
87
  ## Vs. the neighbouring recipes
88
88
 
@@ -5,7 +5,7 @@ Tenant-scoped full-text search (Meilisearch / in-memory adapter).
5
5
  ## What it shows
6
6
 
7
7
  - `searchable` / `searchWeight` on fields
8
- - Handler reads via `ctx.searchAdapter`
8
+ - Handler reads via `ctx.services.searchAdapter`
9
9
 
10
10
  ## Source
11
11
 
@@ -1,6 +1,6 @@
1
1
  // Search Sample
2
2
  // Shows: searchable fields, searchWeight, search via InMemory SearchAdapter.
3
- // Each handler builds its executor inline so `ctx.searchAdapter` is read fresh
3
+ // Each handler builds its executor inline so `ctx.services.searchAdapter` is read fresh
4
4
  // per call — tests swap the adapter between runs.
5
5
 
6
6
  import { buildEntityTable, createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
@@ -38,7 +38,7 @@ export const productFeature = defineFeature("shop", (r) => {
38
38
  }),
39
39
  handler: async (event, ctx) => {
40
40
  const crud = createEventStoreExecutor(productTable, productEntity, {
41
- searchAdapter: ctx.searchAdapter,
41
+ searchAdapter: ctx.services.searchAdapter,
42
42
  entityName: "product",
43
43
  });
44
44
  return crud.create(event.payload, event.user, ctx.db);
@@ -54,7 +54,7 @@ export const productFeature = defineFeature("shop", (r) => {
54
54
  }),
55
55
  handler: async (query, ctx) => {
56
56
  const crud = createEventStoreExecutor(productTable, productEntity, {
57
- searchAdapter: ctx.searchAdapter,
57
+ searchAdapter: ctx.services.searchAdapter,
58
58
  entityName: "product",
59
59
  });
60
60
  return crud.list(query.payload, query.user, ctx.db);
@@ -4,7 +4,7 @@ Tenant-owned secrets with envelope encryption, DEK cache, and KEK rotation.
4
4
 
5
5
  ## What it shows
6
6
 
7
- - `r.secret` + `ctx.secrets.get` (audited reads)
7
+ - `r.secret` + `ctx.services.secrets.get` (audited reads)
8
8
  - Charge-style handler that never returns the plaintext key
9
9
 
10
10
  ## Source
@@ -1,4 +1,4 @@
1
- // A miniature "billing" feature that reads a Stripe API key from ctx.secrets
1
+ // A miniature "billing" feature that reads a Stripe API key from ctx.services.secrets
2
2
  // and simulates a charge. The point is to show how feature code uses the
3
3
  // plaintext secret without ever exposing it to clients — the charge endpoint
4
4
  // returns { chargeId } but never the apiKey.
@@ -27,7 +27,10 @@ const chargeWrite = defineWriteHandler({
27
27
  }),
28
28
  access: { roles: ["TenantAdmin", "User"] },
29
29
  handler: async (event, ctx) => {
30
- const secrets = requireSecretsContext(ctx, "billing:write:charge");
30
+ const secrets = requireSecretsContext(
31
+ { secrets: ctx.services.secrets, user: ctx.user },
32
+ "billing:write:charge",
33
+ );
31
34
  // requireSecretsContext returned a wrapper that auto-fills the audit
32
35
  // context (userId + "billing:write:charge") on every .get — the read
33
36
  // lands in tenant_secret_reads without the handler having to remember.
@@ -23,7 +23,7 @@ export const INVOICE_EVENTS = {
23
23
  // Qualifier used by the reducer to match events from the stream.
24
24
  // `<const TShort>` preserves the literal-string at the call-site, so
25
25
  // `eventName(INVOICE_EVENTS.sent)` carries `"billing:event:invoice-sent"`
26
- // as a literal type. That literal is what `ctx.appendEvent({ type, ... })`
26
+ // as a literal type. That literal is what `ctx.events.append({ type, ... })`
27
27
  // strict-checks against the augmented `KumikoEventTypeMap`.
28
28
  export function eventName<const TShort extends string>(
29
29
  short: TShort,