@cosmicdrift/kumiko-samples 0.378.0 → 0.379.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (506) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +18 -17
  3. package/packages/bundled-features/src/account-security/feature.ts +2 -2
  4. package/packages/bundled-features/src/account-security/index.ts +8 -8
  5. package/packages/bundled-features/src/account-security/{constants.ts → web/constants.ts} +0 -2
  6. package/packages/bundled-features/src/account-security/{i18n.ts → web/i18n.ts} +0 -1
  7. package/packages/bundled-features/src/admin-shell/feature.ts +10 -9
  8. package/packages/bundled-features/src/admin-shell/index.ts +8 -8
  9. package/packages/bundled-features/src/admin-shell/web/client-plugin.tsx +2 -3
  10. package/packages/bundled-features/src/admin-shell/{constants.ts → web/constants.ts} +0 -1
  11. package/packages/bundled-features/src/admin-shell/web/default-translations.ts +10 -0
  12. package/packages/bundled-features/src/admin-shell/web/i18n.ts +51 -9
  13. package/packages/bundled-features/src/admin-shell/web/index.ts +0 -1
  14. package/packages/bundled-features/src/audit/changes.json +7 -0
  15. package/packages/bundled-features/src/audit/feature.ts +72 -64
  16. package/packages/bundled-features/src/audit/handlers/audit-events.ts +153 -0
  17. package/packages/bundled-features/src/audit/handlers/audit-system-db.ts +13 -0
  18. package/packages/bundled-features/src/audit/handlers/details-all-tenants.query.ts +26 -0
  19. package/packages/bundled-features/src/audit/handlers/details.query.ts +11 -39
  20. package/packages/bundled-features/src/audit/handlers/list-all-tenants.query.ts +47 -0
  21. package/packages/bundled-features/src/audit/handlers/list.query.ts +16 -123
  22. package/packages/bundled-features/src/audit/handlers/resolve-audit-tenant.ts +21 -7
  23. package/packages/bundled-features/src/audit/index.ts +1 -1
  24. package/packages/bundled-features/src/audit/run-escape-hatch-retention.ts +4 -4
  25. package/packages/bundled-features/src/audit/screens.ts +82 -0
  26. package/packages/bundled-features/src/audit/web/client-plugin.tsx +2 -3
  27. package/packages/bundled-features/src/audit/{constants.ts → web/constants.ts} +11 -1
  28. package/packages/bundled-features/src/audit/web/default-translations.ts +7 -0
  29. package/packages/bundled-features/src/audit/web/i18n.ts +33 -7
  30. package/packages/bundled-features/src/audit/web/index.ts +0 -2
  31. package/packages/bundled-features/src/auth-email-password/bootstrap.ts +6 -6
  32. package/packages/bundled-features/src/auth-email-password/changes.json +6 -0
  33. package/packages/bundled-features/src/auth-email-password/errors.ts +1 -1
  34. package/packages/bundled-features/src/auth-email-password/feature.ts +2 -2
  35. package/packages/bundled-features/src/auth-email-password/handlers/confirm-account-unlock.write.ts +1 -1
  36. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +4 -4
  37. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +3 -3
  38. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  39. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +38 -4
  40. package/packages/bundled-features/src/auth-email-password/handlers/request-account-unlock.write.ts +1 -1
  41. package/packages/bundled-features/src/auth-email-password/handlers/request-email-verification.write.ts +1 -1
  42. package/packages/bundled-features/src/auth-email-password/handlers/request-password-reset.write.ts +1 -1
  43. package/packages/bundled-features/src/auth-email-password/handlers/reset-password.write.ts +1 -1
  44. package/packages/bundled-features/src/auth-email-password/handlers/verify-email.write.ts +1 -1
  45. package/packages/bundled-features/src/auth-email-password/index.ts +6 -1
  46. package/packages/bundled-features/src/auth-email-password/mail-notifications.ts +1 -1
  47. package/packages/bundled-features/src/auth-email-password/signup-activation.ts +1 -1
  48. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +0 -1
  49. package/packages/bundled-features/src/auth-email-password/web/auth-form-logic.ts +0 -1
  50. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +0 -1
  51. package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +0 -1
  52. package/packages/bundled-features/src/auth-email-password/web/auth-redirect.ts +0 -1
  53. package/packages/bundled-features/src/auth-email-password/web/client-actions.ts +0 -1
  54. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +1 -2
  55. package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +0 -1
  56. package/packages/bundled-features/src/auth-email-password/{constants.ts → web/constants.ts} +3 -6
  57. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +0 -1
  58. package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +0 -1
  59. package/packages/bundled-features/src/auth-email-password/{i18n.ts → web/i18n.ts} +3 -4
  60. package/packages/bundled-features/src/auth-email-password/web/index.ts +1 -2
  61. package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +2 -3
  62. package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +0 -1
  63. package/packages/bundled-features/src/auth-email-password/{mail-i18n.ts → web/mail-i18n.ts} +0 -1
  64. package/packages/bundled-features/src/auth-email-password/web/request-account-unlock-screen.tsx +0 -1
  65. package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +0 -1
  66. package/packages/bundled-features/src/auth-email-password/web/session-bootstrap-error.tsx +0 -1
  67. package/packages/bundled-features/src/auth-email-password/web/session.tsx +0 -1
  68. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +2 -3
  69. package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +0 -1
  70. package/packages/bundled-features/src/auth-email-password/web/tenant-menu-items.tsx +0 -1
  71. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +0 -1
  72. package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +0 -1
  73. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +0 -1
  74. package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +0 -1
  75. package/packages/bundled-features/src/auth-mfa/changes.json +6 -0
  76. package/packages/bundled-features/src/auth-mfa/errors.ts +2 -2
  77. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +1 -1
  78. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  79. package/packages/bundled-features/src/auth-mfa/handlers/enable-start.write.ts +1 -1
  80. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  81. package/packages/bundled-features/src/auth-mfa/index.ts +8 -8
  82. package/packages/bundled-features/src/auth-mfa/mfa-status-checker.ts +4 -4
  83. package/packages/bundled-features/src/auth-mfa/screens.ts +1 -1
  84. package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +0 -1
  85. package/packages/bundled-features/src/auth-mfa/{constants.ts → web/constants.ts} +0 -1
  86. package/packages/bundled-features/src/auth-mfa/web/i18n.ts +0 -1
  87. package/packages/bundled-features/src/auth-mfa/web/index.ts +0 -1
  88. package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +0 -1
  89. package/packages/bundled-features/src/auth-mfa/web/mfa-disable-dialog.tsx +1 -2
  90. package/packages/bundled-features/src/auth-mfa/web/mfa-recovery-codes-reveal.tsx +0 -1
  91. package/packages/bundled-features/src/auth-mfa/web/mfa-regenerate-recovery-dialog.tsx +1 -2
  92. package/packages/bundled-features/src/auth-mfa/web/mfa-setup-preauth-screen.tsx +21 -23
  93. package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +0 -1
  94. package/packages/bundled-features/src/billing-foundation/changes.json +18 -0
  95. package/packages/bundled-features/src/billing-foundation/checkout-core.ts +3 -3
  96. package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-text.ts +2 -2
  97. package/packages/bundled-features/src/billing-foundation/consumer-protection/issue-confirmation.ts +11 -3
  98. package/packages/bundled-features/src/billing-foundation/consumer-protection/mail-notifications.ts +11 -1
  99. package/packages/bundled-features/src/billing-foundation/consumer-protection/register-consent.ts +1 -1
  100. package/packages/bundled-features/src/billing-foundation/consumer-protection/register-termination.ts +12 -1
  101. package/packages/bundled-features/src/billing-foundation/consumer-protection/stored-user-email.ts +12 -0
  102. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-mail.ts +6 -1
  103. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-notify.ts +1 -1
  104. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +167 -28
  105. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-record.ts +102 -3
  106. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-request.ts +43 -12
  107. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-revoke.ts +202 -0
  108. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-texts.ts +70 -0
  109. package/packages/bundled-features/src/billing-foundation/events.ts +20 -2
  110. package/packages/bundled-features/src/billing-foundation/feature.ts +5 -5
  111. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +82 -9
  112. package/packages/bundled-features/src/billing-foundation/handlers/switch-plan.write.ts +1 -1
  113. package/packages/bundled-features/src/billing-foundation/handlers/sync-subscription.write.ts +1 -1
  114. package/packages/bundled-features/src/billing-foundation/index.ts +27 -27
  115. package/packages/bundled-features/src/billing-foundation/plan-catalog.ts +7 -7
  116. package/packages/bundled-features/src/billing-foundation/screens.ts +1 -1
  117. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +1 -1
  118. package/packages/bundled-features/src/billing-foundation/types.ts +17 -3
  119. package/packages/bundled-features/src/billing-foundation/validate-options.ts +3 -3
  120. package/packages/bundled-features/src/billing-foundation/web/billing-contact-plan.tsx +1 -3
  121. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +5 -7
  122. package/packages/bundled-features/src/billing-foundation/web/cancel-contract-dialog.tsx +1 -3
  123. package/packages/bundled-features/src/billing-foundation/web/checkout-consent-dialog.tsx +1 -3
  124. package/packages/bundled-features/src/billing-foundation/web/client-plugin.tsx +1 -2
  125. package/packages/bundled-features/src/billing-foundation/{constants.ts → web/constants.ts} +37 -31
  126. package/packages/bundled-features/src/billing-foundation/{consumer-protection → web/consumer-protection}/consent-locale.ts +0 -1
  127. package/packages/bundled-features/src/billing-foundation/{contact-card.ts → web/contact-card.ts} +0 -2
  128. package/packages/bundled-features/src/billing-foundation/web/index.ts +14 -15
  129. package/packages/bundled-features/src/billing-foundation/web/localized-params.ts +0 -2
  130. package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +5 -2
  131. package/packages/bundled-features/src/cap-overview/feature.ts +1 -1
  132. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -1
  133. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -2
  134. package/packages/bundled-features/src/cap-overview/index.ts +9 -9
  135. package/packages/bundled-features/src/cap-overview/screens.ts +2 -2
  136. package/packages/bundled-features/src/cap-overview/web/cap-cards-panel.tsx +1 -2
  137. package/packages/bundled-features/src/cap-overview/web/cap-usage-bar.tsx +1 -2
  138. package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +0 -2
  139. package/packages/bundled-features/src/cap-overview/web/client-plugin.tsx +3 -4
  140. package/packages/bundled-features/src/cap-overview/{constants.ts → web/constants.ts} +0 -1
  141. package/packages/bundled-features/src/cap-overview/web/index.ts +0 -1
  142. package/packages/bundled-features/src/cap-overview/{usage-math.ts → web/usage-math.ts} +1 -2
  143. package/packages/bundled-features/src/compliance-profiles/feature.ts +5 -5
  144. package/packages/bundled-features/src/compliance-profiles/index.ts +6 -6
  145. package/packages/bundled-features/src/compliance-profiles/web/client-plugin.tsx +2 -3
  146. package/packages/bundled-features/src/compliance-profiles/web/compliance-profile-catalog.tsx +1 -2
  147. package/packages/bundled-features/src/compliance-profiles/{constants.ts → web/constants.ts} +0 -1
  148. package/packages/bundled-features/src/compliance-profiles/web/i18n.ts +0 -1
  149. package/packages/bundled-features/src/compliance-profiles/web/index.ts +0 -1
  150. package/packages/bundled-features/src/config/index.ts +6 -6
  151. package/packages/bundled-features/src/config/web/client-plugin.ts +1 -2
  152. package/packages/bundled-features/src/config/{constants.ts → web/constants.ts} +0 -1
  153. package/packages/bundled-features/src/config/web/i18n.ts +0 -1
  154. package/packages/bundled-features/src/config/web/index.ts +1 -3
  155. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  156. package/packages/bundled-features/src/custom-fields/feature.ts +8 -8
  157. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +1 -1
  158. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +1 -1
  159. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +1 -1
  160. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +4 -4
  161. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
  162. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +1 -1
  163. package/packages/bundled-features/src/custom-fields/index.ts +8 -8
  164. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +1 -1
  165. package/packages/bundled-features/src/custom-fields/schemas.ts +1 -1
  166. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +1 -2
  167. package/packages/bundled-features/src/custom-fields/{constants.ts → web/constants.ts} +18 -19
  168. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +1 -2
  169. package/packages/bundled-features/src/custom-fields/web/i18n.ts +0 -1
  170. package/packages/bundled-features/src/custom-fields/web/index.ts +2 -3
  171. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +1 -2
  172. package/packages/bundled-features/src/delivery/address-opt-out.ts +1 -1
  173. package/packages/bundled-features/src/delivery/attempt-log-retention.ts +24 -8
  174. package/packages/bundled-features/src/delivery/changes.json +6 -0
  175. package/packages/bundled-features/src/delivery/constants.ts +2 -2
  176. package/packages/bundled-features/src/delivery/i18n.ts +1 -1
  177. package/packages/bundled-features/src/delivery/unsubscribe-page.ts +1 -1
  178. package/packages/bundled-features/src/delivery/web/client-plugin.tsx +6 -7
  179. package/packages/bundled-features/src/delivery/web/delivery-channel-cell.tsx +0 -1
  180. package/packages/bundled-features/src/delivery/web/delivery-error-cell.tsx +0 -1
  181. package/packages/bundled-features/src/delivery/web/delivery-status-cell.tsx +1 -2
  182. package/packages/bundled-features/src/delivery/web/delivery-time-cell.tsx +0 -1
  183. package/packages/bundled-features/src/delivery/web/delivery-type-cell.tsx +0 -1
  184. package/packages/bundled-features/src/delivery/web/index.ts +0 -1
  185. package/packages/bundled-features/src/delivery/{public-names.ts → web/public-names.ts} +0 -1
  186. package/packages/bundled-features/src/document-ingest-foundation/changes.json +6 -0
  187. package/packages/bundled-features/src/document-ingest-foundation/events.ts +4 -0
  188. package/packages/bundled-features/src/document-ingest-foundation/executor.ts +2 -1
  189. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +18 -4
  190. package/packages/bundled-features/src/document-ingest-foundation/index.ts +1 -0
  191. package/packages/bundled-features/src/feature-toggles/feature.ts +7 -7
  192. package/packages/bundled-features/src/feature-toggles/handlers/list.query.ts +1 -1
  193. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +1 -1
  194. package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -3
  195. package/packages/bundled-features/src/feature-toggles/index.ts +6 -6
  196. package/packages/bundled-features/src/feature-toggles/web/client-plugin.tsx +1 -2
  197. package/packages/bundled-features/src/feature-toggles/{constants.ts → web/constants.ts} +0 -1
  198. package/packages/bundled-features/src/feature-toggles/web/i18n.ts +0 -1
  199. package/packages/bundled-features/src/feature-toggles/web/index.ts +0 -1
  200. package/packages/bundled-features/src/files/changes.json +7 -0
  201. package/packages/bundled-features/src/folders/feature.ts +1 -1
  202. package/packages/bundled-features/src/folders/handlers/clear-folder.write.ts +1 -1
  203. package/packages/bundled-features/src/folders/handlers/delete-folder.write.ts +1 -1
  204. package/packages/bundled-features/src/folders/handlers/set-folder.write.ts +1 -1
  205. package/packages/bundled-features/src/folders/index.ts +8 -8
  206. package/packages/bundled-features/src/folders/web/client-plugin.tsx +1 -3
  207. package/packages/bundled-features/src/folders/{constants.ts → web/constants.ts} +0 -1
  208. package/packages/bundled-features/src/folders/web/folder-manager.tsx +1 -2
  209. package/packages/bundled-features/src/folders/web/folder-section.tsx +1 -2
  210. package/packages/bundled-features/src/folders/web/i18n.ts +0 -1
  211. package/packages/bundled-features/src/folders/web/index.ts +1 -2
  212. package/packages/bundled-features/src/folders/web/tree.ts +0 -1
  213. package/packages/bundled-features/src/form-draft/changes.json +7 -0
  214. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +25 -11
  215. package/packages/bundled-features/src/form-draft/decrypt-draft.ts +24 -0
  216. package/packages/bundled-features/src/form-draft/entity.ts +6 -9
  217. package/packages/bundled-features/src/form-draft/feature.ts +1 -1
  218. package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +26 -5
  219. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  220. package/packages/bundled-features/src/form-draft/handlers/get.query.ts +6 -7
  221. package/packages/bundled-features/src/form-draft/handlers/list.query.ts +13 -7
  222. package/packages/bundled-features/src/form-draft/handlers/save.write.ts +5 -5
  223. package/packages/bundled-features/src/form-draft/index.ts +8 -8
  224. package/packages/bundled-features/src/form-draft/lookup.ts +10 -4
  225. package/packages/bundled-features/src/form-draft/schemas.ts +1 -1
  226. package/packages/bundled-features/src/form-draft/{constants.ts → web/constants.ts} +0 -1
  227. package/packages/bundled-features/src/form-draft-user-data/hooks.ts +2 -2
  228. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +10 -10
  229. package/packages/bundled-features/src/jobs/feature.ts +7 -7
  230. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  231. package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +1 -1
  232. package/packages/bundled-features/src/jobs/index.ts +1 -1
  233. package/packages/bundled-features/src/jobs/web/client-plugin.tsx +2 -3
  234. package/packages/bundled-features/src/jobs/{constants.ts → web/constants.ts} +0 -1
  235. package/packages/bundled-features/src/jobs/web/default-translations.ts +7 -0
  236. package/packages/bundled-features/src/jobs/web/i18n.ts +53 -7
  237. package/packages/bundled-features/src/jobs/web/index.ts +0 -1
  238. package/packages/bundled-features/src/ledger/changes.json +7 -0
  239. package/packages/bundled-features/src/ledger/entity.ts +1 -1
  240. package/packages/bundled-features/src/ledger/feature.ts +1 -1
  241. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +2 -10
  242. package/packages/bundled-features/src/ledger/handlers/create-transaction.write.ts +1 -1
  243. package/packages/bundled-features/src/ledger/handlers/reports.query.ts +1 -1
  244. package/packages/bundled-features/src/ledger/handlers/reverse-transaction.write.ts +1 -1
  245. package/packages/bundled-features/src/ledger/index.ts +13 -13
  246. package/packages/bundled-features/src/ledger/recurring.ts +1 -1
  247. package/packages/bundled-features/src/ledger/reports.ts +1 -1
  248. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  249. package/packages/bundled-features/src/ledger/{constants.ts → web/constants.ts} +0 -1
  250. package/packages/bundled-features/src/ledger/web/index.ts +11 -12
  251. package/packages/bundled-features/src/legal-pages/README.md +1 -1
  252. package/packages/bundled-features/src/legal-pages/feature.ts +5 -5
  253. package/packages/bundled-features/src/legal-pages/index.ts +11 -11
  254. package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +1 -1
  255. package/packages/bundled-features/src/legal-pages/lib/validate-routes.ts +1 -1
  256. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +1 -2
  257. package/packages/bundled-features/src/legal-pages/{constants.ts → web/constants.ts} +6 -8
  258. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -1
  259. package/packages/bundled-features/src/managed-pages/feature.ts +1 -1
  260. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +1 -2
  261. package/packages/bundled-features/src/managed-pages/web/default-translations.ts +17 -0
  262. package/packages/bundled-features/src/managed-pages/web/i18n.ts +59 -16
  263. package/packages/bundled-features/src/managed-pages/web/index.ts +1 -2
  264. package/packages/bundled-features/src/metrics/compute.ts +1 -1
  265. package/packages/bundled-features/src/metrics/feature.ts +6 -6
  266. package/packages/bundled-features/src/metrics/index.ts +8 -8
  267. package/packages/bundled-features/src/metrics/types.ts +1 -1
  268. package/packages/bundled-features/src/metrics/validate.ts +1 -1
  269. package/packages/bundled-features/src/metrics/{constants.ts → web/constants.ts} +0 -1
  270. package/packages/bundled-features/src/metrics/window.ts +1 -1
  271. package/packages/bundled-features/src/notes-history/feature.ts +1 -1
  272. package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
  273. package/packages/bundled-features/src/notes-history/index.ts +8 -8
  274. package/packages/bundled-features/src/notes-history/web/client-plugin.tsx +1 -3
  275. package/packages/bundled-features/src/notes-history/{constants.ts → web/constants.ts} +0 -1
  276. package/packages/bundled-features/src/notes-history/web/i18n.ts +0 -1
  277. package/packages/bundled-features/src/notes-history/web/index.ts +2 -3
  278. package/packages/bundled-features/src/notes-history/web/notes-section.tsx +2 -3
  279. package/packages/bundled-features/src/personal-access-tokens/feature.ts +12 -10
  280. package/packages/bundled-features/src/personal-access-tokens/handlers/available-scopes.query.ts +1 -1
  281. package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
  282. package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
  283. package/packages/bundled-features/src/personal-access-tokens/hash.ts +1 -1
  284. package/packages/bundled-features/src/personal-access-tokens/i18n.ts +2 -2
  285. package/packages/bundled-features/src/personal-access-tokens/index.ts +5 -5
  286. package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
  287. package/packages/bundled-features/src/personal-access-tokens/schema/api-token.ts +1 -1
  288. package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -2
  289. package/packages/bundled-features/src/personal-access-tokens/{constants.ts → web/constants.ts} +0 -1
  290. package/packages/bundled-features/src/personal-access-tokens/{scopes.ts → web/scopes.ts} +0 -1
  291. package/packages/bundled-features/src/presets/changes.json +7 -0
  292. package/packages/bundled-features/src/presets/index.ts +0 -1
  293. package/packages/bundled-features/src/presets/security-baseline.ts +1 -1
  294. package/packages/bundled-features/src/renderer-foundation/types.ts +1 -1
  295. package/packages/bundled-features/src/secrets/feature.ts +1 -1
  296. package/packages/bundled-features/src/secrets/handlers/delete.write.ts +1 -1
  297. package/packages/bundled-features/src/secrets/handlers/list.query.ts +1 -1
  298. package/packages/bundled-features/src/secrets/handlers/set.write.ts +1 -1
  299. package/packages/bundled-features/src/secrets/i18n.ts +1 -1
  300. package/packages/bundled-features/src/secrets/index.ts +8 -8
  301. package/packages/bundled-features/src/secrets/{constants.ts → web/constants.ts} +0 -1
  302. package/packages/bundled-features/src/secrets/write-gate.ts +1 -1
  303. package/packages/bundled-features/src/sessions/feature.ts +7 -4
  304. package/packages/bundled-features/src/sessions/{i18n.ts → web/i18n.ts} +0 -1
  305. package/packages/bundled-features/src/shared/index.ts +6 -1
  306. package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +10 -2
  307. package/packages/bundled-features/src/shared/web/translate-or-raw.ts +0 -1
  308. package/packages/bundled-features/src/subscription-stripe/feature.ts +2 -0
  309. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +19 -0
  310. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +1 -0
  311. package/packages/bundled-features/src/tags/changes.json +6 -0
  312. package/packages/bundled-features/src/tags/feature.ts +1 -1
  313. package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +11 -7
  314. package/packages/bundled-features/src/tags/handlers/create-tag.write.ts +1 -1
  315. package/packages/bundled-features/src/tags/handlers/delete-tag.write.ts +4 -1
  316. package/packages/bundled-features/src/tags/handlers/remove-tag.write.ts +1 -1
  317. package/packages/bundled-features/src/tags/handlers/update-tag.write.ts +1 -1
  318. package/packages/bundled-features/src/tags/index.ts +12 -12
  319. package/packages/bundled-features/src/tags/screens.ts +1 -1
  320. package/packages/bundled-features/src/tags/web/client-plugin.tsx +1 -3
  321. package/packages/bundled-features/src/tags/{constants.ts → web/constants.ts} +4 -1
  322. package/packages/bundled-features/src/tags/web/entity-tags.tsx +1 -2
  323. package/packages/bundled-features/src/tags/web/i18n.ts +2 -2
  324. package/packages/bundled-features/src/tags/web/index.ts +2 -3
  325. package/packages/bundled-features/src/tags/web/tag-chip.tsx +0 -1
  326. package/packages/bundled-features/src/tags/web/tag-filter.tsx +1 -2
  327. package/packages/bundled-features/src/tags/web/tag-manager.tsx +5 -4
  328. package/packages/bundled-features/src/tags/web/tag-picker.tsx +0 -1
  329. package/packages/bundled-features/src/tags/web/tag-section.tsx +1 -2
  330. package/packages/bundled-features/src/tags/web/tags-cell.tsx +1 -2
  331. package/packages/bundled-features/src/template-resolver/README.md +1 -1
  332. package/packages/bundled-features/src/template-resolver/api.ts +75 -28
  333. package/packages/bundled-features/src/template-resolver/changes.json +43 -0
  334. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +1 -1
  335. package/packages/bundled-features/src/template-resolver/compile-steps-block.ts +2 -2
  336. package/packages/bundled-features/src/template-resolver/document-ops.ts +5 -5
  337. package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +4 -4
  338. package/packages/bundled-features/src/template-resolver/feature.ts +13 -4
  339. package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +6 -1
  340. package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +6 -2
  341. package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
  342. package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -1
  343. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +19 -2
  344. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +2 -2
  345. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +7 -1
  346. package/packages/bundled-features/src/template-resolver/handlers/discard-draft.write.ts +1 -1
  347. package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +8 -2
  348. package/packages/bundled-features/src/template-resolver/handlers/document-blocks.query.ts +2 -2
  349. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +5 -2
  350. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +4 -2
  351. package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +10 -5
  352. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +5 -2
  353. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +68 -10
  354. package/packages/bundled-features/src/template-resolver/handlers/patch-draft.write.ts +1 -1
  355. package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +1 -1
  356. package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +1 -1
  357. package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +2 -2
  358. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +1 -1
  359. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +1 -1
  360. package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +6 -6
  361. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +2 -2
  362. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +8 -2
  363. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +4 -2
  364. package/packages/bundled-features/src/template-resolver/i18n.ts +25 -0
  365. package/packages/bundled-features/src/template-resolver/index.ts +60 -59
  366. package/packages/bundled-features/src/template-resolver/layout-appearance.ts +1 -1
  367. package/packages/bundled-features/src/template-resolver/layout-regions.ts +1 -1
  368. package/packages/bundled-features/src/template-resolver/seeding.ts +16 -7
  369. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +2 -2
  370. package/packages/bundled-features/src/template-resolver/table.ts +1 -1
  371. package/packages/bundled-features/src/template-resolver/template-bundle.ts +2 -2
  372. package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +82 -0
  373. package/packages/bundled-features/src/template-resolver/template-draft.ts +1 -1
  374. package/packages/bundled-features/src/template-resolver/template-edit-policy.ts +2 -2
  375. package/packages/bundled-features/src/template-resolver/template-meta.ts +2 -2
  376. package/packages/bundled-features/src/template-resolver/template-preview.ts +14 -10
  377. package/packages/bundled-features/src/template-resolver/template-usage.ts +1 -1
  378. package/packages/bundled-features/src/template-resolver/template-validation.ts +2 -2
  379. package/packages/bundled-features/src/template-resolver/testing.ts +2 -2
  380. package/packages/bundled-features/src/template-resolver/user-content-table.ts +1 -1
  381. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +4 -5
  382. package/packages/bundled-features/src/template-resolver/{constants.ts → web/constants.ts} +7 -10
  383. package/packages/bundled-features/src/template-resolver/{document-blocks.ts → web/document-blocks.ts} +0 -1
  384. package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +2 -3
  385. package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +0 -1
  386. package/packages/bundled-features/src/template-resolver/{document-images.ts → web/document-images.ts} +0 -1
  387. package/packages/bundled-features/src/template-resolver/{document-schema.ts → web/document-schema.ts} +0 -1
  388. package/packages/bundled-features/src/template-resolver/{document-steps.ts → web/document-steps.ts} +0 -1
  389. package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +6 -7
  390. package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +2 -3
  391. package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +1 -2
  392. package/packages/bundled-features/src/template-resolver/web/i18n.ts +2 -1
  393. package/packages/bundled-features/src/template-resolver/web/index.ts +13 -14
  394. package/packages/bundled-features/src/template-resolver/{mail-constants.ts → web/mail-constants.ts} +0 -1
  395. package/packages/bundled-features/src/template-resolver/{pdf-constants.ts → web/pdf-constants.ts} +0 -1
  396. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +0 -1
  397. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +5 -4
  398. package/packages/bundled-features/src/template-resolver/{placeholder-text.ts → web/placeholder-text.ts} +0 -1
  399. package/packages/bundled-features/src/template-resolver/{qualified-names.ts → web/qualified-names.ts} +0 -1
  400. package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +0 -1
  401. package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -1
  402. package/packages/bundled-features/src/tenant/index.ts +7 -7
  403. package/packages/bundled-features/src/tenant/invitation-table.ts +1 -1
  404. package/packages/bundled-features/src/tenant/invited-membership.ts +1 -1
  405. package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -1
  406. package/packages/bundled-features/src/tenant/member-role-options.ts +1 -1
  407. package/packages/bundled-features/src/tenant/screens.ts +2 -2
  408. package/packages/bundled-features/src/tenant/web/client-plugin.tsx +1 -2
  409. package/packages/bundled-features/src/tenant/{constants.ts → web/constants.ts} +3 -6
  410. package/packages/bundled-features/src/tenant/web/index.ts +0 -1
  411. package/packages/bundled-features/src/tenant/web/member-roles-cell.tsx +0 -1
  412. package/packages/bundled-features/src/tenant/web/member-status-cell.tsx +0 -1
  413. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +2 -2
  414. package/packages/bundled-features/src/tier-engine/entity.ts +1 -1
  415. package/packages/bundled-features/src/tier-engine/feature.ts +7 -7
  416. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +1 -1
  417. package/packages/bundled-features/src/tier-engine/index.ts +8 -8
  418. package/packages/bundled-features/src/tier-engine/web/client-plugin.tsx +2 -3
  419. package/packages/bundled-features/src/tier-engine/{constants.ts → web/constants.ts} +2 -3
  420. package/packages/bundled-features/src/tier-engine/{i18n.ts → web/i18n.ts} +0 -1
  421. package/packages/bundled-features/src/tier-engine/web/index.ts +0 -1
  422. package/packages/bundled-features/src/user/handlers/create.write.ts +1 -1
  423. package/packages/bundled-features/src/user/handlers/update-roles.ts +1 -1
  424. package/packages/bundled-features/src/user/handlers/update.write.ts +1 -1
  425. package/packages/bundled-features/src/user/index.ts +1 -1
  426. package/packages/bundled-features/src/user/invited-global-roles.ts +1 -1
  427. package/packages/bundled-features/src/user/schema/user.ts +1 -1
  428. package/packages/bundled-features/src/user/{constants.ts → web/constants.ts} +0 -1
  429. package/packages/bundled-features/src/user-data-rights/changes.json +14 -0
  430. package/packages/bundled-features/src/user-data-rights/env.ts +1 -1
  431. package/packages/bundled-features/src/user-data-rights/feature.ts +9 -9
  432. package/packages/bundled-features/src/user-data-rights/index.ts +1 -1
  433. package/packages/bundled-features/src/user-data-rights/lib/resolve-tenant-model.ts +1 -1
  434. package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +1 -1
  435. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +2 -3
  436. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +0 -1
  437. package/packages/bundled-features/src/user-data-rights/{constants.ts → web/constants.ts} +11 -12
  438. package/packages/bundled-features/src/user-data-rights/web/default-translations.ts +91 -0
  439. package/packages/bundled-features/src/user-data-rights/web/i18n.ts +41 -91
  440. package/packages/bundled-features/src/user-data-rights/web/index.ts +1 -2
  441. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +1 -2
  442. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +0 -1
  443. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +0 -1
  444. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +10 -1
  445. package/packages/bundled-features/src/user-profile/feature.ts +2 -2
  446. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +1 -1
  447. package/packages/bundled-features/src/user-profile/index.ts +3 -2
  448. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +2 -3
  449. package/packages/bundled-features/src/user-profile/{constants.ts → web/constants.ts} +0 -1
  450. package/packages/bundled-features/src/user-profile/{i18n.ts → web/i18n.ts} +0 -1
  451. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -3
  452. package/packages/bundled-features/src/waitlist/changes.json +6 -0
  453. package/packages/bundled-features/src/waitlist/entity.ts +1 -1
  454. package/packages/bundled-features/src/waitlist/feature.ts +5 -5
  455. package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +3 -3
  456. package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +5 -1
  457. package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
  458. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +3 -3
  459. package/packages/bundled-features/src/waitlist/import.ts +1 -1
  460. package/packages/bundled-features/src/waitlist/index.ts +11 -11
  461. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +1 -1
  462. package/packages/bundled-features/src/waitlist/link-on-signup.ts +1 -1
  463. package/packages/bundled-features/src/waitlist/mail.ts +7 -6
  464. package/packages/bundled-features/src/waitlist/payloads.ts +1 -1
  465. package/packages/bundled-features/src/waitlist/screens.ts +1 -1
  466. package/packages/bundled-features/src/waitlist/{constants.ts → web/constants.ts} +0 -1
  467. package/samples/apps/styleguide/src/features/content/web.tsx +0 -1
  468. package/samples/apps/ui-walkthrough/src/app/client.tsx +2 -0
  469. package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +17 -1
  470. package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +11 -0
  471. package/samples/apps/ui-walkthrough/src/app/server.ts +2 -1
  472. package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +35 -7
  473. package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +6 -0
  474. package/samples/apps/ui-walkthrough/src/features/rental/entities.ts +27 -0
  475. package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +61 -7
  476. package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +48 -24
  477. package/samples/apps/ui-walkthrough/src/features/rental/invoice-receive.ts +0 -1
  478. package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +17 -1
  479. package/samples/apps/ui-walkthrough/src/features/rental/qualified-names.ts +3 -0
  480. package/samples/apps/ui-walkthrough/src/features/rental/receipts-upload.ts +70 -0
  481. package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +90 -13
  482. package/samples/apps/ui-walkthrough/src/features/rental/web/index.ts +0 -2
  483. package/samples/apps/ui-walkthrough/src/features/subscription-plans/feature.ts +103 -0
  484. package/samples/apps/ui-walkthrough/src/features/subscription-plans/i18n.ts +36 -0
  485. package/samples/apps/ui-walkthrough/src/features/subscription-plans/index.ts +2 -0
  486. package/samples/apps/ui-walkthrough/src/features/subscription-plans/seed.ts +21 -0
  487. package/samples/apps/ui-walkthrough/src/run-config.ts +11 -0
  488. package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +1 -1
  489. package/samples/apps/use-all-bundled/feature-manifest.json +4 -4
  490. package/samples/apps/use-all-bundled/scripts/check-coverage.ts +1 -1
  491. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +3 -1
  492. package/samples/recipes/compose-stacks/README.md +1 -2
  493. package/samples/recipes/embedded/README.md +5 -5
  494. package/samples/recipes/embedded/src/handlers/invoice-receive.write.ts +0 -1
  495. package/samples/recipes/embedded/src/screens/invoice-receive.screen.ts +9 -12
  496. package/samples/recipes/legal-pages/README.md +2 -2
  497. package/samples/recipes/legal-pages/src/feature.ts +1 -1
  498. package/samples/recipes/reference-data/src/feature.ts +3 -7
  499. package/packages/bundled-features/src/admin-shell/i18n.ts +0 -54
  500. package/packages/bundled-features/src/audit/i18n.ts +0 -25
  501. package/packages/bundled-features/src/auth-mfa/web/qrcode-browser.d.ts +0 -11
  502. package/packages/bundled-features/src/jobs/i18n.ts +0 -55
  503. package/packages/bundled-features/src/managed-pages/i18n.ts +0 -63
  504. package/packages/bundled-features/src/presets/dsgvo-self-service.ts +0 -35
  505. package/packages/bundled-features/src/user-data-rights/i18n.ts +0 -44
  506. package/samples/apps/ui-walkthrough/src/features/rental/web/upload-standard-layout.tsx +0 -61
@@ -0,0 +1,153 @@
1
+ // Query building and row mapping shared by every audit read handler, so the own-tenant
2
+ // and the all-tenants variants cannot drift apart. The tenant condition is the only part
3
+ // that differs per handler and is passed in.
4
+ //
5
+ // Event payloads hold PII as subject-KMS ciphertext; it is replaced by
6
+ // REDACTED_PII_PLACEHOLDER before returning (payload and metadata), since the API leak guard refuses ciphertext.
7
+
8
+ import { selectMany, type TenantDb, type WhereObject } from "@cosmicdrift/kumiko-framework/db";
9
+ import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
10
+ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
11
+ import * as z from "zod";
12
+ import { redactPiiCiphertext } from "../../shared/index.ts";
13
+
14
+ const MAX_LIMIT = 100;
15
+
16
+ // At most 18 digits keeps the id inside bigint, so an oversized cursor or id is a 422, not a 500.
17
+ const CURSOR_PATTERN = /^\d{1,18}$/;
18
+
19
+ export const auditListPayloadShape = {
20
+ cursor: z.string().regex(CURSOR_PATTERN, "cursor must be a positive integer").optional(),
21
+ before: z.string().regex(CURSOR_PATTERN, "cursor must be a positive integer").optional(),
22
+ search: z.string().trim().optional(),
23
+ limit: z.number().int().min(1).max(MAX_LIMIT).default(50),
24
+ aggregateType: z.string().optional(),
25
+ aggregateId: z.uuid().optional(),
26
+ eventType: z.string().optional(),
27
+ userId: z.string().optional(),
28
+ sort: z.enum(["createdAt", "type"]).optional(),
29
+ sortDirection: z.enum(["asc", "desc"]).optional(),
30
+ from: z.iso.datetime().optional(),
31
+ to: z.iso.datetime().optional(),
32
+ } as const;
33
+
34
+ export const auditEventIdSchema = z
35
+ .string()
36
+ .regex(/^[1-9]\d{0,17}$/, "id must be a positive integer");
37
+
38
+ export const AUDIT_DATE_RANGE_CHECK = {
39
+ isValid: (v: { from?: string | undefined; to?: string | undefined }): boolean =>
40
+ !v.from || !v.to || v.from <= v.to,
41
+ params: {
42
+ message: "`from` must be less than or equal to `to`",
43
+ path: ["from"],
44
+ },
45
+ };
46
+
47
+ function buildDateRange(
48
+ from: string | undefined,
49
+ to: string | undefined,
50
+ ): { gte?: unknown; lte?: unknown } | null {
51
+ if (!from && !to) return null;
52
+ const range: { gte?: unknown; lte?: unknown } = {};
53
+ if (from) range.gte = Temporal.Instant.from(from);
54
+ if (to) range.lte = Temporal.Instant.from(to);
55
+ return range;
56
+ }
57
+
58
+ function escapeLikePattern(value: string): string {
59
+ return value.replace(/[\\%_]/g, (m) => `\\${m}`);
60
+ }
61
+
62
+ export type AuditListFilters = {
63
+ aggregateType?: string | undefined;
64
+ aggregateId?: string | undefined;
65
+ eventType?: string | undefined;
66
+ search?: string | undefined;
67
+ userId?: string | undefined;
68
+ from?: string | undefined;
69
+ to?: string | undefined;
70
+ cursor?: string | undefined;
71
+ before?: string | undefined;
72
+ };
73
+
74
+ /** `tenantCondition` is a tenant id, or an operator object for reads across tenants. */
75
+ export function buildAuditWhere(
76
+ tenantCondition: unknown,
77
+ p: AuditListFilters,
78
+ direction: "asc" | "desc",
79
+ ): WhereObject {
80
+ const where: WhereObject = { tenantId: tenantCondition };
81
+ if (p.aggregateType) where["aggregateType"] = p.aggregateType;
82
+ if (p.aggregateId) where["aggregateId"] = p.aggregateId;
83
+ if (p.eventType) where["type"] = p.eventType;
84
+ else if (p.search) where["type"] = { like: `%${escapeLikePattern(p.search)}%` };
85
+ if (p.userId) where["createdBy"] = p.userId;
86
+ const range = buildDateRange(p.from, p.to);
87
+ if (range) where["createdAt"] = range;
88
+ const cursor = p.cursor ?? p.before;
89
+ // The cursor is an event id, so it only walks pages in id order: ascending
90
+ // pages continue past it, descending pages stop before it.
91
+ if (cursor) where["id"] = direction === "asc" ? { gt: BigInt(cursor) } : { lt: BigInt(cursor) };
92
+ return where;
93
+ }
94
+
95
+ type AuditEventRow = {
96
+ id: bigint;
97
+ tenantId: string;
98
+ aggregateId: string;
99
+ aggregateType: string;
100
+ version: number;
101
+ type: string;
102
+ payload: Record<string, unknown>;
103
+ metadata: Record<string, unknown>;
104
+ createdAt: unknown;
105
+ createdBy: string;
106
+ };
107
+
108
+ export function serializeAuditEvent(r: AuditEventRow) {
109
+ return {
110
+ id: String(r.id),
111
+ tenantId: r.tenantId,
112
+ aggregateId: r.aggregateId,
113
+ aggregateType: r.aggregateType,
114
+ version: r.version,
115
+ type: r.type,
116
+ payload: redactPiiCiphertext(r.payload),
117
+ metadata: redactPiiCiphertext(r.metadata),
118
+ createdAt: r.createdAt,
119
+ createdBy: r.createdBy,
120
+ };
121
+ }
122
+
123
+ export async function loadAuditEvent(db: TenantDb, where: WhereObject) {
124
+ const rows = await selectMany<AuditEventRow>(db, eventsTable, where, { limit: 1 });
125
+ const row = rows[0];
126
+ return row === undefined ? null : serializeAuditEvent(row);
127
+ }
128
+
129
+ export async function listAuditEvents(
130
+ db: TenantDb,
131
+ where: WhereObject,
132
+ p: { limit: number; sort?: "createdAt" | "type" | undefined },
133
+ direction: "asc" | "desc",
134
+ ) {
135
+ const rows = await selectMany<AuditEventRow>(db, eventsTable, where, {
136
+ // The id cursor only resumes an id-ordered listing. created_at comes from the
137
+ // transaction start and can run against insert order, so ordering by it would let
138
+ // a page boundary skip rows; only the type sort leaves id order (and is one page).
139
+ orderBy:
140
+ p.sort === "type"
141
+ ? [
142
+ { col: "type", direction },
143
+ { col: "id", direction },
144
+ ]
145
+ : [{ col: "id", direction }],
146
+ limit: p.limit,
147
+ });
148
+ const serialised = rows.map(serializeAuditEvent);
149
+ const last = serialised[serialised.length - 1];
150
+ // An id cursor cannot resume a type-ordered listing, so that sort is one page.
151
+ const nextId = serialised.length === p.limit && last && p.sort !== "type" ? last.id : null;
152
+ return { rows: serialised, nextCursor: nextId, nextBefore: nextId };
153
+ }
@@ -0,0 +1,13 @@
1
+ import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
2
+
3
+ export function requireAuditSystemDb<TSystemDb>(
4
+ systemDb: TSystemDb | undefined,
5
+ handlerQn: string,
6
+ ): TSystemDb {
7
+ if (!systemDb) {
8
+ throw new InternalError({
9
+ message: `${handlerQn} requires ctx.systemDb — is r.systemScope() still set on the audit feature?`,
10
+ });
11
+ }
12
+ return systemDb;
13
+ }
@@ -0,0 +1,26 @@
1
+ // One audit event of any tenant by its event-store id, for the all-tenants log's detail screen.
2
+
3
+ import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
4
+ import * as z from "zod";
5
+ import { auditEventIdSchema, loadAuditEvent } from "./audit-events.ts";
6
+ import { requireAuditSystemDb } from "./audit-system-db.ts";
7
+ import { allTenantsCondition, assertMayReadAllTenants } from "./resolve-audit-tenant.ts";
8
+
9
+ export const detailsAllTenantsQuery = defineQueryHandler({
10
+ name: "details-all-tenants",
11
+ description:
12
+ "Returns one audit-trail event of any tenant by its event-store id, with full payload, metadata and tenantId; SystemAdmin only, system-tenant events are not included.",
13
+ schema: z.object({ id: auditEventIdSchema }),
14
+ access: { roles: access.systemAdmin },
15
+ handler: async (query, ctx) => {
16
+ assertMayReadAllTenants(query.user);
17
+ const db = requireAuditSystemDb(
18
+ ctx.systemDb,
19
+ "audit:query:details-all-tenants",
20
+ ).acknowledgeCrossTenant("SystemAdmin reads one audit event of any tenant");
21
+ return loadAuditEvent(db, {
22
+ tenantId: allTenantsCondition(undefined),
23
+ id: BigInt(query.payload.id),
24
+ });
25
+ },
26
+ });
@@ -3,12 +3,11 @@
3
3
  // can only read events in their own tenant; a SystemAdmin can pass scope
4
4
  // "system" to read app-instance system events (e.g. app.started).
5
5
 
6
- import { selectMany } from "@cosmicdrift/kumiko-framework/db";
7
6
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
8
- import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
9
7
  import * as z from "zod";
10
- import { redactPiiCiphertext } from "../../shared/index.ts";
11
- import { AUDIT_SCOPE_VALUES } from "../constants.ts";
8
+ import { AUDIT_SCOPE_VALUES } from "../web/constants.ts";
9
+ import { auditEventIdSchema, loadAuditEvent } from "./audit-events.ts";
10
+ import { requireAuditSystemDb } from "./audit-system-db.ts";
12
11
  import { resolveAuditScopeFilter } from "./resolve-audit-tenant.ts";
13
12
 
14
13
  export const detailsQuery = defineQueryHandler({
@@ -16,46 +15,19 @@ export const detailsQuery = defineQueryHandler({
16
15
  description:
17
16
  'Returns one audit-trail event of the caller\'s tenant by its event-store id, with full payload and metadata; use it to inspect the exact change behind a row of the audit log list. A SystemAdmin can set scope "system" to read an app-instance system event (e.g. app.started).',
18
17
  schema: z.object({
19
- id: z.string().regex(/^[1-9]\d*$/, "id must be a positive integer"),
18
+ id: auditEventIdSchema,
20
19
  scope: z.enum(AUDIT_SCOPE_VALUES).optional(),
21
20
  }),
22
21
  access: { roles: access.admin },
23
22
  handler: async (query, ctx) => {
24
23
  const scopeFilter = resolveAuditScopeFilter(query.user, query.payload.scope);
25
- const rows = await selectMany<{
26
- id: bigint;
27
- aggregateId: string;
28
- aggregateType: string;
29
- version: number;
30
- type: string;
31
- payload: Record<string, unknown>;
32
- metadata: Record<string, unknown>;
33
- createdAt: unknown;
34
- createdBy: string;
35
- }>(
36
- ctx.db,
37
- eventsTable,
38
- {
39
- tenantId: scopeFilter.tenantId,
40
- ...(scopeFilter.aggregateType !== undefined && {
41
- aggregateType: scopeFilter.aggregateType,
42
- }),
43
- id: BigInt(query.payload.id),
44
- },
45
- { limit: 1 },
24
+ const db = requireAuditSystemDb(ctx.systemDb, "audit:query:details").assertTenantMatch(
25
+ query.user.tenantId,
46
26
  );
47
- const row = rows[0];
48
- if (row === undefined) return null;
49
- return {
50
- id: String(row.id),
51
- aggregateId: row.aggregateId,
52
- aggregateType: row.aggregateType,
53
- version: row.version,
54
- type: row.type,
55
- payload: redactPiiCiphertext(row.payload),
56
- metadata: row.metadata,
57
- createdAt: row.createdAt,
58
- createdBy: row.createdBy,
59
- };
27
+ return loadAuditEvent(db, {
28
+ tenantId: scopeFilter.tenantId,
29
+ ...(scopeFilter.aggregateType !== undefined && { aggregateType: scopeFilter.aggregateType }),
30
+ id: BigInt(query.payload.id),
31
+ });
60
32
  },
61
33
  });
@@ -0,0 +1,47 @@
1
+ // SystemAdmin view of the audit trail across every tenant (the system tenant excluded, see
2
+ // allTenantsCondition). Rows carry their tenantId so the screen can label the tenant.
3
+
4
+ import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
5
+ import * as z from "zod";
6
+ import {
7
+ AUDIT_DATE_RANGE_CHECK,
8
+ auditListPayloadShape,
9
+ buildAuditWhere,
10
+ listAuditEvents,
11
+ } from "./audit-events.ts";
12
+ import { requireAuditSystemDb } from "./audit-system-db.ts";
13
+ import { allTenantsCondition, assertMayReadAllTenants } from "./resolve-audit-tenant.ts";
14
+
15
+ const MAX_TENANT_FILTER_IDS = 100;
16
+
17
+ // The reference facet on the tenant column sends exactly this shape.
18
+ const tenantIdFiltersSchema = z
19
+ .array(
20
+ z.strictObject({
21
+ field: z.literal("tenantId"),
22
+ op: z.literal("in"),
23
+ value: z.array(z.uuid()).max(MAX_TENANT_FILTER_IDS),
24
+ }),
25
+ )
26
+ .max(1);
27
+
28
+ export const listAllTenantsQuery = defineQueryHandler({
29
+ name: "list-all-tenants",
30
+ description:
31
+ "Lists audit-trail events of every tenant newest-first with cursor paging, each row carrying its tenantId; filterable by tenant, aggregate type, aggregate id, event type, actor and time range. SystemAdmin only; events of the system tenant are not included.",
32
+ schema: z
33
+ .object({ ...auditListPayloadShape, filters: tenantIdFiltersSchema.optional() })
34
+ .refine(AUDIT_DATE_RANGE_CHECK.isValid, AUDIT_DATE_RANGE_CHECK.params),
35
+ access: { roles: access.systemAdmin },
36
+ handler: async (query, ctx) => {
37
+ assertMayReadAllTenants(query.user);
38
+ const p = query.payload;
39
+ const direction = p.sortDirection ?? "desc";
40
+ const where = buildAuditWhere(allTenantsCondition(p.filters?.[0]?.value), p, direction);
41
+ const db = requireAuditSystemDb(
42
+ ctx.systemDb,
43
+ "audit:query:list-all-tenants",
44
+ ).acknowledgeCrossTenant("SystemAdmin reads the audit trail of every tenant");
45
+ return listAuditEvents(db, where, p, direction);
46
+ },
47
+ });
@@ -7,91 +7,27 @@
7
7
  // surface any audit UI needs; tenant-isolated at the WHERE level so cross-
8
8
  // tenant peeking is structurally impossible for non-SystemAdmin callers.
9
9
  // A SystemAdmin can pass scope "system" to read the app-instance system events
10
- // (e.g. app.started); no other cross-tenant read exists.
11
- //
12
- // Event payloads hold PII as subject-KMS ciphertext; it is replaced by
13
- // REDACTED_PII_PLACEHOLDER before returning, since the API leak guard refuses ciphertext.
10
+ // (e.g. app.started); list-all-tenants is the one other cross-tenant read.
14
11
 
15
- import { selectMany, type WhereObject } from "@cosmicdrift/kumiko-framework/db";
16
12
  import { access, defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
17
- import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
18
- import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
19
13
  import * as z from "zod";
20
- import { redactPiiCiphertext } from "../../shared/index.ts";
21
- import { AUDIT_SCOPE_VALUES } from "../constants.ts";
14
+ import { AUDIT_SCOPE_VALUES } from "../web/constants.ts";
15
+ import {
16
+ AUDIT_DATE_RANGE_CHECK,
17
+ auditListPayloadShape,
18
+ buildAuditWhere,
19
+ listAuditEvents,
20
+ } from "./audit-events.ts";
21
+ import { requireAuditSystemDb } from "./audit-system-db.ts";
22
22
  import { resolveAuditScopeFilter } from "./resolve-audit-tenant.ts";
23
23
 
24
- const MAX_LIMIT = 100;
25
-
26
- function buildDateRange(
27
- from: string | undefined,
28
- to: string | undefined,
29
- ): { gte?: unknown; lte?: unknown } | null {
30
- if (!from && !to) return null;
31
- const range: { gte?: unknown; lte?: unknown } = {};
32
- if (from) range.gte = Temporal.Instant.from(from);
33
- if (to) range.lte = Temporal.Instant.from(to);
34
- return range;
35
- }
36
-
37
- function escapeLikePattern(value: string): string {
38
- return value.replace(/[\\%_]/g, (m) => `\\${m}`);
39
- }
40
-
41
- function buildAuditWhere(
42
- tenantId: string,
43
- p: {
44
- aggregateType?: string;
45
- aggregateId?: string;
46
- eventType?: string;
47
- search?: string;
48
- userId?: string;
49
- from?: string;
50
- to?: string;
51
- cursor?: string;
52
- before?: string;
53
- },
54
- direction: "asc" | "desc",
55
- ): WhereObject {
56
- const where: WhereObject = { tenantId };
57
- if (p.aggregateType) where["aggregateType"] = p.aggregateType;
58
- if (p.aggregateId) where["aggregateId"] = p.aggregateId;
59
- if (p.eventType) where["type"] = p.eventType;
60
- else if (p.search) where["type"] = { like: `%${escapeLikePattern(p.search)}%` };
61
- if (p.userId) where["createdBy"] = p.userId;
62
- const range = buildDateRange(p.from, p.to);
63
- if (range) where["createdAt"] = range;
64
- const cursor = p.cursor ?? p.before;
65
- // The cursor is an event id, so it only walks pages in id order: ascending
66
- // pages continue past it, descending pages stop before it.
67
- if (cursor) where["id"] = direction === "asc" ? { gt: BigInt(cursor) } : { lt: BigInt(cursor) };
68
- return where;
69
- }
70
-
71
24
  export const listQuery = defineQueryHandler({
72
25
  name: "list",
73
26
  description:
74
27
  'Lists the tenant\'s audit-trail events newest-first with cursor paging, filterable by aggregate type, aggregate id, event type, actor and time range; use it to answer who changed what and when. A SystemAdmin can set scope "system" to read the app-instance system events (e.g. app.started) instead of the own tenant.',
75
28
  schema: z
76
- .object({
77
- cursor: z.string().regex(/^\d+$/, "cursor must be a positive integer").optional(),
78
- before: z.string().regex(/^\d+$/, "cursor must be a positive integer").optional(),
79
- search: z.string().trim().optional(),
80
- limit: z.number().int().min(1).max(MAX_LIMIT).default(50),
81
- aggregateType: z.string().optional(),
82
- aggregateId: z.uuid().optional(),
83
- eventType: z.string().optional(),
84
- userId: z.string().optional(),
85
- sort: z.enum(["createdAt", "type"]).optional(),
86
- sortDirection: z.enum(["asc", "desc"]).optional(),
87
- from: z.iso.datetime().optional(),
88
- to: z.iso.datetime().optional(),
89
- scope: z.enum(AUDIT_SCOPE_VALUES).optional(),
90
- })
91
- .refine((v) => !v.from || !v.to || v.from <= v.to, {
92
- message: "`from` must be less than or equal to `to`",
93
- path: ["from"],
94
- }),
29
+ .object({ ...auditListPayloadShape, scope: z.enum(AUDIT_SCOPE_VALUES).optional() })
30
+ .refine(AUDIT_DATE_RANGE_CHECK.isValid, AUDIT_DATE_RANGE_CHECK.params),
95
31
  access: { roles: access.admin },
96
32
  handler: async (query, ctx) => {
97
33
  const p = query.payload;
@@ -99,55 +35,12 @@ export const listQuery = defineQueryHandler({
99
35
  const direction = p.sortDirection ?? "desc";
100
36
  const where = buildAuditWhere(
101
37
  scopeFilter.tenantId,
102
- {
103
- ...p,
104
- aggregateType: scopeFilter.aggregateType ?? p.aggregateType,
105
- },
38
+ { ...p, aggregateType: scopeFilter.aggregateType ?? p.aggregateType },
106
39
  direction,
107
40
  );
108
-
109
- const rows = await selectMany<{
110
- id: bigint;
111
- aggregateId: string;
112
- aggregateType: string;
113
- version: number;
114
- type: string;
115
- payload: Record<string, unknown>;
116
- metadata: Record<string, unknown>;
117
- createdAt: unknown;
118
- createdBy: string;
119
- }>(ctx.db, eventsTable, where, {
120
- // The id cursor only resumes an id-ordered listing. created_at comes from the
121
- // transaction start and can run against insert order, so ordering by it would let
122
- // a page boundary skip rows; only the type sort leaves id order (and is one page).
123
- orderBy:
124
- p.sort === "type"
125
- ? [
126
- { col: "type", direction },
127
- { col: "id", direction },
128
- ]
129
- : [{ col: "id", direction }],
130
- limit: p.limit,
131
- });
132
-
133
- const serialised = rows.map((r) => ({
134
- id: String(r.id),
135
- aggregateId: r.aggregateId,
136
- aggregateType: r.aggregateType,
137
- version: r.version,
138
- type: r.type,
139
- payload: redactPiiCiphertext(r.payload),
140
- metadata: r.metadata,
141
- createdAt: r.createdAt,
142
- createdBy: r.createdBy,
143
- }));
144
- const last = serialised[serialised.length - 1];
145
- // An id cursor cannot resume a type-ordered listing, so that sort is one page.
146
- const nextId = serialised.length === p.limit && last && p.sort !== "type" ? last.id : null;
147
- return {
148
- rows: serialised,
149
- nextCursor: nextId,
150
- nextBefore: nextId,
151
- };
41
+ const db = requireAuditSystemDb(ctx.systemDb, "audit:query:list").assertTenantMatch(
42
+ query.user.tenantId,
43
+ );
44
+ return listAuditEvents(db, where, p, direction);
152
45
  },
153
46
  });
@@ -2,10 +2,17 @@ import { mayOverrideTenant, type SessionUser } from "@cosmicdrift/kumiko-framewo
2
2
  import { AccessDeniedError, FrameworkReasons } from "@cosmicdrift/kumiko-framework/errors";
3
3
  import { APP_INSTANCE_STREAM_TYPE } from "@cosmicdrift/kumiko-framework/event-store";
4
4
  import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-types/identifiers";
5
- import { type AuditScope, AuditScopes } from "../constants.ts";
5
+ import { type AuditScope, AuditScopes } from "../web/constants.ts";
6
6
 
7
7
  export type AuditScopeFilter = { readonly tenantId: string; readonly aggregateType?: string };
8
8
 
9
+ function denySystemAdminOnlyRead(): never {
10
+ throw new AccessDeniedError({
11
+ i18nKey: "audit.errors.systemScopeRequiresSystemAdmin",
12
+ details: { reason: FrameworkReasons.tenantOverrideRequiresSystemAdmin },
13
+ });
14
+ }
15
+
9
16
  // The system tenant also holds personal streams of other features (session
10
17
  // revocations, exports, ...); only app-instance streams are released.
11
18
  export function resolveAuditScopeFilter(
@@ -13,11 +20,18 @@ export function resolveAuditScopeFilter(
13
20
  scope: AuditScope | undefined,
14
21
  ): AuditScopeFilter {
15
22
  if (scope !== AuditScopes.system) return { tenantId: user.tenantId };
16
- if (!mayOverrideTenant(user)) {
17
- throw new AccessDeniedError({
18
- i18nKey: "audit.errors.systemScopeRequiresSystemAdmin",
19
- details: { reason: FrameworkReasons.tenantOverrideRequiresSystemAdmin },
20
- });
21
- }
23
+ if (!mayOverrideTenant(user)) denySystemAdminOnlyRead();
22
24
  return { tenantId: SYSTEM_TENANT_ID, aggregateType: APP_INSTANCE_STREAM_TYPE };
23
25
  }
26
+
27
+ export function assertMayReadAllTenants(user: SessionUser): void {
28
+ if (!mayOverrideTenant(user)) denySystemAdminOnlyRead();
29
+ }
30
+
31
+ // The where condition for reads across tenants. The system tenant is always excluded: it holds
32
+ // personal streams of other features, and a where object cannot express "only app-instance
33
+ // streams of that one tenant" next to "every other tenant".
34
+ export function allTenantsCondition(requestedTenantIds: readonly string[] | undefined): unknown {
35
+ if (requestedTenantIds === undefined) return { ne: SYSTEM_TENANT_ID };
36
+ return { in: requestedTenantIds.filter((id) => id !== SYSTEM_TENANT_ID) };
37
+ }
@@ -1,3 +1,3 @@
1
- export { AUDIT_FEATURE, AuditQueries } from "./constants.ts";
2
1
  export { createEscapeHatchAuditSink, ESCAPE_HATCH_USED_EVENT } from "./escape-hatch-audit-sink.ts";
3
2
  export { createAuditFeature } from "./feature.ts";
3
+ export { AUDIT_FEATURE, AuditQueries } from "./web/constants.ts";
@@ -20,14 +20,14 @@ import { pruneEvents } from "@cosmicdrift/kumiko-framework/pipeline";
20
20
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
21
21
  import { resolveProfileForTenant } from "../compliance-profiles/index.ts";
22
22
  import { createConfigAccessor } from "../config/index.ts";
23
- import {
24
- DEFAULT_ESCAPE_HATCH_RETENTION_DAYS,
25
- ESCAPE_HATCH_RETENTION_DAYS_KEY,
26
- } from "./constants.ts";
27
23
  import {
28
24
  ESCAPE_HATCH_USE_AGGREGATE_TYPE,
29
25
  escapeHatchUsedSchema,
30
26
  } from "./escape-hatch-audit-sink.ts";
27
+ import {
28
+ DEFAULT_ESCAPE_HATCH_RETENTION_DAYS,
29
+ ESCAPE_HATCH_RETENTION_DAYS_KEY,
30
+ } from "./web/constants.ts";
31
31
 
32
32
  // pruneEvents opens its own transaction, so a runner that cannot begin one (a tx handle) is rejected instead of nested.
33
33
  export function isDbConnection(runner: DbRunner): runner is DbConnection {
@@ -0,0 +1,82 @@
1
+ // Columns, labels and layout shared by the tenant audit log and its all-tenants variant, so the
2
+ // two screen pairs cannot drift apart. The all-tenants variant only adds the tenant.
3
+
4
+ import { i18nKey } from "@cosmicdrift/kumiko-framework/engine";
5
+ import type { EditLayout, ListColumnSpec } from "@cosmicdrift/kumiko-framework/ui-types";
6
+
7
+ const TENANT_REFERENCE = { refEntity: "tenant:tenant", refLabelField: "name" } as const;
8
+ const ACTOR_REFERENCE = { refEntity: "user:user", refLabelField: "displayName" } as const;
9
+
10
+ const WHEN_COLUMN = {
11
+ field: "createdAt",
12
+ label: i18nKey("audit.log.col.when"),
13
+ renderer: { format: "timestamp" },
14
+ } as const satisfies ListColumnSpec;
15
+ const TENANT_COLUMN = {
16
+ field: "tenantId",
17
+ label: i18nKey("audit.log.col.tenant"),
18
+ ...TENANT_REFERENCE,
19
+ } as const satisfies ListColumnSpec;
20
+ const TYPE_COLUMN = { field: "type", label: i18nKey("audit.log.col.type") } as const;
21
+ const ACTOR_COLUMN = {
22
+ field: "createdBy",
23
+ label: i18nKey("audit.log.col.actor"),
24
+ ...ACTOR_REFERENCE,
25
+ } as const satisfies ListColumnSpec;
26
+
27
+ export const AUDIT_LOG_COLUMNS = [WHEN_COLUMN, TYPE_COLUMN, ACTOR_COLUMN] as const;
28
+ export const AUDIT_LOG_ALL_TENANTS_COLUMNS = [
29
+ WHEN_COLUMN,
30
+ TENANT_COLUMN,
31
+ TYPE_COLUMN,
32
+ ACTOR_COLUMN,
33
+ ] as const;
34
+
35
+ export const AUDIT_LOG_DATE_RANGE_FACET = {
36
+ type: "dateRange",
37
+ field: "createdAt",
38
+ label: i18nKey("audit.log.col.when"),
39
+ params: { from: "from", to: "to" },
40
+ } as const;
41
+
42
+ export const AUDIT_LOG_TENANT_FACET = {
43
+ type: "reference",
44
+ field: "tenantId",
45
+ label: i18nKey("audit.log.col.tenant"),
46
+ entity: TENANT_REFERENCE.refEntity,
47
+ labelField: TENANT_REFERENCE.refLabelField,
48
+ } as const;
49
+
50
+ export const AUDIT_LOG_DETAIL_FIELD_LABELS = {
51
+ type: i18nKey("audit.log.col.type"),
52
+ createdAt: i18nKey("audit.log.col.when"),
53
+ aggregateType: i18nKey("audit.log.col.aggregateType"),
54
+ aggregateId: i18nKey("audit.log.col.aggregateId"),
55
+ createdBy: i18nKey("audit.log.col.actor"),
56
+ id: i18nKey("audit.log.detail.field.id"),
57
+ payload: i18nKey("audit.log.detail.payload"),
58
+ metadata: i18nKey("audit.log.detail.metadata"),
59
+ } as const;
60
+
61
+ export function auditLogDetailLayout(options: { readonly withTenant: boolean }): EditLayout {
62
+ return {
63
+ sections: [
64
+ {
65
+ fields: [
66
+ "type",
67
+ { field: "createdAt", renderer: { format: "timestamp" } },
68
+ ...(options.withTenant ? [{ field: "tenantId", ...TENANT_REFERENCE }] : []),
69
+ "aggregateType",
70
+ "aggregateId",
71
+ { field: "createdBy", ...ACTOR_REFERENCE },
72
+ "id",
73
+ ],
74
+ },
75
+ // No section `title` here (fw#2312 label-dedup fix): each section
76
+ // holds exactly one field, so a title would repeat the field's own
77
+ // label (rendered by RenderField as the Field's heading) verbatim.
78
+ { fields: [{ field: "payload", renderer: { format: "json" } }] },
79
+ { fields: [{ field: "metadata", renderer: { format: "json" } }] },
80
+ ],
81
+ };
82
+ }
@@ -1,8 +1,7 @@
1
- // @runtime client
2
1
  import { mergeTranslations, type TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
2
  import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
4
- import { AUDIT_FEATURE } from "../constants.ts";
5
- import { defaultTranslations } from "./i18n.ts";
3
+ import { AUDIT_FEATURE } from "./constants.ts";
4
+ import { defaultTranslations } from "./default-translations.ts";
6
5
 
7
6
  export type AuditClientOptions = {
8
7
  readonly translations?: TranslationsByLocale;
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Qualified handler names + screen ids — shared by server feature and web client.
3
2
  export const AUDIT_FEATURE = "audit" as const;
4
3
 
@@ -17,6 +16,8 @@ export const SYSTEM_ACTOR_IDS: ReadonlySet<string> = new Set([
17
16
  export const AuditQueries = {
18
17
  list: "audit:query:list",
19
18
  details: "audit:query:details",
19
+ listAllTenants: "audit:query:list-all-tenants",
20
+ detailsAllTenants: "audit:query:details-all-tenants",
20
21
  } as const;
21
22
 
22
23
  /** Read scope of the audit queries: the caller's own tenant (default) or the system tenant (SystemAdmin only). */
@@ -30,6 +31,15 @@ export const AUDIT_LOG_SCREEN_ID = "audit-log" as const;
30
31
  /** Single-event detail screen, breadcrumb-linked to the audit-log list. */
31
32
  export const AUDIT_LOG_DETAIL_SCREEN_ID = "audit-log-detail" as const;
32
33
 
34
+ /** SystemAdmin audit log across every tenant. Nav: `audit:nav:audit-log-all-tenants`. */
35
+ export const AUDIT_LOG_ALL_TENANTS_SCREEN_ID = "audit-log-all-tenants" as const;
36
+
37
+ /** Single-event detail screen of the all-tenants log. */
38
+ export const AUDIT_LOG_ALL_TENANTS_DETAIL_SCREEN_ID = "audit-log-all-tenants-detail" as const;
39
+
40
+ /** Nav entry of the all-tenants log (short id; QN `audit:nav:audit-log-all-tenants`). */
41
+ export const AUDIT_LOG_ALL_TENANTS_NAV_ID = "audit-log-all-tenants" as const;
42
+
33
43
  /**
34
44
  * Config key (system scope) for how long `escapeHatchUse` audit events are kept. Only a fallback
35
45
  * for apps without compliance-profiles; with it mounted, the tenant profile's `auditLog.retention`