@cosmicdrift/kumiko-samples 0.377.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 (526) 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-counter/changes.json +12 -0
  132. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +9 -0
  133. package/packages/bundled-features/src/cap-overview/feature.ts +1 -1
  134. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -1
  135. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +2 -2
  136. package/packages/bundled-features/src/cap-overview/index.ts +9 -9
  137. package/packages/bundled-features/src/cap-overview/screens.ts +2 -2
  138. package/packages/bundled-features/src/cap-overview/web/cap-cards-panel.tsx +1 -2
  139. package/packages/bundled-features/src/cap-overview/web/cap-usage-bar.tsx +1 -2
  140. package/packages/bundled-features/src/cap-overview/web/cap-usage-cell.tsx +0 -2
  141. package/packages/bundled-features/src/cap-overview/web/client-plugin.tsx +3 -4
  142. package/packages/bundled-features/src/cap-overview/{constants.ts → web/constants.ts} +0 -1
  143. package/packages/bundled-features/src/cap-overview/web/index.ts +0 -1
  144. package/packages/bundled-features/src/cap-overview/{usage-math.ts → web/usage-math.ts} +1 -2
  145. package/packages/bundled-features/src/compliance-profiles/feature.ts +5 -5
  146. package/packages/bundled-features/src/compliance-profiles/index.ts +6 -6
  147. package/packages/bundled-features/src/compliance-profiles/web/client-plugin.tsx +2 -3
  148. package/packages/bundled-features/src/compliance-profiles/web/compliance-profile-catalog.tsx +1 -2
  149. package/packages/bundled-features/src/compliance-profiles/{constants.ts → web/constants.ts} +0 -1
  150. package/packages/bundled-features/src/compliance-profiles/web/i18n.ts +0 -1
  151. package/packages/bundled-features/src/compliance-profiles/web/index.ts +0 -1
  152. package/packages/bundled-features/src/config/index.ts +6 -6
  153. package/packages/bundled-features/src/config/web/client-plugin.ts +1 -2
  154. package/packages/bundled-features/src/config/{constants.ts → web/constants.ts} +0 -1
  155. package/packages/bundled-features/src/config/web/i18n.ts +1 -1
  156. package/packages/bundled-features/src/config/web/index.ts +1 -3
  157. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  158. package/packages/bundled-features/src/custom-fields/feature.ts +8 -8
  159. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +1 -1
  160. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +1 -1
  161. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +1 -1
  162. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +4 -4
  163. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +1 -1
  164. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +1 -1
  165. package/packages/bundled-features/src/custom-fields/index.ts +8 -8
  166. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +1 -1
  167. package/packages/bundled-features/src/custom-fields/schemas.ts +1 -1
  168. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +1 -2
  169. package/packages/bundled-features/src/custom-fields/{constants.ts → web/constants.ts} +18 -19
  170. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +1 -2
  171. package/packages/bundled-features/src/custom-fields/web/i18n.ts +0 -1
  172. package/packages/bundled-features/src/custom-fields/web/index.ts +2 -3
  173. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +1 -2
  174. package/packages/bundled-features/src/delivery/address-opt-out.ts +1 -1
  175. package/packages/bundled-features/src/delivery/attempt-log-retention.ts +24 -8
  176. package/packages/bundled-features/src/delivery/changes.json +6 -0
  177. package/packages/bundled-features/src/delivery/constants.ts +2 -2
  178. package/packages/bundled-features/src/delivery/i18n.ts +1 -1
  179. package/packages/bundled-features/src/delivery/unsubscribe-page.ts +1 -1
  180. package/packages/bundled-features/src/delivery/web/client-plugin.tsx +6 -7
  181. package/packages/bundled-features/src/delivery/web/delivery-channel-cell.tsx +0 -1
  182. package/packages/bundled-features/src/delivery/web/delivery-error-cell.tsx +0 -1
  183. package/packages/bundled-features/src/delivery/web/delivery-status-cell.tsx +1 -2
  184. package/packages/bundled-features/src/delivery/web/delivery-time-cell.tsx +0 -1
  185. package/packages/bundled-features/src/delivery/web/delivery-type-cell.tsx +0 -1
  186. package/packages/bundled-features/src/delivery/web/index.ts +0 -1
  187. package/packages/bundled-features/src/delivery/{public-names.ts → web/public-names.ts} +0 -1
  188. package/packages/bundled-features/src/document-ingest-foundation/changes.json +6 -0
  189. package/packages/bundled-features/src/document-ingest-foundation/events.ts +4 -0
  190. package/packages/bundled-features/src/document-ingest-foundation/executor.ts +2 -1
  191. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +18 -4
  192. package/packages/bundled-features/src/document-ingest-foundation/index.ts +1 -0
  193. package/packages/bundled-features/src/feature-toggles/feature.ts +7 -7
  194. package/packages/bundled-features/src/feature-toggles/handlers/list.query.ts +1 -1
  195. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +1 -1
  196. package/packages/bundled-features/src/feature-toggles/handlers/set.write.ts +3 -3
  197. package/packages/bundled-features/src/feature-toggles/index.ts +6 -6
  198. package/packages/bundled-features/src/feature-toggles/web/client-plugin.tsx +1 -2
  199. package/packages/bundled-features/src/feature-toggles/{constants.ts → web/constants.ts} +0 -1
  200. package/packages/bundled-features/src/feature-toggles/web/i18n.ts +0 -1
  201. package/packages/bundled-features/src/feature-toggles/web/index.ts +0 -1
  202. package/packages/bundled-features/src/files/changes.json +7 -0
  203. package/packages/bundled-features/src/folders/feature.ts +1 -1
  204. package/packages/bundled-features/src/folders/handlers/clear-folder.write.ts +1 -1
  205. package/packages/bundled-features/src/folders/handlers/delete-folder.write.ts +1 -1
  206. package/packages/bundled-features/src/folders/handlers/set-folder.write.ts +1 -1
  207. package/packages/bundled-features/src/folders/index.ts +8 -8
  208. package/packages/bundled-features/src/folders/web/client-plugin.tsx +1 -3
  209. package/packages/bundled-features/src/folders/{constants.ts → web/constants.ts} +0 -1
  210. package/packages/bundled-features/src/folders/web/folder-manager.tsx +1 -2
  211. package/packages/bundled-features/src/folders/web/folder-section.tsx +1 -2
  212. package/packages/bundled-features/src/folders/web/i18n.ts +0 -1
  213. package/packages/bundled-features/src/folders/web/index.ts +1 -2
  214. package/packages/bundled-features/src/folders/web/tree.ts +0 -1
  215. package/packages/bundled-features/src/form-draft/changes.json +7 -0
  216. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +25 -11
  217. package/packages/bundled-features/src/form-draft/decrypt-draft.ts +24 -0
  218. package/packages/bundled-features/src/form-draft/entity.ts +6 -9
  219. package/packages/bundled-features/src/form-draft/feature.ts +1 -1
  220. package/packages/bundled-features/src/form-draft/handlers/cleanup.job.ts +26 -5
  221. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  222. package/packages/bundled-features/src/form-draft/handlers/get.query.ts +6 -7
  223. package/packages/bundled-features/src/form-draft/handlers/list.query.ts +13 -7
  224. package/packages/bundled-features/src/form-draft/handlers/save.write.ts +5 -5
  225. package/packages/bundled-features/src/form-draft/index.ts +8 -8
  226. package/packages/bundled-features/src/form-draft/lookup.ts +10 -4
  227. package/packages/bundled-features/src/form-draft/schemas.ts +1 -1
  228. package/packages/bundled-features/src/form-draft/{constants.ts → web/constants.ts} +0 -1
  229. package/packages/bundled-features/src/form-draft-user-data/hooks.ts +2 -2
  230. package/packages/bundled-features/src/inbound-mail-foundation/changes.json +6 -0
  231. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +11 -4
  232. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +10 -10
  233. package/packages/bundled-features/src/jobs/feature.ts +7 -7
  234. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  235. package/packages/bundled-features/src/jobs/handlers/trigger.write.ts +1 -1
  236. package/packages/bundled-features/src/jobs/index.ts +1 -1
  237. package/packages/bundled-features/src/jobs/web/client-plugin.tsx +2 -3
  238. package/packages/bundled-features/src/jobs/{constants.ts → web/constants.ts} +0 -1
  239. package/packages/bundled-features/src/jobs/web/default-translations.ts +7 -0
  240. package/packages/bundled-features/src/jobs/web/i18n.ts +53 -7
  241. package/packages/bundled-features/src/jobs/web/index.ts +0 -1
  242. package/packages/bundled-features/src/ledger/changes.json +7 -0
  243. package/packages/bundled-features/src/ledger/entity.ts +1 -1
  244. package/packages/bundled-features/src/ledger/feature.ts +1 -1
  245. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +2 -10
  246. package/packages/bundled-features/src/ledger/handlers/create-transaction.write.ts +1 -1
  247. package/packages/bundled-features/src/ledger/handlers/reports.query.ts +1 -1
  248. package/packages/bundled-features/src/ledger/handlers/reverse-transaction.write.ts +1 -1
  249. package/packages/bundled-features/src/ledger/index.ts +13 -13
  250. package/packages/bundled-features/src/ledger/recurring.ts +1 -1
  251. package/packages/bundled-features/src/ledger/reports.ts +1 -1
  252. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  253. package/packages/bundled-features/src/ledger/{constants.ts → web/constants.ts} +0 -1
  254. package/packages/bundled-features/src/ledger/web/index.ts +11 -12
  255. package/packages/bundled-features/src/legal-pages/README.md +1 -1
  256. package/packages/bundled-features/src/legal-pages/feature.ts +5 -5
  257. package/packages/bundled-features/src/legal-pages/index.ts +11 -11
  258. package/packages/bundled-features/src/legal-pages/lib/boot-check.ts +1 -1
  259. package/packages/bundled-features/src/legal-pages/lib/validate-routes.ts +1 -1
  260. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +1 -2
  261. package/packages/bundled-features/src/legal-pages/{constants.ts → web/constants.ts} +6 -8
  262. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -1
  263. package/packages/bundled-features/src/mail-foundation/changes.json +6 -0
  264. package/packages/bundled-features/src/mail-foundation/i18n.ts +3 -2
  265. package/packages/bundled-features/src/mail-transport-smtp/i18n.ts +1 -1
  266. package/packages/bundled-features/src/managed-pages/feature.ts +1 -1
  267. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +1 -2
  268. package/packages/bundled-features/src/managed-pages/web/default-translations.ts +17 -0
  269. package/packages/bundled-features/src/managed-pages/web/i18n.ts +59 -16
  270. package/packages/bundled-features/src/managed-pages/web/index.ts +1 -2
  271. package/packages/bundled-features/src/metrics/compute.ts +1 -1
  272. package/packages/bundled-features/src/metrics/feature.ts +6 -6
  273. package/packages/bundled-features/src/metrics/index.ts +8 -8
  274. package/packages/bundled-features/src/metrics/types.ts +1 -1
  275. package/packages/bundled-features/src/metrics/validate.ts +1 -1
  276. package/packages/bundled-features/src/metrics/{constants.ts → web/constants.ts} +0 -1
  277. package/packages/bundled-features/src/metrics/window.ts +1 -1
  278. package/packages/bundled-features/src/notes-history/feature.ts +1 -1
  279. package/packages/bundled-features/src/notes-history/handlers/add-note.write.ts +1 -1
  280. package/packages/bundled-features/src/notes-history/index.ts +8 -8
  281. package/packages/bundled-features/src/notes-history/web/client-plugin.tsx +1 -3
  282. package/packages/bundled-features/src/notes-history/{constants.ts → web/constants.ts} +0 -1
  283. package/packages/bundled-features/src/notes-history/web/i18n.ts +0 -1
  284. package/packages/bundled-features/src/notes-history/web/index.ts +2 -3
  285. package/packages/bundled-features/src/notes-history/web/notes-section.tsx +2 -3
  286. package/packages/bundled-features/src/personal-access-tokens/feature.ts +12 -10
  287. package/packages/bundled-features/src/personal-access-tokens/handlers/available-scopes.query.ts +1 -1
  288. package/packages/bundled-features/src/personal-access-tokens/handlers/create.write.ts +1 -1
  289. package/packages/bundled-features/src/personal-access-tokens/handlers/revoke.write.ts +1 -1
  290. package/packages/bundled-features/src/personal-access-tokens/hash.ts +1 -1
  291. package/packages/bundled-features/src/personal-access-tokens/i18n.ts +2 -2
  292. package/packages/bundled-features/src/personal-access-tokens/index.ts +5 -5
  293. package/packages/bundled-features/src/personal-access-tokens/resolver.ts +1 -1
  294. package/packages/bundled-features/src/personal-access-tokens/schema/api-token.ts +1 -1
  295. package/packages/bundled-features/src/personal-access-tokens/screens.ts +2 -2
  296. package/packages/bundled-features/src/personal-access-tokens/{constants.ts → web/constants.ts} +0 -1
  297. package/packages/bundled-features/src/personal-access-tokens/{scopes.ts → web/scopes.ts} +0 -1
  298. package/packages/bundled-features/src/presets/changes.json +7 -0
  299. package/packages/bundled-features/src/presets/index.ts +0 -1
  300. package/packages/bundled-features/src/presets/security-baseline.ts +1 -1
  301. package/packages/bundled-features/src/renderer-foundation/types.ts +1 -1
  302. package/packages/bundled-features/src/secrets/feature.ts +1 -1
  303. package/packages/bundled-features/src/secrets/handlers/delete.write.ts +1 -1
  304. package/packages/bundled-features/src/secrets/handlers/list.query.ts +1 -1
  305. package/packages/bundled-features/src/secrets/handlers/set.write.ts +1 -1
  306. package/packages/bundled-features/src/secrets/i18n.ts +1 -1
  307. package/packages/bundled-features/src/secrets/index.ts +8 -8
  308. package/packages/bundled-features/src/secrets/{constants.ts → web/constants.ts} +0 -1
  309. package/packages/bundled-features/src/secrets/write-gate.ts +1 -1
  310. package/packages/bundled-features/src/sessions/feature.ts +7 -4
  311. package/packages/bundled-features/src/sessions/{i18n.ts → web/i18n.ts} +0 -1
  312. package/packages/bundled-features/src/shared/index.ts +6 -1
  313. package/packages/bundled-features/src/shared/purge-files-reaching-subject.ts +10 -2
  314. package/packages/bundled-features/src/shared/web/translate-or-raw.ts +0 -1
  315. package/packages/bundled-features/src/subscription-stripe/feature.ts +2 -0
  316. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +19 -0
  317. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +1 -0
  318. package/packages/bundled-features/src/tags/changes.json +6 -0
  319. package/packages/bundled-features/src/tags/feature.ts +1 -1
  320. package/packages/bundled-features/src/tags/handlers/assign-tag.write.ts +11 -7
  321. package/packages/bundled-features/src/tags/handlers/create-tag.write.ts +1 -1
  322. package/packages/bundled-features/src/tags/handlers/delete-tag.write.ts +4 -1
  323. package/packages/bundled-features/src/tags/handlers/remove-tag.write.ts +1 -1
  324. package/packages/bundled-features/src/tags/handlers/update-tag.write.ts +1 -1
  325. package/packages/bundled-features/src/tags/index.ts +12 -12
  326. package/packages/bundled-features/src/tags/screens.ts +1 -1
  327. package/packages/bundled-features/src/tags/web/client-plugin.tsx +1 -3
  328. package/packages/bundled-features/src/tags/{constants.ts → web/constants.ts} +4 -1
  329. package/packages/bundled-features/src/tags/web/entity-tags.tsx +1 -2
  330. package/packages/bundled-features/src/tags/web/i18n.ts +2 -2
  331. package/packages/bundled-features/src/tags/web/index.ts +2 -3
  332. package/packages/bundled-features/src/tags/web/tag-chip.tsx +0 -1
  333. package/packages/bundled-features/src/tags/web/tag-filter.tsx +1 -2
  334. package/packages/bundled-features/src/tags/web/tag-manager.tsx +5 -4
  335. package/packages/bundled-features/src/tags/web/tag-picker.tsx +0 -1
  336. package/packages/bundled-features/src/tags/web/tag-section.tsx +1 -2
  337. package/packages/bundled-features/src/tags/web/tags-cell.tsx +1 -2
  338. package/packages/bundled-features/src/template-resolver/README.md +1 -1
  339. package/packages/bundled-features/src/template-resolver/api.ts +75 -28
  340. package/packages/bundled-features/src/template-resolver/changes.json +63 -0
  341. package/packages/bundled-features/src/template-resolver/compile-document-body.ts +62 -4
  342. package/packages/bundled-features/src/template-resolver/compile-steps-block.ts +2 -2
  343. package/packages/bundled-features/src/template-resolver/document-ops.ts +5 -5
  344. package/packages/bundled-features/src/template-resolver/document-sanitizer.ts +39 -4
  345. package/packages/bundled-features/src/template-resolver/feature.ts +88 -38
  346. package/packages/bundled-features/src/template-resolver/handlers/by-slug.query.ts +6 -1
  347. package/packages/bundled-features/src/template-resolver/handlers/by-tenant.query.ts +6 -2
  348. package/packages/bundled-features/src/template-resolver/handlers/collection-item.query.ts +1 -1
  349. package/packages/bundled-features/src/template-resolver/handlers/collection-list.query.ts +1 -1
  350. package/packages/bundled-features/src/template-resolver/handlers/collection-set.write.ts +20 -7
  351. package/packages/bundled-features/src/template-resolver/handlers/collection-shared.ts +0 -6
  352. package/packages/bundled-features/src/template-resolver/handlers/copy-locale.write.ts +69 -60
  353. package/packages/bundled-features/src/template-resolver/handlers/diff-to-system.query.ts +7 -1
  354. package/packages/bundled-features/src/template-resolver/handlers/discard-draft.write.ts +37 -14
  355. package/packages/bundled-features/src/template-resolver/handlers/document-base.ts +8 -2
  356. package/packages/bundled-features/src/template-resolver/handlers/document-blocks.query.ts +2 -2
  357. package/packages/bundled-features/src/template-resolver/handlers/export-bundle.query.ts +5 -2
  358. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +4 -2
  359. package/packages/bundled-features/src/template-resolver/handlers/import-bundle.write.ts +37 -28
  360. package/packages/bundled-features/src/template-resolver/handlers/layout-source.query.ts +10 -5
  361. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +5 -2
  362. package/packages/bundled-features/src/template-resolver/handlers/overview.query.ts +132 -70
  363. package/packages/bundled-features/src/template-resolver/handlers/patch-draft.write.ts +106 -97
  364. package/packages/bundled-features/src/template-resolver/handlers/reset-to-system.write.ts +62 -49
  365. package/packages/bundled-features/src/template-resolver/handlers/resource-link-pdf.write.ts +44 -29
  366. package/packages/bundled-features/src/template-resolver/handlers/resource-remove.write.ts +52 -36
  367. package/packages/bundled-features/src/template-resolver/handlers/resource-shared.ts +1 -1
  368. package/packages/bundled-features/src/template-resolver/handlers/resource-upload.write.ts +127 -107
  369. package/packages/bundled-features/src/template-resolver/handlers/send-test-shared.ts +38 -0
  370. package/packages/bundled-features/src/template-resolver/handlers/send-test-status.query.ts +31 -0
  371. package/packages/bundled-features/src/template-resolver/handlers/send-test.write.ts +106 -112
  372. package/packages/bundled-features/src/template-resolver/handlers/set.write.ts +111 -104
  373. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +1 -1
  374. package/packages/bundled-features/src/template-resolver/handlers/template-gates.ts +6 -6
  375. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +2 -2
  376. package/packages/bundled-features/src/template-resolver/handlers/toggle-status.write.ts +56 -28
  377. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +38 -29
  378. package/packages/bundled-features/src/template-resolver/handlers/usage.query.ts +8 -2
  379. package/packages/bundled-features/src/template-resolver/handlers/validate.query.ts +4 -2
  380. package/packages/bundled-features/src/template-resolver/i18n.ts +25 -0
  381. package/packages/bundled-features/src/template-resolver/index.ts +68 -60
  382. package/packages/bundled-features/src/template-resolver/layout-appearance.ts +1 -1
  383. package/packages/bundled-features/src/template-resolver/layout-regions.ts +1 -1
  384. package/packages/bundled-features/src/template-resolver/seeding.ts +16 -7
  385. package/packages/bundled-features/src/template-resolver/store-template-resource.ts +2 -2
  386. package/packages/bundled-features/src/template-resolver/table.ts +1 -1
  387. package/packages/bundled-features/src/template-resolver/template-bundle.ts +2 -2
  388. package/packages/bundled-features/src/template-resolver/template-delivery-policy.ts +82 -0
  389. package/packages/bundled-features/src/template-resolver/template-draft.ts +1 -1
  390. package/packages/bundled-features/src/template-resolver/template-edit-policy.ts +91 -0
  391. package/packages/bundled-features/src/template-resolver/template-meta.ts +2 -2
  392. package/packages/bundled-features/src/template-resolver/template-preview.ts +22 -12
  393. package/packages/bundled-features/src/template-resolver/template-usage.ts +1 -1
  394. package/packages/bundled-features/src/template-resolver/template-validation.ts +33 -12
  395. package/packages/bundled-features/src/template-resolver/testing.ts +2 -2
  396. package/packages/bundled-features/src/template-resolver/user-content-table.ts +1 -1
  397. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +4 -5
  398. package/packages/bundled-features/src/template-resolver/{constants.ts → web/constants.ts} +10 -10
  399. package/packages/bundled-features/src/template-resolver/{document-blocks.ts → web/document-blocks.ts} +3 -2
  400. package/packages/bundled-features/src/template-resolver/web/document-editor-extensions.ts +31 -3
  401. package/packages/bundled-features/src/template-resolver/web/document-editor.tsx +0 -1
  402. package/packages/bundled-features/src/template-resolver/web/document-images.ts +28 -0
  403. package/packages/bundled-features/src/template-resolver/{document-schema.ts → web/document-schema.ts} +5 -1
  404. package/packages/bundled-features/src/template-resolver/{document-steps.ts → web/document-steps.ts} +0 -1
  405. package/packages/bundled-features/src/template-resolver/web/document-tiptap-editor.tsx +48 -11
  406. package/packages/bundled-features/src/template-resolver/web/document-toolbar-blocks.ts +4 -3
  407. package/packages/bundled-features/src/template-resolver/web/editor-handle.ts +1 -2
  408. package/packages/bundled-features/src/template-resolver/web/i18n.ts +8 -1
  409. package/packages/bundled-features/src/template-resolver/web/index.ts +13 -14
  410. package/packages/bundled-features/src/template-resolver/{mail-constants.ts → web/mail-constants.ts} +0 -1
  411. package/packages/bundled-features/src/template-resolver/{pdf-constants.ts → web/pdf-constants.ts} +0 -1
  412. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor-lazy.tsx +0 -1
  413. package/packages/bundled-features/src/template-resolver/web/placeholder-line-editor.tsx +5 -4
  414. package/packages/bundled-features/src/template-resolver/{placeholder-text.ts → web/placeholder-text.ts} +0 -1
  415. package/packages/bundled-features/src/template-resolver/{qualified-names.ts → web/qualified-names.ts} +2 -1
  416. package/packages/bundled-features/src/template-resolver/web/use-stable-by-key.ts +0 -1
  417. package/packages/bundled-features/src/tenant/handlers/add-member.write.ts +1 -1
  418. package/packages/bundled-features/src/tenant/index.ts +7 -7
  419. package/packages/bundled-features/src/tenant/invitation-table.ts +1 -1
  420. package/packages/bundled-features/src/tenant/invited-membership.ts +1 -1
  421. package/packages/bundled-features/src/tenant/last-tenant-admin.ts +1 -1
  422. package/packages/bundled-features/src/tenant/member-role-options.ts +1 -1
  423. package/packages/bundled-features/src/tenant/screens.ts +2 -2
  424. package/packages/bundled-features/src/tenant/web/client-plugin.tsx +1 -2
  425. package/packages/bundled-features/src/tenant/{constants.ts → web/constants.ts} +3 -6
  426. package/packages/bundled-features/src/tenant/web/index.ts +0 -1
  427. package/packages/bundled-features/src/tenant/web/member-roles-cell.tsx +0 -1
  428. package/packages/bundled-features/src/tenant/web/member-status-cell.tsx +0 -1
  429. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +2 -2
  430. package/packages/bundled-features/src/tier-engine/entity.ts +1 -1
  431. package/packages/bundled-features/src/tier-engine/feature.ts +7 -7
  432. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +1 -1
  433. package/packages/bundled-features/src/tier-engine/index.ts +8 -8
  434. package/packages/bundled-features/src/tier-engine/web/client-plugin.tsx +2 -3
  435. package/packages/bundled-features/src/tier-engine/{constants.ts → web/constants.ts} +2 -3
  436. package/packages/bundled-features/src/tier-engine/{i18n.ts → web/i18n.ts} +0 -1
  437. package/packages/bundled-features/src/tier-engine/web/index.ts +0 -1
  438. package/packages/bundled-features/src/user/handlers/create.write.ts +1 -1
  439. package/packages/bundled-features/src/user/handlers/update-roles.ts +1 -1
  440. package/packages/bundled-features/src/user/handlers/update.write.ts +1 -1
  441. package/packages/bundled-features/src/user/index.ts +1 -1
  442. package/packages/bundled-features/src/user/invited-global-roles.ts +1 -1
  443. package/packages/bundled-features/src/user/schema/user.ts +1 -1
  444. package/packages/bundled-features/src/user/{constants.ts → web/constants.ts} +0 -1
  445. package/packages/bundled-features/src/user-data-rights/changes.json +14 -0
  446. package/packages/bundled-features/src/user-data-rights/env.ts +1 -1
  447. package/packages/bundled-features/src/user-data-rights/feature.ts +9 -9
  448. package/packages/bundled-features/src/user-data-rights/index.ts +1 -1
  449. package/packages/bundled-features/src/user-data-rights/lib/resolve-tenant-model.ts +1 -1
  450. package/packages/bundled-features/src/user-data-rights/mail-notifications.ts +1 -1
  451. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +2 -3
  452. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +0 -1
  453. package/packages/bundled-features/src/user-data-rights/{constants.ts → web/constants.ts} +11 -12
  454. package/packages/bundled-features/src/user-data-rights/web/default-translations.ts +91 -0
  455. package/packages/bundled-features/src/user-data-rights/web/i18n.ts +41 -91
  456. package/packages/bundled-features/src/user-data-rights/web/index.ts +1 -2
  457. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +1 -2
  458. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +0 -1
  459. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +0 -1
  460. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +10 -1
  461. package/packages/bundled-features/src/user-profile/feature.ts +2 -2
  462. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +1 -1
  463. package/packages/bundled-features/src/user-profile/index.ts +3 -2
  464. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +2 -3
  465. package/packages/bundled-features/src/user-profile/{constants.ts → web/constants.ts} +0 -1
  466. package/packages/bundled-features/src/user-profile/{i18n.ts → web/i18n.ts} +0 -1
  467. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +2 -3
  468. package/packages/bundled-features/src/waitlist/changes.json +6 -0
  469. package/packages/bundled-features/src/waitlist/entity.ts +1 -1
  470. package/packages/bundled-features/src/waitlist/feature.ts +5 -5
  471. package/packages/bundled-features/src/waitlist/handlers/export-purge.write.ts +3 -3
  472. package/packages/bundled-features/src/waitlist/handlers/invite.write.ts +5 -1
  473. package/packages/bundled-features/src/waitlist/handlers/reject.write.ts +1 -1
  474. package/packages/bundled-features/src/waitlist/handlers/submit.write.ts +3 -3
  475. package/packages/bundled-features/src/waitlist/import.ts +1 -1
  476. package/packages/bundled-features/src/waitlist/index.ts +11 -11
  477. package/packages/bundled-features/src/waitlist/legacy-migrate.ts +1 -1
  478. package/packages/bundled-features/src/waitlist/link-on-signup.ts +1 -1
  479. package/packages/bundled-features/src/waitlist/mail.ts +7 -6
  480. package/packages/bundled-features/src/waitlist/payloads.ts +1 -1
  481. package/packages/bundled-features/src/waitlist/screens.ts +1 -1
  482. package/packages/bundled-features/src/waitlist/{constants.ts → web/constants.ts} +0 -1
  483. package/samples/apps/styleguide/src/features/content/web.tsx +0 -1
  484. package/samples/apps/ui-walkthrough/src/app/client.tsx +2 -0
  485. package/samples/apps/ui-walkthrough/src/app/help-action.tsx +37 -0
  486. package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +17 -1
  487. package/samples/apps/ui-walkthrough/src/app/seed-templates.ts +13 -0
  488. package/samples/apps/ui-walkthrough/src/app/server.ts +2 -1
  489. package/samples/apps/ui-walkthrough/src/app/shell.tsx +6 -0
  490. package/samples/apps/ui-walkthrough/src/app/template-seed-data.ts +20 -0
  491. package/samples/apps/ui-walkthrough/src/features/billing/feature.ts +35 -7
  492. package/samples/apps/ui-walkthrough/src/features/billing/i18n.ts +6 -0
  493. package/samples/apps/ui-walkthrough/src/features/rental/entities.ts +27 -0
  494. package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +120 -2
  495. package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +94 -0
  496. package/samples/apps/ui-walkthrough/src/features/rental/invoice-receive.ts +19 -0
  497. package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +32 -1
  498. package/samples/apps/ui-walkthrough/src/features/rental/qualified-names.ts +5 -0
  499. package/samples/apps/ui-walkthrough/src/features/rental/receipts-upload.ts +70 -0
  500. package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +156 -0
  501. package/samples/apps/ui-walkthrough/src/features/subscription-plans/feature.ts +103 -0
  502. package/samples/apps/ui-walkthrough/src/features/subscription-plans/i18n.ts +36 -0
  503. package/samples/apps/ui-walkthrough/src/features/subscription-plans/index.ts +2 -0
  504. package/samples/apps/ui-walkthrough/src/features/subscription-plans/seed.ts +21 -0
  505. package/samples/apps/ui-walkthrough/src/features/tasks/i18n.ts +8 -0
  506. package/samples/apps/ui-walkthrough/src/run-config.ts +43 -3
  507. package/samples/apps/use-all-bundled/e2e-billing-gallery/server.ts +1 -1
  508. package/samples/apps/use-all-bundled/feature-manifest.json +5 -5
  509. package/samples/apps/use-all-bundled/scripts/check-coverage.ts +1 -1
  510. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +3 -1
  511. package/samples/recipes/compose-stacks/README.md +1 -2
  512. package/samples/recipes/delivery-notifications/README.md +1 -1
  513. package/samples/recipes/embedded/README.md +8 -0
  514. package/samples/recipes/embedded/src/feature.ts +8 -0
  515. package/samples/recipes/embedded/src/handlers/invoice-receive.write.ts +37 -0
  516. package/samples/recipes/embedded/src/screens/invoice-receive.screen.ts +56 -0
  517. package/samples/recipes/legal-pages/README.md +2 -2
  518. package/samples/recipes/legal-pages/src/feature.ts +1 -1
  519. package/samples/recipes/reference-data/src/feature.ts +3 -7
  520. package/packages/bundled-features/src/admin-shell/i18n.ts +0 -54
  521. package/packages/bundled-features/src/audit/i18n.ts +0 -25
  522. package/packages/bundled-features/src/auth-mfa/web/qrcode-browser.d.ts +0 -11
  523. package/packages/bundled-features/src/jobs/i18n.ts +0 -55
  524. package/packages/bundled-features/src/managed-pages/i18n.ts +0 -63
  525. package/packages/bundled-features/src/presets/dsgvo-self-service.ts +0 -35
  526. package/packages/bundled-features/src/user-data-rights/i18n.ts +0 -44
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.379.0",
4
+ "type": "fix",
5
+ "title": "documentExtract projection survives a rebuild",
6
+ "detail": "DOCUMENT_EXTRACT_AGGREGATE_TYPE is exported, and the documentExtract entity projection applies the stored document-extract.* events, so rebuildProjection restores the rows. No event is rewritten."
7
+ },
2
8
  {
3
9
  "version": "0.370.0",
4
10
  "type": "breaking",
@@ -8,6 +8,10 @@ import * as z from "zod";
8
8
  // worker job (kumiko-enterprise LiteParse provider) subscribes to.
9
9
  export const DOCUMENT_INGEST_AGGREGATE_TYPE = "document-ingest";
10
10
 
11
+ // Stream name of stored extract events; differs from the camelCase r.entity name
12
+ // "documentExtract", so the projection replays this stream through an extension.
13
+ export const DOCUMENT_EXTRACT_AGGREGATE_TYPE = "document-extract";
14
+
11
15
  export const DOCUMENT_INGEST_REQUESTED_EVENT_SHORT = "documentIngest.requested" as const;
12
16
 
13
17
  // Qualified name — what ctx.unsafeAppendEvent's `type` actually needs
@@ -4,9 +4,10 @@
4
4
 
5
5
  import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
6
6
  import { documentExtractEntity, documentExtractsTable } from "./entity.ts";
7
+ import { DOCUMENT_EXTRACT_AGGREGATE_TYPE } from "./events.ts";
7
8
 
8
9
  export const documentExtractExecutor = createEventStoreExecutor(
9
10
  documentExtractsTable,
10
11
  documentExtractEntity,
11
- { entityName: "document-extract" },
12
+ { entityName: DOCUMENT_EXTRACT_AGGREGATE_TYPE },
12
13
  );
@@ -4,7 +4,7 @@
4
4
  // hardcoded mime allowlist or size cap — providers register via
5
5
  // EXT_DOCUMENT_INGEST_PROVIDER (see providers.ts).
6
6
 
7
- import { entityEventName } from "@cosmicdrift/kumiko-framework/db";
7
+ import { applyEntityEvent, entityEventName } from "@cosmicdrift/kumiko-framework/db";
8
8
  import {
9
9
  access,
10
10
  createTenantConfig,
@@ -16,8 +16,9 @@ import { normalizeMimeType } from "@cosmicdrift/kumiko-framework/files";
16
16
  import * as z from "zod";
17
17
  import { documentIngestAggregateId } from "./aggregate-id.ts";
18
18
  import { validateDocumentIngestProviderWiring } from "./boot-checks.ts";
19
- import { documentExtractEntity } from "./entity.ts";
19
+ import { documentExtractEntity, documentExtractsTable } from "./entity.ts";
20
20
  import {
21
+ DOCUMENT_EXTRACT_AGGREGATE_TYPE,
21
22
  DOCUMENT_INGEST_AGGREGATE_TYPE,
22
23
  DOCUMENT_INGEST_REQUESTED_EVENT_QN,
23
24
  DOCUMENT_INGEST_REQUESTED_EVENT_SHORT,
@@ -44,9 +45,9 @@ const FILE_REF_CREATED = entityEventName("fileRef", "created");
44
45
  const FILE_REF_RESTORED = entityEventName("fileRef", "restored");
45
46
  const FILE_REF_DELETED = entityEventName("fileRef", "deleted");
46
47
  const FILE_REF_FORGOTTEN = entityEventName("fileRef", "forgotten");
47
- // Executors write under entityName "document-extract" (executor.ts), not the
48
+ // Executors write under DOCUMENT_EXTRACT_AGGREGATE_TYPE (executor.ts), not the
48
49
  // camelCase r.entity() name — the event type follows the executor.
49
- const DOCUMENT_EXTRACT_CREATED = entityEventName("document-extract", "created");
50
+ const DOCUMENT_EXTRACT_CREATED = entityEventName(DOCUMENT_EXTRACT_AGGREGATE_TYPE, "created");
50
51
 
51
52
  type MspApplyContext = Parameters<MultiStreamApplyFn>[2];
52
53
 
@@ -141,6 +142,19 @@ export function createDocumentIngestFoundationFeature() {
141
142
  r.useExtension(EXT_TENANT_DATA, "documentExtract", {
142
143
  destroy: documentExtractTenantDestroyHook,
143
144
  });
145
+ // The implicit projection listens for "documentExtract.*"; stored events are
146
+ // "document-extract.*", so a rebuild would otherwise drop every extract row.
147
+ r.extendEntityProjection("documentExtract", {
148
+ sources: [DOCUMENT_EXTRACT_AGGREGATE_TYPE],
149
+ apply: Object.fromEntries(
150
+ (["created", "updated", "deleted", "forgotten"] as const).map((verb) => [
151
+ entityEventName(DOCUMENT_EXTRACT_AGGREGATE_TYPE, verb),
152
+ async (event, tx) => {
153
+ await applyEntityEvent(event, documentExtractsTable, documentExtractEntity, tx);
154
+ },
155
+ ]),
156
+ ),
157
+ });
144
158
 
145
159
  // No onRegister: resolution happens at boot and per-apply, not on register.
146
160
  r.extendsRegistrar(EXT_DOCUMENT_INGEST_PROVIDER, {});
@@ -8,6 +8,7 @@ export {
8
8
  type IngestPage,
9
9
  } from "./entity.ts";
10
10
  export {
11
+ DOCUMENT_EXTRACT_AGGREGATE_TYPE,
11
12
  DOCUMENT_INGEST_AGGREGATE_TYPE,
12
13
  DOCUMENT_INGEST_REQUESTED_EVENT_QN,
13
14
  DOCUMENT_INGEST_REQUESTED_EVENT_SHORT,
@@ -1,10 +1,4 @@
1
1
  import { defineFeature, type FeatureDefinition } from "@cosmicdrift/kumiko-framework/engine";
2
- import {
3
- FEATURE_TOGGLE_SET_EVENT_NAME,
4
- FeatureToggleHandlers,
5
- FeatureToggleQueries,
6
- TOGGLE_ADMIN_SCREEN_ID,
7
- } from "./constants.ts";
8
2
  import { featureToggleSetSchema } from "./events.ts";
9
3
  import { globalFeatureStateTableMeta } from "./global-feature-state-table.ts";
10
4
  import { listQuery } from "./handlers/list.query.ts";
@@ -12,6 +6,12 @@ import { registeredQuery } from "./handlers/registered.query.ts";
12
6
  import { createSetWriteHandler } from "./handlers/set.write.ts";
13
7
  import { FEATURE_TOGGLES_I18N } from "./i18n.ts";
14
8
  import type { GlobalFeatureToggleRuntime } from "./toggle-runtime.ts";
9
+ import {
10
+ FEATURE_TOGGLE_SET_EVENT_NAME,
11
+ FeatureToggleHandlers,
12
+ FeatureToggleQueries,
13
+ TOGGLE_ADMIN_SCREEN_ID,
14
+ } from "./web/constants.ts";
15
15
 
16
16
  // IMPORTANT: feature-toggles itself is NOT r.toggleable. Making it
17
17
  // toggleable would brick the system — once disabled, no handler of this
@@ -157,7 +157,6 @@ export function createFeatureTogglesFeature(
157
157
  });
158
158
  }
159
159
 
160
- export { FEATURE_TOGGLE_SET_EVENT_NAME, FeatureToggleErrors } from "./constants.ts";
161
160
  export {
162
161
  globalFeatureStateTable,
163
162
  globalFeatureStateTableMeta,
@@ -170,3 +169,4 @@ export {
170
169
  type ToggleSyncSignal,
171
170
  } from "./toggle-runtime.ts";
172
171
  export { createRedisToggleSyncSignal, type RedisToggleSyncSignal } from "./toggle-sync-signal.ts";
172
+ export { FEATURE_TOGGLE_SET_EVENT_NAME, FeatureToggleErrors } from "./web/constants.ts";
@@ -1,7 +1,7 @@
1
1
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import * as z from "zod";
3
- import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../constants.ts";
4
3
  import { globalFeatureStateTable } from "../global-feature-state-table.ts";
4
+ import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../web/constants.ts";
5
5
 
6
6
  // List every row in the global_feature_state table — i.e. every feature
7
7
  // that has ever been explicitly flipped. Features without a row aren't
@@ -1,7 +1,7 @@
1
1
  import { defineQueryHandler, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import * as z from "zod";
3
- import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../constants.ts";
4
3
  import { globalFeatureStateTable } from "../global-feature-state-table.ts";
4
+ import { FEATURE_TOGGLE_CROSS_TENANT_REASON } from "../web/constants.ts";
5
5
 
6
6
  // Inventory of every registered feature, annotated with toggle metadata
7
7
  // and the current effective state. This is the canonical "what's here,
@@ -7,14 +7,14 @@ import {
7
7
  } from "@cosmicdrift/kumiko-framework/errors";
8
8
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
9
9
  import * as z from "zod";
10
+ import { globalFeatureStateTable } from "../global-feature-state-table.ts";
11
+ import type { GlobalFeatureToggleRuntime } from "../toggle-runtime.ts";
10
12
  import {
11
13
  FEATURE_TOGGLE_AGGREGATE_TYPE,
12
14
  FEATURE_TOGGLE_CROSS_TENANT_REASON,
13
15
  FEATURE_TOGGLE_SET_EVENT_NAME,
14
16
  FeatureToggleErrors,
15
- } from "../constants.ts";
16
- import { globalFeatureStateTable } from "../global-feature-state-table.ts";
17
- import type { GlobalFeatureToggleRuntime } from "../toggle-runtime.ts";
17
+ } from "../web/constants.ts";
18
18
 
19
19
  // Factory: binds a runtime accessor to the handler at registration time.
20
20
  // The runtime holds the in-memory snapshot that the dispatcher's gate
@@ -1,10 +1,4 @@
1
1
  export { composeTierResolverWithGlobalToggles } from "./compose-tier-resolver.ts";
2
- export {
3
- FEATURE_TOGGLES_FEATURE,
4
- FeatureToggleHandlers,
5
- FeatureToggleQueries,
6
- TOGGLE_ADMIN_SCREEN_ID,
7
- } from "./constants.ts";
8
2
  export {
9
3
  createFeatureToggleRuntime,
10
4
  createFeatureTogglesFeature,
@@ -18,3 +12,9 @@ export {
18
12
  type RedisToggleSyncSignal,
19
13
  type ToggleSyncSignal,
20
14
  } from "./feature.ts";
15
+ export {
16
+ FEATURE_TOGGLES_FEATURE,
17
+ FeatureToggleHandlers,
18
+ FeatureToggleQueries,
19
+ TOGGLE_ADMIN_SCREEN_ID,
20
+ } from "./web/constants.ts";
@@ -1,7 +1,6 @@
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 { FEATURE_TOGGLES_FEATURE } from "../constants.ts";
3
+ import { FEATURE_TOGGLES_FEATURE } from "./constants.ts";
5
4
  import { defaultTranslations } from "./i18n.ts";
6
5
 
7
6
  export type FeatureTogglesClientOptions = {
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  export const FEATURE_TOGGLES_FEATURE = "feature-toggles" as const;
3
2
 
4
3
  // Fully-qualified event name for feature-toggle changes. Kept as a constant
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
2
 
4
3
  export const defaultTranslations: TranslationsByLocale = {
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  export {
3
2
  type FeatureTogglesClientOptions,
4
3
  featureTogglesClient,
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.379.0",
4
+ "type": "improvement",
5
+ "title": "File uploads in an actionForm, dropzone display for files fields",
6
+ "detail": "A files or images field of an actionForm screen uploads through POST /files with actionForm=<screen QN> and fieldName; the file is stored pending under the screen and the route checks the caller's access to the screen and its handler before writing bytes. New helpers resolveActionFormFileField and listActionFormFileFields (framework/files), bindPendingFileRef takes bindTo (the target entity file field, checked against its accept and maxSize) and registry, and ACTION_FORM_PSEUDO_ENTITY moves to framework/ui-types. New display \"list\" or \"dropzone\" on FilesFieldDef and ImagesFieldDef; the dropzone works in entityEdit and actionForm and maps server error codes to translated texts. Pending actionForm uploads are removed on user forget and by the forget-subject file purge. New i18n keys kumiko.widget.upload.too-large|invalid-type|max-count|remove, kumiko.field.dropzone.* and errors.file.violatesBindTarget (de, es, fr, it included).",
7
+ "migration": "Custom upload screens such as solon document-upload can become an actionForm with a files field and display \"dropzone\". The form's handler must bind every file it keeps: load it with loadPendingFileRef (entityName = the screen QN) and move it onto a record with bindPendingFileRef({ bindTo, registry: ctx.registry }); unbound uploads are treated as the uploader's personal data and removed on forget."
8
+ },
2
9
  {
3
10
  "version": "0.372.0",
4
11
  "type": "breaking",
@@ -26,11 +26,11 @@ import {
26
26
  type FeatureRegistrar,
27
27
  } from "@cosmicdrift/kumiko-framework/engine";
28
28
  import { assertNoWhereRuleInOwnershipWrite } from "../shared/index.ts";
29
- import { DEFAULT_FOLDER_ACCESS, FOLDERS_FEATURE_NAME } from "./constants.ts";
30
29
  import { createFolderAssignmentEntity, folderEntity } from "./entity.ts";
31
30
  import { createClearFolderHandler } from "./handlers/clear-folder.write.ts";
32
31
  import { createDeleteFolderHandler } from "./handlers/delete-folder.write.ts";
33
32
  import { createSetFolderHandler } from "./handlers/set-folder.write.ts";
33
+ import { DEFAULT_FOLDER_ACCESS, FOLDERS_FEATURE_NAME } from "./web/constants.ts";
34
34
 
35
35
  // Opt-in tier-gating: when set, the feature declares itself r.toggleable so the
36
36
  // dispatcher gate + feature-toggles + tier-engine can switch the WHOLE feature
@@ -1,9 +1,9 @@
1
1
  import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import { denyUnlessJoinRowParentVisible } from "../../shared/index.ts";
3
3
  import { folderAssignmentAggregateId } from "../aggregate-id.ts";
4
- import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
5
4
  import { folderAssignmentExecutor } from "../executor.ts";
6
5
  import { type ClearFolderPayload, clearFolderPayloadSchema } from "../schemas.ts";
6
+ import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
7
7
 
8
8
  // clear-folder — removes a host entity from its folder (back to "unfiled").
9
9
  // Idempotent: clearing an entity that isn't in any folder is already the
@@ -2,8 +2,8 @@ import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/
2
2
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
3
3
  import * as z from "zod";
4
4
  import { hostRowIsGone } from "../../shared/index.ts";
5
- import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
6
5
  import { folderAssignmentExecutor, folderExecutor } from "../executor.ts";
6
+ import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
7
7
 
8
8
  const deleteFolderPayloadSchema = z.object({ id: z.uuid() });
9
9
 
@@ -2,9 +2,9 @@ import type { AccessRule, WriteHandlerDef } from "@cosmicdrift/kumiko-framework/
2
2
  import { NotFoundError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
3
3
  import { denyUnlessJoinRowParentVisible } from "../../shared/index.ts";
4
4
  import { folderAssignmentAggregateId } from "../aggregate-id.ts";
5
- import { DEFAULT_FOLDER_ACCESS } from "../constants.ts";
6
5
  import { folderAssignmentExecutor, folderExecutor } from "../executor.ts";
7
6
  import { type SetFolderPayload, setFolderPayloadSchema } from "../schemas.ts";
7
+ import { DEFAULT_FOLDER_ACCESS } from "../web/constants.ts";
8
8
 
9
9
  // set-folder — puts a host entity into a folder. Single-membership: the
10
10
  // assignment id is deterministic over (tenant, entity) WITHOUT folderId, so an
@@ -1,12 +1,4 @@
1
1
  export { folderAssignmentAggregateId } from "./aggregate-id.ts";
2
- export {
3
- DEFAULT_FOLDER_ACCESS,
4
- DEFAULT_FOLDER_ROLES,
5
- FOLDER_SECTION_EXTENSION_NAME,
6
- FOLDERS_FEATURE_NAME,
7
- FoldersHandlers,
8
- FoldersQueries,
9
- } from "./constants.ts";
10
2
  export { folderAssignmentEntity, folderEntity } from "./entity.ts";
11
3
  export {
12
4
  createFoldersFeature,
@@ -20,3 +12,11 @@ export {
20
12
  type SetFolderPayload,
21
13
  setFolderPayloadSchema,
22
14
  } from "./schemas.ts";
15
+ export {
16
+ DEFAULT_FOLDER_ACCESS,
17
+ DEFAULT_FOLDER_ROLES,
18
+ FOLDER_SECTION_EXTENSION_NAME,
19
+ FOLDERS_FEATURE_NAME,
20
+ FoldersHandlers,
21
+ FoldersQueries,
22
+ } from "./web/constants.ts";
@@ -1,7 +1,5 @@
1
- // @runtime client
2
-
3
1
  import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer/web";
4
- import { FOLDER_SECTION_EXTENSION_NAME, FOLDERS_FEATURE_NAME } from "../constants.ts";
2
+ import { FOLDER_SECTION_EXTENSION_NAME, FOLDERS_FEATURE_NAME } from "./constants.ts";
5
3
  import { FolderSection } from "./folder-section.tsx";
6
4
  import { defaultTranslations } from "./i18n.ts";
7
5
 
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // folders bundle constants — feature-name + qualified handler/query names.
3
2
  //
4
3
  // Spec: kumiko-platform/docs/plans/folders-feature.md
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // FolderManager — in-screen folder tree the user manages directly: create root
3
2
  // folders + subfolders, rename, delete, collapse/expand. KPI-agnostic: a host
4
3
  // passes `renderMeta` to hang its own per-folder badges (e.g. money-horse's
@@ -35,7 +34,7 @@ import {
35
34
  } from "@cosmicdrift/kumiko-renderer";
36
35
  import { ChevronRight, File, Folder, type LucideIcon, Pencil, Plus, Trash2 } from "lucide-react";
37
36
  import { type DragEvent, type ReactNode, useEffect, useState } from "react";
38
- import { FoldersHandlers, FoldersQueries } from "../constants.ts";
37
+ import { FoldersHandlers, FoldersQueries } from "./constants.ts";
39
38
  import { buildFolderTree, type FolderNode, type FolderRow } from "./tree.ts";
40
39
 
41
40
  type FolderListResponse = { readonly rows: readonly FolderRow[] };
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // FolderSection — drop-in single-folder picker for ANY entity. Unlike tags
3
2
  // (many-to-many multi-combobox), an entity lives in exactly ONE folder, so this
4
3
  // is a single-select combobox with a "no folder" option plus a compact row to
@@ -19,7 +18,7 @@ import {
19
18
  useTranslation,
20
19
  } from "@cosmicdrift/kumiko-renderer";
21
20
  import { type ReactNode, useState } from "react";
22
- import { FoldersHandlers, FoldersQueries } from "../constants.ts";
21
+ import { FoldersHandlers, FoldersQueries } from "./constants.ts";
23
22
  import { type FolderRow, folderPath } from "./tree.ts";
24
23
 
25
24
  type AssignmentRow = {
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Default translation bundle for the folders UI. foldersClient() hangs it into
3
2
  // the LocaleProvider as a fallback bundle — apps override individual keys via
4
3
  // foldersClient({ translations }). Keys follow `folders.<area>.<slug>`.
@@ -1,6 +1,5 @@
1
- // @runtime client
2
- export { FOLDER_SECTION_EXTENSION_NAME, FoldersHandlers, FoldersQueries } from "../constants.ts";
3
1
  export { foldersClient } from "./client-plugin.tsx";
2
+ export { FOLDER_SECTION_EXTENSION_NAME, FoldersHandlers, FoldersQueries } from "./constants.ts";
4
3
  export { type FolderFiling, type FolderLeaf, FolderManager } from "./folder-manager.tsx";
5
4
  export { FolderSection } from "./folder-section.tsx";
6
5
  export { buildFolderTree, type FolderNode, type FolderRow, folderPath } from "./tree.ts";
@@ -1,4 +1,3 @@
1
- // @runtime client
2
1
  // Pure tree helpers shared by FolderManager (nested render) and FolderSection
3
2
  // (path-labelled options). No React, no IO — folder rows in, structure out, so
4
3
  // both can be unit-tested without a renderer harness.
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "version": "0.379.0",
4
+ "type": "breaking",
5
+ "title": "Form draft content is encrypted per owner",
6
+ "detail": "The jsonb field draft carries personal: { of: \"ownerId\" }, so its content is stored as ciphertext in events and in read_form_drafts; the delete event no longer keeps the plaintext in previous. The PII event backfill (jsonb-objects-v3) encrypts existing events once on the next boot and rebuilds the table. The column type stays jsonb, so there is no schema change.",
7
+ "migration": "Nothing to run; the backfill happens on boot. Code that reads read_form_drafts.draft with raw SQL must decrypt it (decryptPiiFieldValues) or use the form-draft lookup helpers; the get and list queries are unchanged for clients."
8
+ },
2
9
  {
3
10
  "version": "0.370.0",
4
11
  "type": "breaking",
@@ -2,6 +2,7 @@ import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { unsafeReadRetrying } from "@cosmicdrift/kumiko-framework/db";
3
3
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
5
+ import { readStoredDraft } from "../../decrypt-draft.ts";
5
6
  import type { FormDraftBlob } from "../../schemas.ts";
6
7
 
7
8
  export type StaleDraftRow = {
@@ -9,7 +10,10 @@ export type StaleDraftRow = {
9
10
  readonly tenantId: TenantId;
10
11
  readonly ownerId: string;
11
12
  readonly draftKey: string;
12
- readonly draft: FormDraftBlob;
13
+ readonly draft: FormDraftBlob | null;
14
+ // Decryption failed (e.g. KMS outage): `draft: null` then does not mean "empty", so the row must
15
+ // not be deleted — its FileRefs could not be released.
16
+ readonly draftUnreadable?: true;
13
17
  readonly insertedAt: Temporal.Instant;
14
18
  };
15
19
 
@@ -28,30 +32,40 @@ export async function selectStaleDraftsBatch(
28
32
  db: DbConnection,
29
33
  olderThanDays: number,
30
34
  batchSize: number,
35
+ excludeIds: readonly string[] = [],
31
36
  ): Promise<readonly StaleDraftRow[]> {
32
37
  const rows = await unsafeReadRetrying<{
33
38
  id: string;
34
39
  tenant_id: string;
35
40
  owner_id: string;
36
41
  draft_key: string;
37
- draft: FormDraftBlob;
42
+ draft: unknown;
38
43
  inserted_at: Date;
39
44
  }>(
40
45
  db,
41
46
  `SELECT "id", "tenant_id", "owner_id", "draft_key", "draft", "inserted_at" FROM "read_form_drafts"
42
47
  WHERE COALESCE("modified_at", "inserted_at") < now() - ($1::int * interval '1 day')
48
+ AND NOT ("id"::text = ANY($3::text[]))
43
49
  ORDER BY COALESCE("modified_at", "inserted_at") ASC
44
50
  LIMIT $2`,
45
- [olderThanDays, batchSize],
51
+ [olderThanDays, batchSize, [...excludeIds]],
52
+ );
53
+ return Promise.all(
54
+ rows.map(async (row) => {
55
+ const base = {
56
+ id: row.id,
57
+ tenantId: row.tenant_id as TenantId, // @cast-boundary db-row
58
+ ownerId: row.owner_id,
59
+ draftKey: row.draft_key,
60
+ insertedAt: Temporal.Instant.fromEpochMilliseconds(+row.inserted_at), // @cast-boundary db-row
61
+ };
62
+ try {
63
+ return { ...base, draft: await readStoredDraft(row.draft) };
64
+ } catch {
65
+ return { ...base, draft: null, draftUnreadable: true as const };
66
+ }
67
+ }),
46
68
  );
47
- return rows.map((row) => ({
48
- id: row.id,
49
- tenantId: row.tenant_id as TenantId, // @cast-boundary db-row
50
- ownerId: row.owner_id,
51
- draftKey: row.draft_key,
52
- draft: row.draft,
53
- insertedAt: Temporal.Instant.fromEpochMilliseconds(+row.inserted_at), // @cast-boundary db-row
54
- }));
55
69
  }
56
70
 
57
71
  /** Re-check staleness after the select→release window so a freshly saved draft is not deleted. */
@@ -0,0 +1,24 @@
1
+ import { requestContext } from "@cosmicdrift/kumiko-framework/api";
2
+ import {
3
+ configuredPiiSubjectKms,
4
+ decryptPiiFieldValues,
5
+ isPiiCiphertext,
6
+ } from "@cosmicdrift/kumiko-framework/crypto";
7
+ import { type FormDraftBlob, formDraftBlobSchema } from "./schemas.ts";
8
+
9
+ // Raw reads (fetchOne/selectMany/SQL) return the stored column, which is
10
+ // ciphertext once the owner's key exists. The field name is part of the AAD,
11
+ // so it must stay "draft". An erased owner yields the sentinel string, which
12
+ // fails the blob schema and reads as null (no usable draft).
13
+ export async function readStoredDraft(stored: unknown): Promise<FormDraftBlob | null> {
14
+ let plain = stored;
15
+ const kms = configuredPiiSubjectKms();
16
+ if (isPiiCiphertext(stored) && kms) {
17
+ const out = await decryptPiiFieldValues({ draft: stored }, ["draft"], kms, {
18
+ requestId: requestContext.get()?.requestId ?? "form-draft:read",
19
+ });
20
+ plain = out["draft"];
21
+ }
22
+ const parsed = formDraftBlobSchema.safeParse(plain);
23
+ return parsed.success ? parsed.data : null;
24
+ }
@@ -3,7 +3,7 @@ import {
3
3
  createJsonbField,
4
4
  createTextField,
5
5
  } from "@cosmicdrift/kumiko-framework/engine";
6
- import { FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT } from "./constants.ts";
6
+ import { FORM_DRAFT_KEY_MAX_LENGTH, FORM_DRAFT_UNIQUE_KEY_CONSTRAINT } from "./web/constants.ts";
7
7
 
8
8
  // form-draft — a per-user, pre-submission working copy of an in-progress
9
9
  // form (e.g. a wizard-mode EditLayout). `draftKey` is caller-assigned
@@ -37,14 +37,11 @@ export const formDraftEntity = createEntity({
37
37
  // The blob shape is fixed by issue #1889, not left to the caller:
38
38
  // { values: Record<string, unknown>, stepIndex: number, savedAt: string }.
39
39
  // Free-form because `values` mirrors whatever fields the in-progress
40
- // form has, so it can carry arbitrary user-entered PII. NOT given a
41
- // `personal` annotation — the framework's PII field-encryption engine only
42
- // accepts string values (pii-field-encryption.ts throws on a non-string
43
- // field), and this is a jsonb object. Erasure instead runs as a real
44
- // physical row-delete on forget (see form-draft-user-data/hooks.ts),
45
- // not crypto-shredding; `ownerId`'s `subjectRef` annotation alone
46
- // already satisfies the GDPR-hook-coverage boot guard.
47
- draft: createJsonbField(),
40
+ // form has, so it can carry arbitrary user-entered PII. Encrypted under
41
+ // the owner's key (jsonb ciphertext scalar in the row and in every event
42
+ // that carries it, `previous` of delete included), so forgetting the
43
+ // owner shreds all copies.
44
+ draft: createJsonbField({ personal: { of: "ownerId" } }),
48
45
  },
49
46
  // One draft per (tenant, owner, draftKey) — save() is an upsert keyed on
50
47
  // this index (see handlers/save.write.ts); a resume query must find at
@@ -7,13 +7,13 @@
7
7
 
8
8
  import type { DbConnection } from "@cosmicdrift/kumiko-framework/db";
9
9
  import { defineFeature, type FeatureRegistrar } from "@cosmicdrift/kumiko-framework/engine";
10
- import { FORM_DRAFT_FEATURE_NAME } from "./constants.ts";
11
10
  import { formDraftEntity } from "./entity.ts";
12
11
  import { cleanupDraftsJob, formDraftRetentionDaysConfig } from "./handlers/cleanup.job.ts";
13
12
  import { discardDraftWrite } from "./handlers/discard.write.ts";
14
13
  import { getDraftQuery } from "./handlers/get.query.ts";
15
14
  import { listDraftsQuery } from "./handlers/list.query.ts";
16
15
  import { saveDraftWrite } from "./handlers/save.write.ts";
16
+ import { FORM_DRAFT_FEATURE_NAME } from "./web/constants.ts";
17
17
 
18
18
  const CLEANUP_ESCAPE_HATCH_REASON = "purges stale drafts of every tenant";
19
19
 
@@ -126,14 +126,27 @@ export async function deleteStaleDraftsBatch(
126
126
  db: DbConnection,
127
127
  retentionDays: number,
128
128
  log: AppContext["log"],
129
- ): Promise<{ readonly deletedRows: readonly StaleDraftRow[]; readonly skippedCount: number }> {
129
+ ): Promise<{
130
+ readonly deletedRows: readonly StaleDraftRow[];
131
+ readonly skippedCount: number;
132
+ readonly deferredIds: readonly string[];
133
+ }> {
130
134
  const deletedRows: StaleDraftRow[] = [];
135
+ const deferredIds: string[] = [];
131
136
  let skippedCount = 0;
132
137
  const byId = new Map(batch.map((row) => [row.id, row]));
133
138
  for (const [tenantId, ids] of groupStaleDraftIdsByTenant(batch)) {
134
139
  const systemUser = createSystemUser(tenantId);
135
140
  const tenantDb = createTenantDb({ db, tenantId, mode: "system" });
136
141
  for (const id of ids) {
142
+ // skip: an unreadable blob hides its FileRefs; deleting now would orphan them, so the next run retries.
143
+ if (byId.get(id)?.draftUnreadable) {
144
+ log?.warn?.(
145
+ `[form-draft:cleanup] draft id=${id} tenant=${tenantId} could not be decrypted — kept for the next run`,
146
+ );
147
+ deferredIds.push(id);
148
+ continue;
149
+ }
137
150
  // Race: user may have saved between select and here — skip if no longer stale.
138
151
  if (!(await isDraftStillStale(db, tenantId, id, retentionDays))) {
139
152
  skippedCount++;
@@ -150,7 +163,7 @@ export async function deleteStaleDraftsBatch(
150
163
  }
151
164
  }
152
165
  }
153
- return { deletedRows, skippedCount };
166
+ return { deletedRows, skippedCount, deferredIds };
154
167
  }
155
168
 
156
169
  export async function cleanupDraftsJob(
@@ -181,9 +194,12 @@ export async function cleanupDraftsJob(
181
194
  const fileProviderResolver = ctx._fileProviderResolver;
182
195
 
183
196
  let deleted = 0;
197
+ const deferred = new Set<string>();
184
198
  while (true) {
185
199
  if (ctx.signal?.aborted) break;
186
- const batch = await selectStaleDraftsBatch(db, retentionDays, DEFAULT_BATCH_SIZE);
200
+ const batch = await selectStaleDraftsBatch(db, retentionDays, DEFAULT_BATCH_SIZE, [
201
+ ...deferred,
202
+ ]);
187
203
  if (batch.length === 0) break;
188
204
 
189
205
  // Rows span arbitrary tenants (this job sweeps the whole table under
@@ -193,12 +209,13 @@ export async function cleanupDraftsJob(
193
209
  // entirely for rows with no FileRefs in the blob, the common case.
194
210
  // Delete first (with staleness re-check), then release binaries from rows
195
211
  // that actually disappeared — never release a draft the user just saved.
196
- const { deletedRows, skippedCount } = await deleteStaleDraftsBatch(
212
+ const { deletedRows, skippedCount, deferredIds } = await deleteStaleDraftsBatch(
197
213
  batch,
198
214
  db,
199
215
  retentionDays,
200
216
  ctx.log,
201
217
  );
218
+ for (const id of deferredIds) deferred.add(id);
202
219
  for (const row of deletedRows) {
203
220
  await releaseRowFileRefs(row, db, fileProviderResolver, ctx.log);
204
221
  }
@@ -206,7 +223,11 @@ export async function cleanupDraftsJob(
206
223
  // A skipped row is no longer stale, so the next select drops it — a fully
207
224
  // skipped batch still makes progress. Only a batch with neither deletes nor
208
225
  // skips (all failed) would reselect the same rows forever.
209
- if (deletedRows.length + skippedCount === 0 || batch.length < DEFAULT_BATCH_SIZE) break;
226
+ if (
227
+ deletedRows.length + skippedCount + deferredIds.length === 0 ||
228
+ batch.length < DEFAULT_BATCH_SIZE
229
+ )
230
+ break;
210
231
  }
211
232
  ctx.log?.info?.(`[form-draft:cleanup] deleted=${deleted} retentionDays=${retentionDays}`);
212
233
  }
@@ -1,12 +1,12 @@
1
1
  import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
2
2
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { fileRefEntity, fileRefsTable } from "@cosmicdrift/kumiko-framework/files";
4
- import { FORM_DRAFT_ACCESS } from "../constants.ts";
5
4
  import { filterOwnedFileRefs } from "../db/queries/owned-file-refs.ts";
6
5
  import { formDraftExecutor } from "../executor.ts";
7
6
  import { lookupDraft } from "../lookup.ts";
8
7
  import { collectDraftFileRefKeys, releaseDraftFileRefs } from "../release-file-refs.ts";
9
8
  import { discardDraftPayloadSchema } from "../schemas.ts";
9
+ import { FORM_DRAFT_ACCESS } from "../web/constants.ts";
10
10
 
11
11
  // Same construction as file-routes.ts/user-data-rights-defaults' fileRef
12
12
  // hook — self-contained (table + entity), no registry needed. `.forget()`