@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
@@ -18,9 +18,10 @@ export function createDeleteHandler(access: AccessRule = DEFAULT_SECRETS_ACCESS)
18
18
  access,
19
19
  escapeHatch: { grants: ["unsafeRaw"], reason: JOIN_REQUEST_TRANSACTION_REASON },
20
20
  handler: async (event, ctx) => {
21
- const secrets = requireSecretsContext(ctx, SecretsHandlers.delete).withRunner(
22
- ctx.db.unsafeRaw(),
23
- );
21
+ const secrets = requireSecretsContext(
22
+ { secrets: ctx.services.secrets, user: ctx.user },
23
+ SecretsHandlers.delete,
24
+ ).withRunner(ctx.db.unsafeRaw());
24
25
  const gate = checkSecretKeyWrite(ctx.registry, event.user.roles, event.payload.key, {
25
26
  allowUndeclared: true,
26
27
  });
@@ -61,13 +61,13 @@ export async function rotateJob(
61
61
  db: DbConnection,
62
62
  ): Promise<void> {
63
63
  const payload = rawPayload as RotateJobPayload; // @cast-boundary engine-payload
64
- if (!ctx.masterKeyProvider) {
64
+ if (!ctx.services.masterKeyProvider) {
65
65
  throw new InternalError({
66
66
  message:
67
- "[secrets:rotate] ctx.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
67
+ "[secrets:rotate] ctx.services.masterKeyProvider missing — wire it via extraContext.masterKeyProvider at boot.",
68
68
  });
69
69
  }
70
- const provider = ctx.masterKeyProvider;
70
+ const provider = ctx.services.masterKeyProvider;
71
71
  const batchSize = payload.batchSize ?? DEFAULT_BATCH_SIZE;
72
72
  const maxFailures = payload.maxFailures ?? DEFAULT_MAX_FAILURES;
73
73
  const deadline = payload.maxDurationMs
@@ -81,7 +81,12 @@ export async function rotateJob(
81
81
  function tdbFor(tenantId: TenantId): TenantDb {
82
82
  let existing = tdbCache.get(tenantId);
83
83
  if (!existing) {
84
- existing = createTenantDb({ db, tenantId, mode: "system" });
84
+ existing = createTenantDb({
85
+ db,
86
+ tenantId,
87
+ mode: "system",
88
+ reason: "secret key rotation job re-encrypts secrets of every tenant",
89
+ });
85
90
  tdbCache.set(tenantId, existing);
86
91
  }
87
92
  return existing;
@@ -137,7 +142,7 @@ export async function rotateJob(
137
142
  // potentially even past target.
138
143
  if (!result.isSuccess) {
139
144
  if (result.error.code === "version_conflict") return "skipped";
140
- ctx.log?.warn?.(`[secrets:rotate] executor rejected row ${row.id}`, {
145
+ ctx.obs.log?.warn?.(`[secrets:rotate] executor rejected row ${row.id}`, {
141
146
  code: result.error.code,
142
147
  });
143
148
  return "failed";
@@ -150,9 +155,9 @@ export async function rotateJob(
150
155
  migrateRow,
151
156
  maxFailures,
152
157
  deadlineAt: deadline,
153
- signal: ctx.signal,
158
+ signal: ctx.lifecycle.signal,
154
159
  onRowError: (row, err) => {
155
- ctx.log?.warn?.(`[secrets:rotate] failed to rotate row ${row.id}`, { err });
160
+ ctx.obs.log?.warn?.(`[secrets:rotate] failed to rotate row ${row.id}`, { err });
156
161
  },
157
162
  });
158
163
 
@@ -162,5 +167,5 @@ export async function rotateJob(
162
167
  batchesProcessed: outcome.batchesProcessed,
163
168
  stoppedReason: outcome.stoppedReason,
164
169
  };
165
- ctx.log?.info?.(`[secrets:rotate] complete: ${JSON.stringify(result)}`);
170
+ ctx.obs.log?.info?.(`[secrets:rotate] complete: ${JSON.stringify(result)}`);
166
171
  }
@@ -25,9 +25,10 @@ export function createSetHandler(access: AccessRule = DEFAULT_SECRETS_ACCESS) {
25
25
  access,
26
26
  escapeHatch: { grants: ["unsafeRaw"], reason: JOIN_REQUEST_TRANSACTION_REASON },
27
27
  handler: async (event, ctx) => {
28
- const secrets = requireSecretsContext(ctx, SecretsHandlers.set).withRunner(
29
- ctx.db.unsafeRaw(),
30
- );
28
+ const secrets = requireSecretsContext(
29
+ { secrets: ctx.services.secrets, user: ctx.user },
30
+ SecretsHandlers.set,
31
+ ).withRunner(ctx.db.unsafeRaw());
31
32
  const { key, value, redactedPreview, hint } = event.payload;
32
33
 
33
34
  // Preview-priority: explicit payload param > feature-declared redact
@@ -1,6 +1,6 @@
1
- // Feature-level accessor injected as `ctx.secrets` at boot. Not a HTTP API —
1
+ // Feature-level accessor injected as `ctx.services.secrets` at boot. Not a HTTP API —
2
2
  // feature code that needs a plaintext secret (SMTP-connect, Stripe-call, …)
3
- // pulls it via ctx.secrets.get. Cleartext never crosses the wire.
3
+ // pulls it via ctx.services.secrets.get. Cleartext never crosses the wire.
4
4
  //
5
5
  // Post-ES pivot: all three ops (get/set/delete) flow through the events-
6
6
  // table.
@@ -154,7 +154,7 @@ function buildSecretsContext(
154
154
  const readId = generateId();
155
155
  const metadata: EventMetadata = { userId: auditCtx.userId };
156
156
  // Parse against the registered schema so the low-level append
157
- // here gets the same validation guarantee as ctx.appendEvent.
157
+ // here gets the same validation guarantee as ctx.events.append.
158
158
  // A payload-shape drift between schema + call-site fails at the
159
159
  // source instead of landing on the events-stream.
160
160
  const payload = secretReadSchema.parse({
@@ -206,7 +206,12 @@ function buildSecretsContext(
206
206
  tenantId,
207
207
  roles: SYSTEM_ROLES,
208
208
  };
209
- const tdb = createTenantDb({ db, tenantId, mode: "system" });
209
+ const tdb = createTenantDb({
210
+ db,
211
+ tenantId,
212
+ mode: "system",
213
+ reason: "secrets API writes for a caller-named tenant, outside a request scope",
214
+ });
210
215
 
211
216
  const existing = await lookup(tenantId, key);
212
217
  const commonFields = {
@@ -271,7 +276,12 @@ function buildSecretsContext(
271
276
  tenantId,
272
277
  roles: SYSTEM_ROLES,
273
278
  };
274
- const tdb = createTenantDb({ db, tenantId, mode: "system" });
279
+ const tdb = createTenantDb({
280
+ db,
281
+ tenantId,
282
+ mode: "system",
283
+ reason: "secrets API writes for a caller-named tenant, outside a request scope",
284
+ });
275
285
  const result = await executor.delete({ id: existing.id }, actor, tdb);
276
286
  return result.isSuccess;
277
287
  },
@@ -279,7 +289,7 @@ function buildSecretsContext(
279
289
  }
280
290
 
281
291
  // Wrap an executor-level write failure into a KumikoError so callers of
282
- // ctx.secrets.set / .delete can still branch on .code / details / i18nKey
292
+ // ctx.services.secrets.set / .delete can still branch on .code / details / i18nKey
283
293
  // after it propagates up. Plain `new Error(...)` would have stripped the
284
294
  // structured payload the error-contract promises.
285
295
  function wrapSetFailure(err: WriteErrorInfo): InternalError {
@@ -77,7 +77,7 @@ export function checkSecretKeyWrite(
77
77
  return { ok: true, keyDef };
78
78
  }
79
79
 
80
- // The registry surface the value check needs; lets ctx.secrets validate without a full Registry.
80
+ // The registry surface the value check needs; lets ctx.services.secrets validate without a full Registry.
81
81
  export type SecretValueSchemaSource = Pick<Registry, "getSecretKey" | "findSecretNamespace">;
82
82
 
83
83
  // Carries neither the value nor the schema's issues.
@@ -285,7 +285,7 @@ export function createSeoFeature(opts: SeoOptions): FeatureDefinition {
285
285
  sitemapEntries: opts.sitemapEntries,
286
286
  includeLegalPages: opts.includeLegalPages ?? false,
287
287
  hasManagedPages: opts.managedPages !== undefined,
288
- log: ctx.log,
288
+ log: ctx.obs.log,
289
289
  }),
290
290
  );
291
291
 
@@ -1,4 +1,16 @@
1
1
  [
2
+ {
3
+ "version": "0.390.0",
4
+ "type": "fix",
5
+ "title": "Session screens show the device without sessionsClient()",
6
+ "detail": "The list, my-sessions and detail screens showed [object Object] in the device column for apps that do not register sessionsClient(). The session queries (user-session:list, user-session:mine, user-session:detail) now return a deviceLabel string such as \"Chrome 141 · macOS\" next to the unchanged device object, null when the user agent is unknown, and the screens render that field. sessionsClient() only adds the translated \"Unknown device\" for rows without a label."
7
+ },
8
+ {
9
+ "version": "0.390.0",
10
+ "type": "improvement",
11
+ "title": "Sessions tests no longer write projection tables directly",
12
+ "detail": "The sessions integration tests change tenant memberships and user status through the update-member-roles handler or the event-store executor instead of writing into the projection tables. Nothing changes for apps; the package is only republished."
13
+ },
2
14
  {
3
15
  "version": "0.389.0",
4
16
  "type": "breaking",
@@ -157,7 +157,7 @@ export function createSessionsFeature(options?: SessionsFeatureOptions): Feature
157
157
  } satisfies SessionStoreProvider);
158
158
 
159
159
  // Custom domain-event for cross-instance access-invalidation.
160
- // r.defineEvent registers the schema so ctx.unsafeAppendEvent (revoke,
160
+ // r.defineEvent registers the schema so ctx.events.unsafeAppend (revoke,
161
161
  // revoke-all-others) enforces it at append time. revoke-all-for-user
162
162
  // appends via the low-level append() instead (needs to anchor on
163
163
  // SYSTEM_TENANT_ID — see that handler for why) — append() does NOT
@@ -60,7 +60,7 @@ export async function cleanupJob(
60
60
  let stoppedReason: SessionCleanupResult["stoppedReason"] = "empty";
61
61
 
62
62
  while (true) {
63
- if (ctx.signal?.aborted) {
63
+ if (ctx.lifecycle.signal?.aborted) {
64
64
  stoppedReason = "signal";
65
65
  break;
66
66
  }
@@ -79,5 +79,5 @@ export async function cleanupJob(
79
79
  }
80
80
 
81
81
  const result: SessionCleanupResult = { deleted, batchesProcessed, stoppedReason };
82
- ctx.log?.info?.(`[sessions:cleanup] complete: ${JSON.stringify(result)}`);
82
+ ctx.obs.log?.info?.(`[sessions:cleanup] complete: ${JSON.stringify(result)}`);
83
83
  }
@@ -3,7 +3,7 @@ import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine
3
3
  import * as z from "zod";
4
4
  import { decryptStoredPii } from "../../shared/index.ts";
5
5
  import { userSessionTable } from "../schema/user-session.ts";
6
- import { parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
6
+ import { formatDeviceLabel, parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
7
7
 
8
8
  // Admin single-session inspector — mirrors list.query's decrypt handling for
9
9
  // the one-row case. ctx.db (TenantDb) applies tenant-scoping automatically.
@@ -16,6 +16,7 @@ const sessionRowSchema = z.object({
16
16
  ip: z.string().nullable(),
17
17
  userAgent: z.string().nullable(),
18
18
  device: parsedDeviceSchema,
19
+ deviceLabel: z.string().nullable(),
19
20
  });
20
21
 
21
22
  export const createDetailQuery = (adminRoles: readonly string[] = access.admin) =>
@@ -42,6 +43,7 @@ export const createDetailQuery = (adminRoles: readonly string[] = access.admin)
42
43
  const userAgent = row.userAgent
43
44
  ? await decryptStoredPii(row.userAgent, "userAgent", "sessions:detail")
44
45
  : row.userAgent;
46
+ const device = parseUserAgent(userAgent);
45
47
  return {
46
48
  id: row.id,
47
49
  userId: row.userId,
@@ -50,7 +52,8 @@ export const createDetailQuery = (adminRoles: readonly string[] = access.admin)
50
52
  revokedAt: row.revokedAt,
51
53
  ip: row.ip ? await decryptStoredPii(row.ip, "ip", "sessions:detail") : row.ip,
52
54
  userAgent,
53
- device: parseUserAgent(userAgent),
55
+ device,
56
+ deviceLabel: formatDeviceLabel(device),
54
57
  };
55
58
  },
56
59
  });
@@ -8,7 +8,7 @@ import { isOneOf } from "@cosmicdrift/kumiko-types/type-guards";
8
8
  import * as z from "zod";
9
9
  import { decryptStoredPii } from "../../shared/index.ts";
10
10
  import { userSessionTable } from "../schema/user-session.ts";
11
- import { parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
11
+ import { formatDeviceLabel, parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
12
12
 
13
13
  // `sort` arrives raw from the client's query string. selectMany's orderBy
14
14
  // has no column-existence check — an unrecognised field just gets
@@ -49,6 +49,7 @@ export const createListQuery = (adminRoles: readonly string[] = access.admin) =>
49
49
  ip: z.string().nullable(),
50
50
  userAgent: z.string().nullable(),
51
51
  device: parsedDeviceSchema,
52
+ deviceLabel: z.string().nullable(),
52
53
  }),
53
54
  ),
54
55
  nextCursor: z.string().nullable(),
@@ -85,6 +86,7 @@ export const createListQuery = (adminRoles: readonly string[] = access.admin) =>
85
86
  const userAgent = r.userAgent
86
87
  ? await decryptStoredPii(r.userAgent, "userAgent", "sessions:list")
87
88
  : r.userAgent;
89
+ const device = parseUserAgent(userAgent);
88
90
  return {
89
91
  id: r.id,
90
92
  userId: r.userId,
@@ -93,7 +95,8 @@ export const createListQuery = (adminRoles: readonly string[] = access.admin) =>
93
95
  revokedAt: r.revokedAt,
94
96
  ip: r.ip ? await decryptStoredPii(r.ip, "ip", "sessions:list") : r.ip,
95
97
  userAgent,
96
- device: parseUserAgent(userAgent),
98
+ device,
99
+ deviceLabel: formatDeviceLabel(device),
97
100
  };
98
101
  }),
99
102
  );
@@ -3,7 +3,7 @@ import { definePagedQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import * as z from "zod";
4
4
  import { decryptStoredPii } from "../../shared/index.ts";
5
5
  import { userSessionTable } from "../schema/user-session.ts";
6
- import { parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
6
+ import { formatDeviceLabel, parsedDeviceSchema, parseUserAgent } from "../web/user-agent.ts";
7
7
 
8
8
  // "My live sessions" — the backing data for a devices/sessions UI. Returns
9
9
  // ONLY the current user's own, currently-live sessions, ordered by most-
@@ -31,6 +31,7 @@ export const mineQuery = definePagedQueryHandler({
31
31
  ip: z.string().nullable(),
32
32
  userAgent: z.string().nullable(),
33
33
  device: parsedDeviceSchema,
34
+ deviceLabel: z.string().nullable(),
34
35
  current: z.boolean(),
35
36
  }),
36
37
  ),
@@ -57,13 +58,15 @@ export const mineQuery = definePagedQueryHandler({
57
58
  const userAgent = r.userAgent
58
59
  ? await decryptStoredPii(r.userAgent, "userAgent", "sessions:mine")
59
60
  : r.userAgent;
61
+ const device = parseUserAgent(userAgent);
60
62
  return {
61
63
  id: r.id,
62
64
  createdAt: r.createdAt,
63
65
  expiresAt: r.expiresAt,
64
66
  ip: r.ip ? await decryptStoredPii(r.ip, "ip", "sessions:mine") : r.ip,
65
67
  userAgent,
66
- device: parseUserAgent(userAgent),
68
+ device,
69
+ deviceLabel: formatDeviceLabel(device),
67
70
  current: currentSid === r.id,
68
71
  };
69
72
  }),
@@ -67,9 +67,9 @@ export const revokeAllForUserWrite = defineWriteHandler({
67
67
  // Lightweight append alongside the direct-write above; see revoke.write.ts
68
68
  // for why this isn't a lifecycle event on
69
69
  // store_user_sessions. Uses the low-level append() (not
70
- // ctx.unsafeAppendEvent) because this handler is deliberately
70
+ // ctx.events.unsafeAppend) because this handler is deliberately
71
71
  // cross-tenant: the privileged caller's own tenantId (what
72
- // ctx.unsafeAppendEvent would bind to) has no relationship to the
72
+ // ctx.events.unsafeAppend would bind to) has no relationship to the
73
73
  // target user's session tenant(s). Anchored on SYSTEM_TENANT_ID
74
74
  // instead, same as the jobs feature's cross-tenant run-lifecycle
75
75
  // events (job-run-logger.ts) — a fresh aggregate per call, so no
@@ -77,7 +77,7 @@ export const revokeAllForUserWrite = defineWriteHandler({
77
77
  //
78
78
  // append() itself does NOT validate against the r.defineEvent-
79
79
  // registered schema (that guarantee only comes from going through
80
- // ctx.unsafeAppendEvent's dispatcher path). Mirrors job-run-logger.ts:
80
+ // ctx.events.unsafeAppend's dispatcher path). Mirrors job-run-logger.ts:
81
81
  // parse explicitly before the raw append so a shape drift fails loudly
82
82
  // here instead of landing unvalidated on the events table.
83
83
  if (updated.length > 0) {
@@ -51,7 +51,7 @@ export const revokeAllOthersWrite = defineWriteHandler({
51
51
  // store_user_sessions. Skipped when nothing was revoked (no other
52
52
  // live sessions) — a spurious invalidation would be the failure mode.
53
53
  if (updated.length > 0) {
54
- await ctx.unsafeAppendEvent({
54
+ await ctx.events.unsafeAppend({
55
55
  aggregateId: generateId(),
56
56
  aggregateType: SESSION_REVOKED_AGGREGATE_TYPE,
57
57
  type: SESSION_REVOKED_EVENT_QN,
@@ -55,7 +55,7 @@ export const revokeWrite = defineWriteHandler({
55
55
  // unmanaged direct-write store, see feature.ts). Own aggregate id per
56
56
  // revoke, no predecessor to satisfy, no version_conflict against a
57
57
  // concurrent revoke on a different sid.
58
- await ctx.unsafeAppendEvent({
58
+ await ctx.events.unsafeAppend({
59
59
  aggregateId: generateId(),
60
60
  aggregateType: SESSION_REVOKED_AGGREGATE_TYPE,
61
61
  type: SESSION_REVOKED_EVENT_QN,
@@ -39,7 +39,7 @@ export const createSessionListScreen = (
39
39
  refLabelField: "displayName",
40
40
  },
41
41
  {
42
- field: "device",
42
+ field: "deviceLabel",
43
43
  label: i18nKey("sessions.list.col.device"),
44
44
  renderer: DEVICE_RENDERER,
45
45
  },
@@ -94,7 +94,7 @@ export const createSessionDetailScreen = (
94
94
  { field: "createdAt", renderer: { format: "timestamp" } },
95
95
  { field: "expiresAt", renderer: { format: "timestamp" } },
96
96
  { field: "revokedAt", renderer: { format: "timestamp" } },
97
- { field: "device", renderer: DEVICE_RENDERER },
97
+ { field: "deviceLabel", renderer: DEVICE_RENDERER },
98
98
  "ip",
99
99
  "userAgent",
100
100
  ],
@@ -107,7 +107,7 @@ export const createSessionDetailScreen = (
107
107
  createdAt: i18nKey("sessions.detail.field.createdAt"),
108
108
  expiresAt: i18nKey("sessions.detail.field.expiresAt"),
109
109
  revokedAt: i18nKey("sessions.detail.field.revokedAt"),
110
- device: i18nKey("sessions.list.col.device"),
110
+ deviceLabel: i18nKey("sessions.list.col.device"),
111
111
  ip: i18nKey("sessions.detail.field.ip"),
112
112
  userAgent: i18nKey("sessions.detail.field.userAgent"),
113
113
  },
@@ -120,7 +120,11 @@ export const sessionMineScreen: ProjectionListScreenDefinition = {
120
120
  type: "projectionList",
121
121
  query: SessionQueries.mine,
122
122
  columns: [
123
- { field: "device", label: i18nKey("sessions.mine.col.userAgent"), renderer: DEVICE_RENDERER },
123
+ {
124
+ field: "deviceLabel",
125
+ label: i18nKey("sessions.mine.col.userAgent"),
126
+ renderer: DEVICE_RENDERER,
127
+ },
124
128
  { field: "ip", label: i18nKey("sessions.mine.col.ip") },
125
129
  {
126
130
  field: "current",
@@ -12,7 +12,7 @@ import * as z from "zod";
12
12
  // _SHORT/_QN pair mirrors cap-counter's rolling-incremented event:
13
13
  // _SHORT — r.defineEvent(short, schema) in feature.ts, framework prefixes
14
14
  // it to the QN below.
15
- // _QN — ctx.unsafeAppendEvent({ type }) / raw append()'s `type` field.
15
+ // _QN — ctx.events.unsafeAppend({ type }) / raw append()'s `type` field.
16
16
  export const SESSION_REVOKED_EVENT_SHORT = "session-revoked" as const;
17
17
  export const SESSION_REVOKED_EVENT_QN = "sessions:event:session-revoked" as const;
18
18
 
@@ -1,19 +1,17 @@
1
- // Column renderer for the parsed `device` of a session row, registered via `sessionsClient()`.
1
+ // Column renderer for session devices, registered via `sessionsClient()`. Takes the server-made
2
+ // `deviceLabel` string, or the parsed `device` object for screens that bind that column.
2
3
 
3
4
  import { type ColumnRendererProps, useTranslation } from "@cosmicdrift/kumiko-renderer";
4
5
  import type { ReactNode } from "react";
5
- import { parsedDeviceSchema } from "./user-agent.ts";
6
+ import { formatDeviceLabel, parsedDeviceSchema } from "./user-agent.ts";
7
+
8
+ function deviceLabelOf(value: unknown): string | null {
9
+ if (typeof value === "string") return value === "" ? null : value;
10
+ const parsed = parsedDeviceSchema.safeParse(value);
11
+ return parsed.success ? formatDeviceLabel(parsed.data) : null;
12
+ }
6
13
 
7
14
  export function SessionDeviceCell({ value }: ColumnRendererProps): ReactNode {
8
15
  const t = useTranslation();
9
- const parsed = parsedDeviceSchema.safeParse(value);
10
- const device = parsed.success ? parsed.data : null;
11
- if (device === null) return t("sessions.device.unknown");
12
- const browser =
13
- device.browser === null
14
- ? null
15
- : device.browserMajor === null
16
- ? device.browser
17
- : `${device.browser} ${device.browserMajor}`;
18
- return [browser, device.os].filter((part) => part !== null).join(" · ");
16
+ return deviceLabelOf(value) ?? t("sessions.device.unknown");
19
17
  }
@@ -56,6 +56,18 @@ const OPERATING_SYSTEM_PATTERNS: readonly {
56
56
  { os: "Linux", pattern: /\bLinux\b/ },
57
57
  ];
58
58
 
59
+ export function formatDeviceLabel(device: ParsedDevice): string | null {
60
+ if (device === null) return null;
61
+ const browser =
62
+ device.browser === null
63
+ ? null
64
+ : device.browserMajor === null
65
+ ? device.browser
66
+ : `${device.browser} ${device.browserMajor}`;
67
+ const parts = [browser, device.os].filter((part) => part !== null);
68
+ return parts.length === 0 ? null : parts.join(" · ");
69
+ }
70
+
59
71
  export function parseUserAgent(userAgent: string | null): ParsedDevice {
60
72
  if (userAgent === null || userAgent === "") return null;
61
73
  let browser: UserAgentBrowser | null = null;
@@ -92,5 +92,20 @@ export {
92
92
  type SignupHandoverProvider,
93
93
  } from "./signup-handover.ts";
94
94
  export { createSingleUseTokenStore, hashSingleUseToken } from "./single-use-token-store.ts";
95
+ export {
96
+ backfillAggregateStreamTenants,
97
+ type StreamBackfillCandidate,
98
+ type StreamBackfillFailure,
99
+ type StreamBackfillOptions,
100
+ type StreamBackfillResult,
101
+ type StreamTenantTarget,
102
+ } from "./stream-tenant-backfill.ts";
103
+ export {
104
+ createSearchBucketCleanup,
105
+ type DerivedStateMode,
106
+ rebuildAndReindex,
107
+ type StreamBackfillStepFailure,
108
+ stepFailures,
109
+ } from "./stream-tenant-derived-state.ts";
95
110
  export type { SystemQueryFn } from "./system-query.ts";
96
111
  export { type BurnResult, burnToken, unburnToken } from "./token-burn-store.ts";
@@ -206,7 +206,12 @@ export async function purgeFilesReachingSubject(args: {
206
206
  }
207
207
  const deleteBytes = await storagePromise;
208
208
  const systemUser = createSystemUser(tenantId);
209
- const tdb = createTenantDb({ db, tenantId, mode: "system" });
209
+ const tdb = createTenantDb({
210
+ db,
211
+ tenantId,
212
+ mode: "system",
213
+ reason: "subject erasure purges file refs in every tenant that holds them",
214
+ });
210
215
 
211
216
  const outcome = await purgeRowFileRefs({
212
217
  db,
@@ -353,7 +358,12 @@ async function purgePendingFileRef(
353
358
  const forgotten = await fileRefExecutor.forget(
354
359
  { id: fileRefId },
355
360
  createSystemUser(tenantId),
356
- createTenantDb({ db, tenantId, mode: "system" }),
361
+ createTenantDb({
362
+ db,
363
+ tenantId,
364
+ mode: "system",
365
+ reason: "subject erasure purges file refs in every tenant that holds them",
366
+ }),
357
367
  );
358
368
  return forgotten.isSuccess
359
369
  ? undefined
@@ -5,14 +5,16 @@ import type {
5
5
  } from "@cosmicdrift/kumiko-framework/engine";
6
6
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
7
7
 
8
- // ctx.forTenant is absent for r.systemScope() handlers and without a db; a write handler that
8
+ // ctx.tenants.writeTarget is absent for r.systemScope() handlers and without a db; a write handler that
9
9
  // needs a cross-tenant target must fail loudly instead of falling back to ctx.db.
10
10
  export function requireForTenant(
11
- ctx: Pick<HandlerContext, "forTenant">,
11
+ ctx: Pick<HandlerContext, "tenants">,
12
12
  targetTenantId: TenantId,
13
13
  ): TenantWriteTarget {
14
- if (!ctx.forTenant) {
15
- throw new InternalError({ message: "ctx.forTenant is not available in this handler context" });
14
+ if (!ctx.tenants.writeTarget) {
15
+ throw new InternalError({
16
+ message: "ctx.tenants.writeTarget is not available in this handler context",
17
+ });
16
18
  }
17
- return ctx.forTenant(targetTenantId);
19
+ return ctx.tenants.writeTarget(targetTenantId);
18
20
  }