@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
@@ -19,7 +19,7 @@ import { CONSENT_LOCALES } from "./web/consumer-protection/consent-locale.ts";
19
19
  export const SUBSCRIPTION_AGGREGATE_TYPE = "subscription" as const;
20
20
 
21
21
  // Event-name constants — short form (for r.defineEvent) and qualified
22
- // FQN (for ctx.unsafeAppendEvent and projection-apply keys).
22
+ // FQN (for ctx.events.unsafeAppend and projection-apply keys).
23
23
  export const SUBSCRIPTION_CREATED_EVENT_SHORT = "subscription-created" as const;
24
24
  export const SUBSCRIPTION_UPDATED_EVENT_SHORT = "subscription-updated" as const;
25
25
  export const SUBSCRIPTION_CANCELED_EVENT_SHORT = "subscription-canceled" as const;
@@ -172,7 +172,7 @@ export function createBillingFoundationFeature<TTier extends string = string>(
172
172
  r.defineEvent(PAYMENT_RECEIVED_EVENT_SHORT, paymentEventPayloadSchema, { piiFields: "none" });
173
173
 
174
174
  // Inline projection: materialized current state in `read_subscriptions`.
175
- // Apply runs in the same TX as ctx.unsafeAppendEvent — read-your-own-
175
+ // Apply runs in the same TX as ctx.events.unsafeAppend — read-your-own-
176
176
  // write without a dispatcher tick.
177
177
  r.projection({
178
178
  name: "subscription",
@@ -260,13 +260,18 @@ export function createBillingFoundationFeature<TTier extends string = string>(
260
260
  perTenant: true,
261
261
  runOnBoot: true,
262
262
  handler: async (_payload, ctx) => {
263
- const result = await ctx.write(SubscriptionFoundationHandlers.syncSubscription, {});
263
+ const result = await ctx.dispatch.write(
264
+ SubscriptionFoundationHandlers.syncSubscription,
265
+ {},
266
+ );
264
267
  if (!result.isSuccess) {
265
268
  throw new Error(
266
269
  `billing-foundation:sync-subscriptions: sync-subscription write failed: ${JSON.stringify(result.error)}`,
267
270
  );
268
271
  }
269
- ctx.log.info(`[billing-foundation:sync-subscriptions] ${JSON.stringify(result.data)}`);
272
+ ctx.obs.log.info(
273
+ `[billing-foundation:sync-subscriptions] ${JSON.stringify(result.data)}`,
274
+ );
270
275
  },
271
276
  });
272
277
 
@@ -29,7 +29,7 @@ export type SubscriptionView = {
29
29
  * aggregate ID), or null if the tenant has never subscribed. The status
30
30
  * may be active/canceled/past_due/etc.; the caller decides what to do. */
31
31
  export async function getSubscriptionForTenant(
32
- ctx: HandlerContext,
32
+ ctx: Pick<HandlerContext, "db">,
33
33
  tenantId: string,
34
34
  ): Promise<SubscriptionView | null> {
35
35
  const aggId = subscriptionAggregateId(tenantId);
@@ -9,7 +9,7 @@
9
9
  // with no second append.
10
10
  // 2. Type mapping: SubscriptionEvent.type (= normalized by the plugin)
11
11
  // → one of the 5 ES event types.
12
- // 3. ctx.unsafeAppendEvent — the inline projection materializes the
12
+ // 3. ctx.events.unsafeAppend — the inline projection materializes the
13
13
  // `read_subscriptions` row in the same TX.
14
14
 
15
15
  import {
@@ -175,7 +175,7 @@ export async function appendSubscriptionEvent(
175
175
  // streams, optimize via snapshot or a per-tenant dedup table as the
176
176
  // idempotency anchor (like cap-counter).
177
177
  // ---------------------------------------------------------------
178
- const existingEvents = await ctx.loadAggregate(aggId);
178
+ const existingEvents = await ctx.events.load(aggId);
179
179
  const alreadySeen = existingEvents.some((e) => {
180
180
  const headers = e.metadata.headers ?? {};
181
181
  return (
@@ -191,7 +191,7 @@ export async function appendSubscriptionEvent(
191
191
  // late delivery: appending it would roll the row back (a canceled subscription
192
192
  // would come back active). Invoice events carry the live state, not a snapshot.
193
193
  if (isLateStateEvent(existingEvents, payload)) {
194
- ctx.log?.warn(
194
+ ctx.obs.log?.warn(
195
195
  `[billing-foundation:process-event] dropped late ${payload.type} ${payload.providerEventId}: a newer provider event is already stored`,
196
196
  );
197
197
  return { duplicate: false, stale: true, subscriptionAggregateId: aggId };
@@ -260,7 +260,7 @@ export async function appendSubscriptionEvent(
260
260
  providerEventId: payload.providerEventId,
261
261
  providerName: payload.providerName,
262
262
  };
263
- await ctx.unsafeAppendEvent({
263
+ await ctx.events.unsafeAppend({
264
264
  aggregateId: aggId,
265
265
  aggregateType: SUBSCRIPTION_AGGREGATE_TYPE,
266
266
  type: esEventType,
@@ -311,7 +311,7 @@ export function createProcessEventHandler(now: () => Temporal.Instant): WriteHan
311
311
  const payload = event.payload as ProcessEventPayload;
312
312
  const current = await getSubscriptionForTenant(ctx, event.user.tenantId);
313
313
  if (isStaleSubscriptionEvent(current, payload, now())) {
314
- ctx.log?.warn(
314
+ ctx.obs.log?.warn(
315
315
  `[billing-foundation:process-event] dropped stale ${payload.type} ${payload.providerEventId}: tenant already tracks another subscription`,
316
316
  );
317
317
  return {
@@ -6,7 +6,7 @@
6
6
  // 1. Idempotency-check: loads the payment-stream and scans for an
7
7
  // already-seen `metadata.providerEventId`. A provider-replay with
8
8
  // the same event-id → duplicate=true, no second append.
9
- // 2. ctx.unsafeAppendEvent — inline-projection materializes a new
9
+ // 2. ctx.events.unsafeAppend — inline-projection materializes a new
10
10
  // `read_payments`-row (INSERT-once, not UPSERT — every payment is
11
11
  // its own fact, not a state-update).
12
12
 
@@ -55,7 +55,7 @@ export const processPaymentEventHandler: WriteHandlerDef = {
55
55
  // (a tenant with hundreds of purchases scans hundreds of events;
56
56
  // optimize via a per-tenant providerEventId-index if that bites).
57
57
  // ---------------------------------------------------------------
58
- const existingEvents = await ctx.loadAggregate(aggId);
58
+ const existingEvents = await ctx.events.load(aggId);
59
59
  const alreadySeen = existingEvents.some((e) => {
60
60
  const headers = e.metadata.headers ?? {};
61
61
  return (
@@ -106,7 +106,7 @@ export const processPaymentEventHandler: WriteHandlerDef = {
106
106
  providerCheckoutId: payload.providerCheckoutId,
107
107
  }),
108
108
  };
109
- await ctx.unsafeAppendEvent({
109
+ await ctx.events.unsafeAppend({
110
110
  aggregateId: aggId,
111
111
  aggregateType: PAYMENT_AGGREGATE_TYPE,
112
112
  type: PAYMENT_RECEIVED_EVENT_QN,
@@ -77,7 +77,7 @@ export async function resolvePlanPrices(
77
77
  prices = await plugin.retrievePrices(ctx, allPriceIds);
78
78
  } catch (error) {
79
79
  const message = error instanceof Error ? error.message : String(error);
80
- ctx.log?.warn("billing-foundation: retrievePrices threw, all plan prices unavailable", {
80
+ ctx.obs.log?.warn("billing-foundation: retrievePrices threw, all plan prices unavailable", {
81
81
  message,
82
82
  });
83
83
  return result;
@@ -93,7 +93,7 @@ export async function resolvePlanPrices(
93
93
  const chosen = active[0];
94
94
  if (chosen) result.set(tier, { priceId: chosen.priceId, price: chosen });
95
95
  } else if (active.length > 1) {
96
- ctx.log?.warn(
96
+ ctx.obs.log?.warn(
97
97
  `billing-foundation: tier "${tier}" has ${active.length} active flat-amount prices — expected exactly one, price stays unavailable`,
98
98
  );
99
99
  }
@@ -1,7 +1,7 @@
1
1
  // Inline projection for `read_subscriptions`. Materializes the 5
2
2
  // subscription events into one row per tenant.
3
3
  //
4
- // Apply runs in the same transaction as ctx.unsafeAppendEvent, so the caller
4
+ // Apply runs in the same transaction as ctx.events.unsafeAppend, so the caller
5
5
  // sees its write state immediately (no dispatcher tick required). The PK is
6
6
  // event.aggregateId (= deterministic uuidv5 per tenant), so replays collide
7
7
  // on the PK instead of creating duplicate rows.
@@ -18,7 +18,7 @@
18
18
  // 2. **Post-tenant-resolution:** `createPortalSession` +
19
19
  // `cancelSubscription` are called from regular write handlers with
20
20
  // a fully resolved HandlerContext. The plugin can use ctx.config +
21
- // ctx.secrets for tenant-specific configuration (e.g. tenant-owned
21
+ // ctx.services.secrets for tenant-specific configuration (e.g. tenant-owned
22
22
  // customer-id mappings).
23
23
  //
24
24
  // Foundation uses only the common subset of provider functionality;
@@ -38,7 +38,7 @@ export function capCounterAggregateId(
38
38
  * different uuidv5 namespace, different output UUID. This also prevents an
39
39
  * accidental calendar increment from landing on the rolling stream.
40
40
  *
41
- * **Caller:** `CapCounterHandlers.incrementRolling` (via `ctx.write`) calls
41
+ * **Caller:** `CapCounterHandlers.incrementRolling` (via `ctx.dispatch.write`) calls
42
42
  * this with tenantId + capName and appends increment events to the stream.
43
43
  * Race-free because the event store appends with an auto-incrementing version.
44
44
  */
@@ -5,6 +5,7 @@ import {
5
5
  createEntityExecutor,
6
6
  type HandlerContext,
7
7
  type JobContext,
8
+ type ReservationContext,
8
9
  type SessionUser,
9
10
  type TenantId,
10
11
  type WriteResult,
@@ -84,7 +85,7 @@ export type BookCapUsageOptions = {
84
85
  readonly guardCurrentValue?: (currentValue: number) => void;
85
86
  };
86
87
 
87
- export type CapCounterContext = HandlerContext | JobContext;
88
+ export type CapCounterContext = HandlerContext | JobContext | ReservationContext;
88
89
 
89
90
  export type CapCounterScope = {
90
91
  readonly user: SessionUser;
@@ -104,7 +105,7 @@ function assertDbServesUser(db: TenantDb, user: SessionUser): TenantDb {
104
105
  }
105
106
 
106
107
  // Jobs write in place (their db is not transaction-bound); systemScope handlers reach both dbs via
107
- // systemDb, because their ctx.db / ctx.dbOutsideTransaction are fail-closed proxies.
108
+ // systemDb, because their ctx.db / ctx.db.outsideTransaction are fail-closed proxies.
108
109
  export function resolveCapCounterScope(
109
110
  ctx: CapCounterContext,
110
111
  outsideTransaction: boolean,
@@ -130,11 +131,11 @@ export function resolveCapCounterScope(
130
131
  : readDb;
131
132
  return { user, readDb, writeDb };
132
133
  }
133
- const writeDb = outsideTransaction ? ctx.dbOutsideTransaction : ctx.db;
134
+ const writeDb = outsideTransaction ? ctx.db.outsideTransaction : ctx.db;
134
135
  if (!writeDb) {
135
136
  throw new Error(
136
137
  outsideTransaction
137
- ? "cap-counter: outsideTransaction requested but ctx.dbOutsideTransaction is undefined"
138
+ ? "cap-counter: outsideTransaction requested but ctx.db.outsideTransaction is undefined"
138
139
  : "cap-counter: ctx.db missing — run inside a handler context",
139
140
  );
140
141
  }
@@ -612,7 +612,7 @@ export async function releaseExpiredCapReservations(
612
612
  try {
613
613
  await releaseCapReservation(ctx, id, outsideTransaction);
614
614
  } catch (error) {
615
- ctx.log?.error("releasing an expired cap reservation failed", { id, capName, error });
615
+ ctx.obs.log?.error("releasing an expired cap reservation failed", { id, capName, error });
616
616
  }
617
617
  }
618
618
  }
@@ -13,7 +13,7 @@ export const CAP_COUNTER_ROLLING_AGGREGATE_TYPE = "cap-counter-rolling" as const
13
13
  // Custom event types for rolling-window counters. The pair is symmetric:
14
14
  // _SHORT — matches `r.defineEvent(short, schema)` in the registrar
15
15
  // (the framework automatically prefixes it to the QN)
16
- // _QN — qualified form for `ctx.unsafeAppendEvent({type})`, the
16
+ // _QN — qualified form for `ctx.events.unsafeAppend({type})`, the
17
17
  // `events.type` column, and `registry.getEvent(qn)` lookups
18
18
  // Both MUST stay consistent; the feature test pins against drift.
19
19
  export const ROLLING_INCREMENTED_EVENT_SHORT = "rolling-incremented" as const;
@@ -31,7 +31,7 @@
31
31
  // ai-foundation are BYOK by default and currently have no platform pool
32
32
  // to count. cap-counter is generic: an app owner who wants to use the
33
33
  // counter calls `bookCapUsage(...)` /
34
- // `ctx.write(CapCounterHandlers.incrementRolling, ...)` from their own handler.
34
+ // `ctx.dispatch.write(CapCounterHandlers.incrementRolling, ...)` from their own handler.
35
35
  // - **No reset cron for the calendar period.** It works without one: the
36
36
  // periodStartIso part of the aggregate id rolls over to a fresh counter
37
37
  // at the period boundary. Old rows remain for auditing.
@@ -86,7 +86,7 @@ export function createCapCounterFeature() {
86
86
  });
87
87
 
88
88
  // Custom domain event for the rolling counter. r.defineEvent registers the
89
- // schema with the registry; ctx.unsafeAppendEvent in the handler reuses the
89
+ // schema with the registry; ctx.events.unsafeAppend in the handler reuses the
90
90
  // same schema for append-time validation. QN after prefixing:
91
91
  // "cap-counter:event:rolling-incremented" (see
92
92
  // ROLLING_INCREMENTED_EVENT_QN).
@@ -71,7 +71,7 @@ export const incrementRollingCapHandler: WriteHandlerDef = {
71
71
  // unsafeAppendEvent: the strict appendEvent is bound to an app's own event map, which
72
72
  // bundled-features cannot see. Schema validation still runs because r.defineEvent
73
73
  // registered the schema.
74
- await ctx.unsafeAppendEvent({
74
+ await ctx.events.unsafeAppend({
75
75
  aggregateId,
76
76
  aggregateType: CAP_COUNTER_ROLLING_AGGREGATE_TYPE,
77
77
  type: ROLLING_INCREMENTED_EVENT_QN,
@@ -30,7 +30,7 @@ export function chainReservations(
30
30
  try {
31
31
  await innerHandle.release();
32
32
  } catch (releaseError) {
33
- ctx.log?.error("releasing the inner cap reservation failed", { error: releaseError });
33
+ ctx.obs.log?.error("releasing the inner cap reservation failed", { error: releaseError });
34
34
  }
35
35
  throw error;
36
36
  }
@@ -12,7 +12,7 @@
12
12
  // after a rollback, failure result or failed COMMIT only gives back what is still booked, so an
13
13
  // unknown COMMIT outcome cannot under-count. No connection is held across the handler. Rows a
14
14
  // crashed process left behind expire after CAP_RESERVATION_TTL_MINUTES and are given back before the
15
- // next reserve of the same cap. Reached through a nested ctx.write the cap is not reserved, so the
15
+ // next reserve of the same cap. Reached through a nested ctx.dispatch.write the cap is not reserved, so the
16
16
  // dispatcher rejects that call unless the top-level batch reserved the same handler.
17
17
  //
18
18
  // The wrapper spreads the wrapped handler and chains its reserveBeforeTransaction: inner reserves
@@ -25,7 +25,7 @@
25
25
  // (enforce-cap.ts).
26
26
 
27
27
  import type {
28
- HandlerContext,
28
+ ReservationContext,
29
29
  WriteEvent,
30
30
  WriteHandlerDef,
31
31
  } from "@cosmicdrift/kumiko-framework/engine";
@@ -67,7 +67,7 @@ export type CalendarCapDef = {
67
67
  * tier from DB. */
68
68
  export type CalendarCapResolver = (
69
69
  event: WriteEvent,
70
- ctx: HandlerContext,
70
+ ctx: ReservationContext,
71
71
  ) => Promise<CalendarCapDef> | CalendarCapDef;
72
72
 
73
73
  /**
@@ -111,7 +111,7 @@ export type RollingCapDef = {
111
111
 
112
112
  export type RollingCapResolver = (
113
113
  event: WriteEvent,
114
- ctx: HandlerContext,
114
+ ctx: ReservationContext,
115
115
  ) => Promise<RollingCapDef> | RollingCapDef;
116
116
 
117
117
  /**
@@ -76,7 +76,7 @@ export function createCapsUsageQuery(
76
76
 
77
77
  // Override path: limits must read the TARGET tenant's config, not the
78
78
  // SystemAdmin caller's.
79
- const config = override === undefined ? ctx.config : ctx.configFor?.(targetTenantId);
79
+ const config = override === undefined ? ctx.config : ctx.tenants.config?.(targetTenantId);
80
80
 
81
81
  const rows: CapUsageWithMeta[] = await Promise.all(
82
82
  caps.map(async (cap) => {
@@ -251,7 +251,7 @@ export function createTenantCapsListQuery(caps: readonly CapSpec[], listCaps: re
251
251
  const limitByTenantAndCap = await resolveLimitsByTenantAndCap(
252
252
  listedCaps,
253
253
  page,
254
- ctx.configFor,
254
+ ctx.tenants.config,
255
255
  );
256
256
 
257
257
  const rows: TenantCapsListRow[] = page.map((row) => {
@@ -20,12 +20,12 @@ import {
20
20
  type DbConnection,
21
21
  fetchOne,
22
22
  } from "@cosmicdrift/kumiko-framework/db";
23
- import type { SessionUser, TenantId } from "@cosmicdrift/kumiko-framework/engine";
24
23
  import {
25
- runEventStoreSeed,
26
- type SeedIfExists,
27
- TestUsers,
28
- } from "@cosmicdrift/kumiko-framework/seeding";
24
+ createSystemUser,
25
+ type SessionUser,
26
+ type TenantId,
27
+ } from "@cosmicdrift/kumiko-framework/engine";
28
+ import { runEventStoreSeed, type SeedIfExists } from "@cosmicdrift/kumiko-framework/seeding";
29
29
 
30
30
  import {
31
31
  tenantComplianceProfileEntity,
@@ -52,8 +52,13 @@ export async function seedComplianceProfile(
52
52
  ): Promise<{ id: string }> {
53
53
  // user.tenantId must equal opts.tenantId so the Event Store stream
54
54
  // and projection remain in the same tenant bucket.
55
- const by = opts.by ?? { ...TestUsers.systemAdmin, tenantId: opts.tenantId };
56
- const tdb = createTenantDb({ db, tenantId: opts.tenantId, mode: "system" });
55
+ const by = opts.by ?? createSystemUser(opts.tenantId);
56
+ const tdb = createTenantDb({
57
+ db,
58
+ tenantId: opts.tenantId,
59
+ mode: "system",
60
+ reason: "seeding writes the compliance profile into an explicitly named tenant",
61
+ });
57
62
  const overrideJson = opts.override !== undefined ? JSON.stringify(opts.override) : null;
58
63
 
59
64
  const existing = (await fetchOne(db, tenantComplianceProfileTable, {
@@ -111,15 +111,15 @@ export function createConfigAccessorFactory(
111
111
  // session reads "config feature not wired into AppContext" instead of a
112
112
  // generic "configResolver missing".
113
113
  export function requireConfigResolver(ctx: HandlerContext, handlerName: string): ConfigResolver {
114
- if (!ctx.configResolver) {
114
+ if (!ctx.services.configResolver) {
115
115
  throw new InternalError({
116
116
  message:
117
- `[${handlerName}] ctx.configResolver missing — pass createConfigAccessorFactory's ` +
117
+ `[${handlerName}] ctx.services.configResolver missing — pass createConfigAccessorFactory's ` +
118
118
  `output via extraContext.configAccessorFactory and the resolver via ` +
119
119
  `extraContext.configResolver at boot.`,
120
120
  });
121
121
  }
122
- return ctx.configResolver;
122
+ return ctx.services.configResolver;
123
123
  }
124
124
 
125
125
  // Config declares r.systemScope() (raw ctx.db is unfiltered across tenants
@@ -156,14 +156,14 @@ export function requireSystemDb(
156
156
  // if a handler tries to write an encrypted key without the provider in
157
157
  // place, pointing at the exact wiring gap).
158
158
  export function requireConfigEncryption(ctx: HandlerContext, handlerName: string): EnvelopeCipher {
159
- if (!ctx.configEncryption) {
159
+ if (!ctx.services.configEncryption) {
160
160
  throw new InternalError({
161
161
  message:
162
- `[${handlerName}] ctx.configEncryption missing — at least one config key declares ` +
162
+ `[${handlerName}] ctx.services.configEncryption missing — at least one config key declares ` +
163
163
  `encrypted: true, so the boot wiring must pass an EnvelopeCipher via ` +
164
164
  `extraContext.configEncryption (run{Prod,Dev}App wire it automatically from ` +
165
165
  `KUMIKO_SECRETS_MASTER_KEY_V<n>; same instance the resolver was built with).`,
166
166
  });
167
167
  }
168
- return ctx.configEncryption;
168
+ return ctx.services.configEncryption;
169
169
  }
@@ -59,7 +59,7 @@ export const cascadeQuery = defineQueryHandler({
59
59
  query.user.tenantId,
60
60
  query.user.id,
61
61
  db,
62
- ctx.secrets,
62
+ ctx.services.secrets,
63
63
  );
64
64
 
65
65
  const result: Record<string, ConfigCascade> = {};
@@ -106,7 +106,7 @@ export async function collectMissingRequiredConfig(
106
106
  user.tenantId,
107
107
  user.id,
108
108
  db,
109
- ctx.secrets,
109
+ ctx.services.secrets,
110
110
  );
111
111
  for (const [qualifiedKey, keyDef] of candidates) {
112
112
  // Deliberately the unredacted cascade value: readiness asks "does this
@@ -69,22 +69,22 @@ export type ReencryptJobResult = {
69
69
 
70
70
  export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void> => {
71
71
  const payload = rawPayload as ReencryptJobPayload; // @cast-boundary engine-payload
72
- const maybeCipher = ctx.configEncryption;
72
+ const maybeCipher = ctx.services.configEncryption;
73
73
  if (!maybeCipher) {
74
74
  throw new InternalError({
75
75
  message:
76
- "[config:reencrypt] ctx.configEncryption missing — provide a master key " +
76
+ "[config:reencrypt] ctx.services.configEncryption missing — provide a master key " +
77
77
  "(KUMIKO_SECRETS_MASTER_KEY_V<n>) so the boot wires the envelope cipher.",
78
78
  });
79
79
  }
80
80
  // hoisted function declarations below capture these — pin the narrowed
81
81
  // type explicitly so TS keeps it inside the closures
82
82
  const cipher: EnvelopeCipher = maybeCipher;
83
- const provider = ctx.masterKeyProvider;
83
+ const provider = ctx.services.masterKeyProvider;
84
84
  if (!provider) {
85
85
  throw new InternalError({
86
86
  message:
87
- "[config:reencrypt] ctx.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
87
+ "[config:reencrypt] ctx.services.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
88
88
  });
89
89
  }
90
90
  if (!ctx.registry) {
@@ -116,8 +116,8 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
116
116
  handler: "config:job:reencrypt",
117
117
  tenantId,
118
118
  actor: "system",
119
- sink: ctx._escapeHatchAuditSink,
120
- log: ctx.log,
119
+ sink: ctx.services._escapeHatchAuditSink,
120
+ log: ctx.obs.log,
121
121
  });
122
122
  }
123
123
 
@@ -125,7 +125,12 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
125
125
  function tdbFor(tenantId: TenantId): TenantDb {
126
126
  let existing = tdbCache.get(tenantId);
127
127
  if (!existing) {
128
- existing = createTenantDb({ db, tenantId, mode: "system" });
128
+ existing = createTenantDb({
129
+ db,
130
+ tenantId,
131
+ mode: "system",
132
+ reason: "KEK rotation job re-encrypts config values of every tenant",
133
+ });
129
134
  tdbCache.set(tenantId, existing);
130
135
  }
131
136
  return existing;
@@ -146,7 +151,12 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
146
151
  // tenant's writes — sharing it with sdbFor(SYSTEM_TENANT_ID) would make a
147
152
  // write-path cache entry double as the scan's ack gate.
148
153
  const scanDb = createSystemDbView(
149
- createTenantDb({ db, tenantId: SYSTEM_TENANT_ID, mode: "system" }),
154
+ createTenantDb({
155
+ db,
156
+ tenantId: SYSTEM_TENANT_ID,
157
+ mode: "system",
158
+ reason: "KEK rotation scan enumerates config values across all tenants",
159
+ }),
150
160
  undefined,
151
161
  reportEscapeHatchFor(SYSTEM_TENANT_ID),
152
162
  );
@@ -219,7 +229,7 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
219
229
  // format) — never a supported re-encrypt input, so fail loudly
220
230
  // instead of relying on cipher.decrypt to reject it. Log only the
221
231
  // row id, never the value (ciphertext-adjacent).
222
- ctx.log?.warn?.(
232
+ ctx.obs.log?.warn?.(
223
233
  `[config:reencrypt] row ${row.id} is not a current-cipher envelope, not re-encryptable`,
224
234
  );
225
235
  return "failed";
@@ -244,7 +254,7 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
244
254
  // holds a fresh envelope written by the set handler — already fine.
245
255
  if (!result.isSuccess) {
246
256
  if (result.error.code === "version_conflict") return "skipped";
247
- ctx.log?.warn?.(`[config:reencrypt] executor rejected row ${row.id}`, {
257
+ ctx.obs.log?.warn?.(`[config:reencrypt] executor rejected row ${row.id}`, {
248
258
  code: result.error.code,
249
259
  });
250
260
  return "failed";
@@ -257,9 +267,9 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
257
267
  migrateRow,
258
268
  maxFailures,
259
269
  deadlineAt: deadline,
260
- signal: ctx.signal,
270
+ signal: ctx.lifecycle.signal,
261
271
  onRowError: ({ row }, err) => {
262
- ctx.log?.warn?.(`[config:reencrypt] failed to re-encrypt row ${row.id}`, { err });
272
+ ctx.obs.log?.warn?.(`[config:reencrypt] failed to re-encrypt row ${row.id}`, { err });
263
273
  },
264
274
  });
265
275
 
@@ -269,5 +279,5 @@ export const reencryptJob: JobHandlerFn = async (rawPayload, ctx): Promise<void>
269
279
  alreadyCurrent,
270
280
  stoppedReason: outcome.stoppedReason,
271
281
  };
272
- ctx.log?.info?.(`[config:reencrypt] complete: ${JSON.stringify(result)}`);
282
+ ctx.obs.log?.info?.(`[config:reencrypt] complete: ${JSON.stringify(result)}`);
273
283
  };
@@ -48,14 +48,14 @@ export const resetWrite = defineWriteHandler({
48
48
  // backing="secrets": clear the secret from the secrets store. delete() is
49
49
  // idempotent (returns false if absent) — mirrors the config no-op contract.
50
50
  if (keyDef.backing === "secrets") {
51
- if (!ctx.secrets) {
51
+ if (!ctx.services.secrets) {
52
52
  throw new InternalError({
53
53
  message:
54
54
  `[config:write:reset] key "${event.payload.key}" declares backing="secrets" but ` +
55
- `ctx.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
55
+ `ctx.services.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
56
56
  });
57
57
  }
58
- await ctx.secrets.delete(SYSTEM_TENANT_ID, event.payload.key, {
58
+ await ctx.services.secrets.delete(SYSTEM_TENANT_ID, event.payload.key, {
59
59
  deletedBy: event.user.id,
60
60
  });
61
61
  return { isSuccess: true, data: { key: event.payload.key, scope } };
@@ -53,7 +53,7 @@ export const selectedExtensionsQuery = defineQueryHandler({
53
53
  query.user.tenantId,
54
54
  query.user.id,
55
55
  db,
56
- ctx.secrets,
56
+ ctx.services.secrets,
57
57
  );
58
58
  const selected: Record<string, string> = {};
59
59
  for (const [selectorKey, keyDef] of readableSelectors) {
@@ -127,7 +127,7 @@ export const setWrite = defineWriteHandler({
127
127
  tenantId,
128
128
  event.user.id,
129
129
  validateDb,
130
- ctx.secrets,
130
+ ctx.services.secrets,
131
131
  );
132
132
  },
133
133
  });
@@ -146,14 +146,14 @@ export const setWrite = defineWriteHandler({
146
146
  // serialization as a config row so the read path round-trips via
147
147
  // deserializeValue. system-scope is guaranteed by the boot-guard.
148
148
  if (keyDef.backing === "secrets") {
149
- if (!ctx.secrets) {
149
+ if (!ctx.services.secrets) {
150
150
  throw new InternalError({
151
151
  message:
152
152
  `[config:write:set] key "${event.payload.key}" declares backing="secrets" but ` +
153
- `ctx.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
153
+ `ctx.services.secrets is not wired — provide extraContext.secrets (and a MasterKeyProvider).`,
154
154
  });
155
155
  }
156
- await ctx.secrets.set(
156
+ await ctx.services.secrets.set(
157
157
  SYSTEM_TENANT_ID,
158
158
  event.payload.key,
159
159
  JSON.stringify(event.payload.value),
@@ -59,7 +59,7 @@ export const valuesQuery = defineQueryHandler({
59
59
  query.user.tenantId,
60
60
  query.user.id,
61
61
  db,
62
- ctx.secrets,
62
+ ctx.services.secrets,
63
63
  );
64
64
 
65
65
  const result: Record<