@cosmicdrift/kumiko-samples 0.385.0 → 0.387.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 (395) hide show
  1. package/LICENSE +21 -57
  2. package/README.md +1 -1
  3. package/package.json +2 -2
  4. package/packages/bundled-features/package.json +2 -2
  5. package/packages/bundled-features/src/agent-tools/tool-catalog.ts +1 -1
  6. package/packages/bundled-features/src/agent-tools/tool-dispatch.ts +0 -2
  7. package/packages/bundled-features/src/audit/screens.ts +1 -1
  8. package/packages/bundled-features/src/auth-email-password/auth-user-row.ts +10 -10
  9. package/packages/bundled-features/src/auth-email-password/feature.ts +6 -6
  10. package/packages/bundled-features/src/auth-email-password/handlers/change-password.write.ts +3 -3
  11. package/packages/bundled-features/src/auth-email-password/handlers/confirm-token-flow.ts +5 -5
  12. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept-with-login.write.ts +1 -1
  13. package/packages/bundled-features/src/auth-email-password/handlers/invite-accept.write.ts +18 -18
  14. package/packages/bundled-features/src/auth-email-password/handlers/invite-create.write.ts +12 -12
  15. package/packages/bundled-features/src/auth-email-password/handlers/invite-info.query.ts +1 -1
  16. package/packages/bundled-features/src/auth-email-password/handlers/invite-signup-complete.write.ts +24 -26
  17. package/packages/bundled-features/src/auth-email-password/handlers/login.write.ts +1 -1
  18. package/packages/bundled-features/src/auth-email-password/handlers/self-registration-status.query.ts +1 -1
  19. package/packages/bundled-features/src/auth-email-password/handlers/signup-confirm.write.ts +34 -37
  20. package/packages/bundled-features/src/auth-email-password/handlers/signup-request.write.ts +6 -7
  21. package/packages/bundled-features/src/auth-email-password/handlers/switch-tenant-mfa-gate.write.ts +1 -5
  22. package/packages/bundled-features/src/auth-email-password/index.ts +5 -5
  23. package/packages/bundled-features/src/auth-email-password/lockout-store.ts +1 -1
  24. package/packages/bundled-features/src/auth-email-password/seeding.ts +63 -66
  25. package/packages/bundled-features/src/auth-email-password/signup-token-store.ts +8 -8
  26. package/packages/bundled-features/src/auth-email-password/testing.ts +3 -3
  27. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +57 -57
  28. package/packages/bundled-features/src/auth-email-password/web/auth-form-primitives.tsx +14 -14
  29. package/packages/bundled-features/src/auth-email-password/web/auth-gate.tsx +15 -16
  30. package/packages/bundled-features/src/auth-email-password/web/client-plugin.ts +11 -12
  31. package/packages/bundled-features/src/auth-email-password/web/confirm-account-unlock-screen.tsx +1 -1
  32. package/packages/bundled-features/src/auth-email-password/web/constants.ts +3 -3
  33. package/packages/bundled-features/src/auth-email-password/web/default-topbar-actions.tsx +14 -14
  34. package/packages/bundled-features/src/auth-email-password/web/forgot-password-screen.tsx +11 -11
  35. package/packages/bundled-features/src/auth-email-password/web/index.ts +5 -5
  36. package/packages/bundled-features/src/auth-email-password/web/invite-accept-screen.tsx +17 -17
  37. package/packages/bundled-features/src/auth-email-password/web/login-screen.tsx +3 -4
  38. package/packages/bundled-features/src/auth-email-password/web/reset-password-screen.tsx +16 -17
  39. package/packages/bundled-features/src/auth-email-password/web/session.tsx +34 -34
  40. package/packages/bundled-features/src/auth-email-password/web/signup-complete-screen.tsx +3 -3
  41. package/packages/bundled-features/src/auth-email-password/web/signup-screen.tsx +14 -14
  42. package/packages/bundled-features/src/auth-email-password/web/tenant-switcher.tsx +26 -27
  43. package/packages/bundled-features/src/auth-email-password/web/use-shell-user.ts +12 -13
  44. package/packages/bundled-features/src/auth-email-password/web/user-menu.tsx +17 -18
  45. package/packages/bundled-features/src/auth-email-password/web/verify-email-screen.tsx +11 -12
  46. package/packages/bundled-features/src/auth-foundation/boot-checks.ts +4 -4
  47. package/packages/bundled-features/src/auth-foundation/resolve-anonymous-access.ts +4 -4
  48. package/packages/bundled-features/src/auth-foundation/types.ts +2 -2
  49. package/packages/bundled-features/src/auth-mfa/handlers/disable.write.ts +3 -3
  50. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm-preauth.write.ts +4 -4
  51. package/packages/bundled-features/src/auth-mfa/handlers/enable-confirm.write.ts +2 -2
  52. package/packages/bundled-features/src/auth-mfa/handlers/enable-start-preauth.write.ts +1 -1
  53. package/packages/bundled-features/src/auth-mfa/handlers/reencrypt.job.ts +1 -1
  54. package/packages/bundled-features/src/auth-mfa/handlers/regenerate-recovery.write.ts +5 -5
  55. package/packages/bundled-features/src/auth-mfa/handlers/verify.write.ts +1 -1
  56. package/packages/bundled-features/src/auth-mfa/token-secrets.ts +1 -1
  57. package/packages/bundled-features/src/auth-mfa/web/client-plugin.ts +2 -2
  58. package/packages/bundled-features/src/auth-mfa/web/i18n.ts +3 -3
  59. package/packages/bundled-features/src/auth-mfa/web/index.ts +4 -4
  60. package/packages/bundled-features/src/auth-mfa/web/mfa-client.ts +17 -16
  61. package/packages/bundled-features/src/auth-mfa/web/mfa-verify-screen.tsx +6 -6
  62. package/packages/bundled-features/src/billing-foundation/aggregate-id.ts +10 -11
  63. package/packages/bundled-features/src/billing-foundation/entities.ts +27 -27
  64. package/packages/bundled-features/src/billing-foundation/events.ts +22 -21
  65. package/packages/bundled-features/src/billing-foundation/feature.ts +42 -43
  66. package/packages/bundled-features/src/billing-foundation/get-subscription-for-tenant.ts +3 -5
  67. package/packages/bundled-features/src/billing-foundation/handlers/create-checkout-session.write.ts +18 -17
  68. package/packages/bundled-features/src/billing-foundation/handlers/create-portal-session.write.ts +11 -12
  69. package/packages/bundled-features/src/billing-foundation/handlers/list-subscriptions.query.ts +4 -4
  70. package/packages/bundled-features/src/billing-foundation/handlers/process-event.write.ts +20 -20
  71. package/packages/bundled-features/src/billing-foundation/projection.ts +38 -37
  72. package/packages/bundled-features/src/billing-foundation/subscription-tier-sync.ts +3 -3
  73. package/packages/bundled-features/src/billing-foundation/tenant-destroy-hook.ts +7 -8
  74. package/packages/bundled-features/src/billing-foundation/types.ts +64 -65
  75. package/packages/bundled-features/src/billing-foundation/web/billing-plans-panel.tsx +4 -4
  76. package/packages/bundled-features/src/billing-foundation/webhook-handler.ts +1 -1
  77. package/packages/bundled-features/src/cap-counter/aggregate-id.ts +8 -9
  78. package/packages/bundled-features/src/cap-counter/constants.ts +11 -12
  79. package/packages/bundled-features/src/cap-counter/enforce-cap.ts +64 -67
  80. package/packages/bundled-features/src/cap-counter/entity.ts +29 -29
  81. package/packages/bundled-features/src/cap-counter/feature.ts +34 -35
  82. package/packages/bundled-features/src/cap-counter/handlers/increment-rolling.write.ts +31 -31
  83. package/packages/bundled-features/src/cap-counter/handlers/mark-soft-warned.write.ts +4 -5
  84. package/packages/bundled-features/src/cap-counter/stock-cap-guard.ts +1 -1
  85. package/packages/bundled-features/src/cap-counter/with-cap-enforcement.ts +3 -5
  86. package/packages/bundled-features/src/cap-overview/handlers/caps-usage.query.ts +1 -3
  87. package/packages/bundled-features/src/cap-overview/handlers/tenant-caps-list.query.ts +1 -1
  88. package/packages/bundled-features/src/channel-email/smtp-transport.ts +34 -31
  89. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +3 -4
  90. package/packages/bundled-features/src/compliance-profiles/feature.ts +15 -16
  91. package/packages/bundled-features/src/compliance-profiles/handlers/for-tenant.query.ts +3 -6
  92. package/packages/bundled-features/src/compliance-profiles/handlers/list-profiles.query.ts +5 -5
  93. package/packages/bundled-features/src/compliance-profiles/handlers/needs-profile.query.ts +4 -4
  94. package/packages/bundled-features/src/compliance-profiles/handlers/set-profile.write.ts +13 -14
  95. package/packages/bundled-features/src/compliance-profiles/handlers/sub-processors.query.ts +9 -11
  96. package/packages/bundled-features/src/compliance-profiles/resolve-for-tenant.ts +7 -7
  97. package/packages/bundled-features/src/compliance-profiles/schema/profile-selection.ts +18 -23
  98. package/packages/bundled-features/src/compliance-profiles/seeding.ts +14 -15
  99. package/packages/bundled-features/src/compliance-profiles-ops/handlers/tenants-missing-profile.query.ts +3 -3
  100. package/packages/bundled-features/src/compliance-profiles-ops/index.ts +2 -2
  101. package/packages/bundled-features/src/config/handlers/readiness.query.ts +7 -7
  102. package/packages/bundled-features/src/config/handlers/reencrypt.job.ts +4 -5
  103. package/packages/bundled-features/src/config/handlers/set.write.ts +4 -4
  104. package/packages/bundled-features/src/config/resolver.ts +4 -4
  105. package/packages/bundled-features/src/config/table.ts +10 -10
  106. package/packages/bundled-features/src/config/write-helpers.ts +1 -1
  107. package/packages/bundled-features/src/crypto-shredding/handlers/forget-subject.write.ts +13 -12
  108. package/packages/bundled-features/src/custom-fields/aggregate-id.ts +16 -17
  109. package/packages/bundled-features/src/custom-fields/entity.ts +49 -47
  110. package/packages/bundled-features/src/custom-fields/events.ts +7 -8
  111. package/packages/bundled-features/src/custom-fields/feature.ts +70 -72
  112. package/packages/bundled-features/src/custom-fields/handlers/clear-custom-field.write.ts +9 -8
  113. package/packages/bundled-features/src/custom-fields/handlers/define-tenant-field.write.ts +28 -26
  114. package/packages/bundled-features/src/custom-fields/handlers/delete-system-field.write.ts +6 -7
  115. package/packages/bundled-features/src/custom-fields/handlers/delete-tenant-field.write.ts +12 -13
  116. package/packages/bundled-features/src/custom-fields/handlers/set-custom-field.write.ts +25 -28
  117. package/packages/bundled-features/src/custom-fields/handlers/update-tenant-field.write.ts +6 -6
  118. package/packages/bundled-features/src/custom-fields/lib/field-access.ts +2 -2
  119. package/packages/bundled-features/src/custom-fields/lib/parse-serialized-field.ts +1 -1
  120. package/packages/bundled-features/src/custom-fields/lib/quota.ts +1 -1
  121. package/packages/bundled-features/src/custom-fields/lib/value-schema.ts +10 -12
  122. package/packages/bundled-features/src/custom-fields/run-retention.ts +3 -3
  123. package/packages/bundled-features/src/custom-fields/schemas.ts +14 -14
  124. package/packages/bundled-features/src/custom-fields/web/client-plugin.tsx +2 -5
  125. package/packages/bundled-features/src/custom-fields/web/constants.ts +2 -2
  126. package/packages/bundled-features/src/custom-fields/web/custom-fields-form-section.tsx +26 -26
  127. package/packages/bundled-features/src/custom-fields/wire-for-entity.ts +65 -67
  128. package/packages/bundled-features/src/custom-fields/wire-user-data-rights.ts +3 -3
  129. package/packages/bundled-features/src/data-retention/_internal/parse-override.ts +2 -3
  130. package/packages/bundled-features/src/data-retention/feature.ts +11 -18
  131. package/packages/bundled-features/src/data-retention/handlers/policy-for.query.ts +6 -6
  132. package/packages/bundled-features/src/data-retention/keep-for.ts +17 -17
  133. package/packages/bundled-features/src/data-retention/override-schema.ts +13 -15
  134. package/packages/bundled-features/src/data-retention/presets.ts +18 -23
  135. package/packages/bundled-features/src/data-retention/resolve-for-tenant.ts +1 -1
  136. package/packages/bundled-features/src/data-retention/resolve-tenant-preset.ts +17 -16
  137. package/packages/bundled-features/src/data-retention/resolver.ts +33 -32
  138. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +71 -58
  139. package/packages/bundled-features/src/data-retention/schema/tenant-retention-override.ts +13 -11
  140. package/packages/bundled-features/src/delivery/feature.ts +3 -3
  141. package/packages/bundled-features/src/delivery/handlers/log.query.ts +1 -1
  142. package/packages/bundled-features/src/delivery/tables.ts +9 -8
  143. package/packages/bundled-features/src/delivery/unsubscribe.ts +4 -4
  144. package/packages/bundled-features/src/delivery/upsert-preference.ts +3 -4
  145. package/packages/bundled-features/src/document-ingest-foundation/entity.ts +5 -5
  146. package/packages/bundled-features/src/document-ingest-foundation/events.ts +2 -2
  147. package/packages/bundled-features/src/document-ingest-foundation/feature.ts +2 -2
  148. package/packages/bundled-features/src/document-ingest-foundation/pages.ts +1 -1
  149. package/packages/bundled-features/src/document-ingest-foundation/tenant-destroy-hook.ts +4 -4
  150. package/packages/bundled-features/src/feature-toggles/compose-tier-resolver.ts +1 -1
  151. package/packages/bundled-features/src/feature-toggles/feature.ts +1 -1
  152. package/packages/bundled-features/src/feature-toggles/global-feature-state-table.ts +1 -1
  153. package/packages/bundled-features/src/feature-toggles/handlers/registered.query.ts +5 -5
  154. package/packages/bundled-features/src/feature-toggles/toggle-runtime.ts +1 -1
  155. package/packages/bundled-features/src/feature-toggles/toggle-sync-signal.ts +1 -1
  156. package/packages/bundled-features/src/feature-toggles/web/constants.ts +1 -1
  157. package/packages/bundled-features/src/file-derivatives/feature.ts +2 -2
  158. package/packages/bundled-features/src/file-derivatives/handlers/public-variant.query.ts +1 -1
  159. package/packages/bundled-features/src/file-derivatives/presets.ts +1 -1
  160. package/packages/bundled-features/src/file-foundation/feature.ts +6 -6
  161. package/packages/bundled-features/src/file-provider-inmemory/feature.ts +16 -16
  162. package/packages/bundled-features/src/file-provider-s3/feature.ts +16 -16
  163. package/packages/bundled-features/src/file-provider-s3/lib/s3-provider.ts +6 -6
  164. package/packages/bundled-features/src/files/feature.ts +6 -6
  165. package/packages/bundled-features/src/files-tenant-data/handlers/sweep-orphaned-derivatives.job.ts +5 -5
  166. package/packages/bundled-features/src/files-tenant-data/hooks.ts +24 -26
  167. package/packages/bundled-features/src/files-tenant-data/index.ts +1 -1
  168. package/packages/bundled-features/src/folders/feature.ts +1 -1
  169. package/packages/bundled-features/src/folders/web/folder-manager.tsx +2 -2
  170. package/packages/bundled-features/src/folders/web/tree.ts +5 -5
  171. package/packages/bundled-features/src/form-draft/db/queries/cleanup.ts +1 -1
  172. package/packages/bundled-features/src/form-draft/db/queries/owned-file-refs.ts +1 -1
  173. package/packages/bundled-features/src/form-draft/entity.ts +3 -3
  174. package/packages/bundled-features/src/form-draft/feature.ts +4 -5
  175. package/packages/bundled-features/src/form-draft/handlers/discard.write.ts +1 -1
  176. package/packages/bundled-features/src/form-draft/release-file-refs.ts +6 -6
  177. package/packages/bundled-features/src/form-draft/schemas.ts +3 -3
  178. package/packages/bundled-features/src/form-draft/web/constants.ts +0 -2
  179. package/packages/bundled-features/src/inbound-mail-foundation/aggregate-id.ts +19 -19
  180. package/packages/bundled-features/src/inbound-mail-foundation/connect-routes.ts +4 -3
  181. package/packages/bundled-features/src/inbound-mail-foundation/constants.ts +30 -33
  182. package/packages/bundled-features/src/inbound-mail-foundation/entities.ts +47 -48
  183. package/packages/bundled-features/src/inbound-mail-foundation/events.ts +54 -50
  184. package/packages/bundled-features/src/inbound-mail-foundation/feature.ts +39 -39
  185. package/packages/bundled-features/src/inbound-mail-foundation/handlers/account-state.ts +8 -8
  186. package/packages/bundled-features/src/inbound-mail-foundation/handlers/connect-account.write.ts +25 -26
  187. package/packages/bundled-features/src/inbound-mail-foundation/handlers/disconnect-account.write.ts +7 -7
  188. package/packages/bundled-features/src/inbound-mail-foundation/handlers/ingest-message.write.ts +50 -51
  189. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-accounts.query.ts +8 -8
  190. package/packages/bundled-features/src/inbound-mail-foundation/handlers/list-messages.query.ts +10 -10
  191. package/packages/bundled-features/src/inbound-mail-foundation/handlers/scope-visibility.ts +3 -4
  192. package/packages/bundled-features/src/inbound-mail-foundation/handlers/update-account.write.ts +11 -11
  193. package/packages/bundled-features/src/inbound-mail-foundation/oauth-state.ts +16 -15
  194. package/packages/bundled-features/src/inbound-mail-foundation/projection.ts +31 -29
  195. package/packages/bundled-features/src/inbound-mail-foundation/provider-factory.ts +9 -9
  196. package/packages/bundled-features/src/inbound-mail-foundation/retention-sweep.ts +45 -41
  197. package/packages/bundled-features/src/inbound-mail-foundation/tenant-destroy-hook.ts +14 -16
  198. package/packages/bundled-features/src/inbound-mail-foundation/types.ts +66 -67
  199. package/packages/bundled-features/src/inbound-mail-foundation/watch-supervisor.ts +69 -68
  200. package/packages/bundled-features/src/inbound-provider-imap/credential-document.ts +13 -13
  201. package/packages/bundled-features/src/inbound-provider-imap/feature.ts +42 -40
  202. package/packages/bundled-features/src/inbound-provider-imap/imap-client.ts +20 -19
  203. package/packages/bundled-features/src/inbound-provider-inmemory/feature.ts +21 -21
  204. package/packages/bundled-features/src/jobs/db/queries/retention.ts +2 -2
  205. package/packages/bundled-features/src/jobs/db/queries/stale-run-sweep.ts +3 -3
  206. package/packages/bundled-features/src/jobs/events.ts +1 -1
  207. package/packages/bundled-features/src/jobs/feature.ts +6 -7
  208. package/packages/bundled-features/src/jobs/handlers/detail.query.ts +4 -4
  209. package/packages/bundled-features/src/jobs/handlers/list.query.ts +1 -1
  210. package/packages/bundled-features/src/jobs/handlers/projection-rebuild.job.ts +1 -1
  211. package/packages/bundled-features/src/jobs/handlers/reindex-entity.job.ts +1 -1
  212. package/packages/bundled-features/src/jobs/handlers/retry.write.ts +1 -1
  213. package/packages/bundled-features/src/jobs/job-instant.ts +1 -1
  214. package/packages/bundled-features/src/jobs/job-run-logger.ts +14 -15
  215. package/packages/bundled-features/src/jobs/job-run-table.ts +3 -3
  216. package/packages/bundled-features/src/jobs/screens.ts +1 -1
  217. package/packages/bundled-features/src/jobs/tenant-job-failure-table.ts +1 -1
  218. package/packages/bundled-features/src/jobs/tenant-job-run-table.ts +1 -1
  219. package/packages/bundled-features/src/ledger/entity.ts +5 -5
  220. package/packages/bundled-features/src/ledger/feature.ts +3 -3
  221. package/packages/bundled-features/src/ledger/handlers/confirm-schedule-period.write.ts +3 -3
  222. package/packages/bundled-features/src/ledger/recurring.ts +12 -12
  223. package/packages/bundled-features/src/ledger/schemas.ts +1 -1
  224. package/packages/bundled-features/src/ledger/web/constants.ts +2 -2
  225. package/packages/bundled-features/src/ledger/web/index.ts +7 -7
  226. package/packages/bundled-features/src/legal-pages/feature.ts +40 -41
  227. package/packages/bundled-features/src/legal-pages/markdown.ts +3 -3
  228. package/packages/bundled-features/src/legal-pages/web/client-plugin.ts +23 -24
  229. package/packages/bundled-features/src/legal-pages/web/index.ts +0 -2
  230. package/packages/bundled-features/src/mail-foundation/feature.ts +26 -27
  231. package/packages/bundled-features/src/mail-transport-inmemory/feature.ts +27 -28
  232. package/packages/bundled-features/src/mail-transport-smtp/feature.ts +20 -20
  233. package/packages/bundled-features/src/managed-pages/branding.ts +6 -6
  234. package/packages/bundled-features/src/managed-pages/feature.ts +62 -62
  235. package/packages/bundled-features/src/managed-pages/handlers/by-slug.query.ts +5 -6
  236. package/packages/bundled-features/src/managed-pages/handlers/by-tenant-published.query.ts +8 -8
  237. package/packages/bundled-features/src/managed-pages/handlers/set.write.ts +5 -7
  238. package/packages/bundled-features/src/managed-pages/screens/page-screens.ts +11 -11
  239. package/packages/bundled-features/src/managed-pages/seeding.ts +8 -8
  240. package/packages/bundled-features/src/managed-pages/table.ts +16 -15
  241. package/packages/bundled-features/src/managed-pages/web/client-plugin.tsx +6 -6
  242. package/packages/bundled-features/src/managed-pages/web/i18n.ts +1 -1
  243. package/packages/bundled-features/src/notes-history/entity.ts +4 -4
  244. package/packages/bundled-features/src/notes-history/feature.ts +2 -2
  245. package/packages/bundled-features/src/notes-history-user-data/hooks.ts +1 -1
  246. package/packages/bundled-features/src/page-render/layout.ts +9 -9
  247. package/packages/bundled-features/src/page-render/markdown.ts +11 -11
  248. package/packages/bundled-features/src/page-render/security-headers.ts +7 -6
  249. package/packages/bundled-features/src/personal-access-tokens/feature.ts +5 -5
  250. package/packages/bundled-features/src/personal-access-tokens/roles.ts +2 -2
  251. package/packages/bundled-features/src/readiness/handlers/status.query.ts +3 -3
  252. package/packages/bundled-features/src/renderer-foundation/api.ts +12 -13
  253. package/packages/bundled-features/src/renderer-foundation/constants.ts +2 -2
  254. package/packages/bundled-features/src/renderer-foundation/feature.ts +7 -7
  255. package/packages/bundled-features/src/renderer-foundation/types.ts +11 -12
  256. package/packages/bundled-features/src/secrets/feature.ts +9 -9
  257. package/packages/bundled-features/src/secrets/web/constants.ts +2 -2
  258. package/packages/bundled-features/src/seo/feature.ts +3 -3
  259. package/packages/bundled-features/src/sessions/constants.ts +1 -1
  260. package/packages/bundled-features/src/sessions/feature.ts +9 -9
  261. package/packages/bundled-features/src/sessions/handlers/revoke-all-for-user.write.ts +2 -2
  262. package/packages/bundled-features/src/sessions/handlers/revoke-all-others.write.ts +2 -2
  263. package/packages/bundled-features/src/sessions/handlers/revoke.write.ts +1 -1
  264. package/packages/bundled-features/src/sessions/schema/user-session.ts +4 -4
  265. package/packages/bundled-features/src/sessions/screens.ts +2 -2
  266. package/packages/bundled-features/src/sessions/session-callbacks.ts +2 -2
  267. package/packages/bundled-features/src/sessions/session-revoked-event.ts +2 -2
  268. package/packages/bundled-features/src/shared/assert-no-where-rule-in-ownership-write.ts +1 -1
  269. package/packages/bundled-features/src/shared/decrypt-stored-pii.ts +1 -1
  270. package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +1 -1
  271. package/packages/bundled-features/src/shared/map-with-concurrency.ts +5 -4
  272. package/packages/bundled-features/src/shared/parent-visibility.ts +2 -2
  273. package/packages/bundled-features/src/shared/password-hashing.ts +1 -1
  274. package/packages/bundled-features/src/shared/signup-handover.ts +1 -2
  275. package/packages/bundled-features/src/shared/single-use-token-store.ts +1 -1
  276. package/packages/bundled-features/src/subscription-mollie/constants.ts +15 -17
  277. package/packages/bundled-features/src/subscription-mollie/feature.ts +41 -42
  278. package/packages/bundled-features/src/subscription-mollie/index.ts +3 -3
  279. package/packages/bundled-features/src/subscription-mollie/plugin-methods.ts +17 -16
  280. package/packages/bundled-features/src/subscription-mollie/verify-webhook.ts +34 -34
  281. package/packages/bundled-features/src/subscription-stripe/constants.ts +4 -6
  282. package/packages/bundled-features/src/subscription-stripe/feature.ts +44 -43
  283. package/packages/bundled-features/src/subscription-stripe/index.ts +6 -6
  284. package/packages/bundled-features/src/subscription-stripe/plugin-methods.ts +22 -27
  285. package/packages/bundled-features/src/subscription-stripe/runtime.ts +2 -2
  286. package/packages/bundled-features/src/subscription-stripe/verify-webhook.ts +62 -64
  287. package/packages/bundled-features/src/tags/feature.ts +3 -3
  288. package/packages/bundled-features/src/tags/screens.ts +1 -1
  289. package/packages/bundled-features/src/template-resolver/api.ts +10 -10
  290. package/packages/bundled-features/src/template-resolver/handlers/find-by-id.query.ts +5 -5
  291. package/packages/bundled-features/src/template-resolver/handlers/list.query.ts +1 -1
  292. package/packages/bundled-features/src/template-resolver/handlers/shared.ts +2 -2
  293. package/packages/bundled-features/src/template-resolver/handlers/template-write.ts +3 -3
  294. package/packages/bundled-features/src/template-resolver/handlers/upsert-system.write.ts +3 -4
  295. package/packages/bundled-features/src/template-resolver/handlers/upsert-tenant.write.ts +4 -5
  296. package/packages/bundled-features/src/template-resolver/seeding.ts +4 -4
  297. package/packages/bundled-features/src/template-resolver/table.ts +13 -14
  298. package/packages/bundled-features/src/template-resolver/web/client-plugin.tsx +2 -2
  299. package/packages/bundled-features/src/tenant/feature.ts +7 -7
  300. package/packages/bundled-features/src/tenant/handlers/member-directory.query.ts +1 -1
  301. package/packages/bundled-features/src/tenant/handlers/members.query.ts +1 -1
  302. package/packages/bundled-features/src/tenant/handlers/memberships.query.ts +1 -1
  303. package/packages/bundled-features/src/tenant/handlers/team-list.query.ts +1 -1
  304. package/packages/bundled-features/src/tenant/handlers/tenant-directory.query.ts +1 -1
  305. package/packages/bundled-features/src/tenant/invitation-table.ts +37 -40
  306. package/packages/bundled-features/src/tenant/membership-table.ts +3 -3
  307. package/packages/bundled-features/src/tenant/schema/tenant.ts +7 -9
  308. package/packages/bundled-features/src/tenant/screens.ts +1 -1
  309. package/packages/bundled-features/src/tenant/seeding.ts +19 -18
  310. package/packages/bundled-features/src/tenant/testing.ts +5 -6
  311. package/packages/bundled-features/src/tenant/web/constants.ts +2 -2
  312. package/packages/bundled-features/src/tenant-handover/events.ts +5 -7
  313. package/packages/bundled-features/src/tenant-handover/feature.ts +1 -1
  314. package/packages/bundled-features/src/tenant-handover/grant.ts +1 -1
  315. package/packages/bundled-features/src/tenant-handover/handlers/claim.write.ts +1 -1
  316. package/packages/bundled-features/src/tenant-handover/move-entity-graph.ts +8 -9
  317. package/packages/bundled-features/src/tenant-handover/signup-handover-provider.ts +1 -2
  318. package/packages/bundled-features/src/tenant-handover/transfer-graph.ts +4 -5
  319. package/packages/bundled-features/src/tenant-lifecycle/boot-checks.ts +1 -1
  320. package/packages/bundled-features/src/tenant-lifecycle/feature.ts +1 -1
  321. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +2 -2
  322. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +1 -1
  323. package/packages/bundled-features/src/tenant-settings/constants.ts +1 -1
  324. package/packages/bundled-features/src/tenant-settings/tenant-defaults.ts +12 -5
  325. package/packages/bundled-features/src/tier-engine/aggregate-id.ts +15 -16
  326. package/packages/bundled-features/src/tier-engine/compose-app.ts +14 -14
  327. package/packages/bundled-features/src/tier-engine/entity.ts +18 -19
  328. package/packages/bundled-features/src/tier-engine/feature.ts +88 -87
  329. package/packages/bundled-features/src/tier-engine/handlers/active-tier.query.ts +6 -7
  330. package/packages/bundled-features/src/tier-engine/handlers/get-tenant-tier.query.ts +4 -4
  331. package/packages/bundled-features/src/tier-engine/handlers/set-tenant-tier.write.ts +8 -8
  332. package/packages/bundled-features/src/tier-engine/tier-resolver.ts +2 -2
  333. package/packages/bundled-features/src/tier-engine/trial.ts +13 -13
  334. package/packages/bundled-features/src/tier-engine/web/index.ts +4 -4
  335. package/packages/bundled-features/src/user/db/queries/stream-tenant-backfill.ts +8 -8
  336. package/packages/bundled-features/src/user/handlers/create.write.ts +4 -4
  337. package/packages/bundled-features/src/user/schema/user.ts +45 -44
  338. package/packages/bundled-features/src/user/seeding.ts +40 -40
  339. package/packages/bundled-features/src/user/testing.ts +3 -3
  340. package/packages/bundled-features/src/user-data-rights/audit-download.ts +27 -28
  341. package/packages/bundled-features/src/user-data-rights/boot-checks.ts +1 -1
  342. package/packages/bundled-features/src/user-data-rights/deletion-token.ts +1 -1
  343. package/packages/bundled-features/src/user-data-rights/feature.ts +112 -113
  344. package/packages/bundled-features/src/user-data-rights/handlers/cancel-deletion.write.ts +9 -9
  345. package/packages/bundled-features/src/user-data-rights/handlers/confirm-deletion-by-token.write.ts +8 -8
  346. package/packages/bundled-features/src/user-data-rights/handlers/download-by-job.query.ts +29 -30
  347. package/packages/bundled-features/src/user-data-rights/handlers/download-by-token.query.ts +40 -42
  348. package/packages/bundled-features/src/user-data-rights/handlers/export-status.query.ts +8 -9
  349. package/packages/bundled-features/src/user-data-rights/handlers/lift-restriction.write.ts +7 -8
  350. package/packages/bundled-features/src/user-data-rights/handlers/list-download-attempts.query.ts +2 -2
  351. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +4 -4
  352. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion-by-email.write.ts +30 -29
  353. package/packages/bundled-features/src/user-data-rights/handlers/request-deletion.write.ts +15 -18
  354. package/packages/bundled-features/src/user-data-rights/handlers/request-export.write.ts +42 -41
  355. package/packages/bundled-features/src/user-data-rights/handlers/restrict-account.write.ts +22 -19
  356. package/packages/bundled-features/src/user-data-rights/handlers/run-forget-cleanup.write.ts +8 -8
  357. package/packages/bundled-features/src/user-data-rights/index.ts +8 -10
  358. package/packages/bundled-features/src/user-data-rights/lib/default-mailers.ts +3 -3
  359. package/packages/bundled-features/src/user-data-rights/lib/update-user-lifecycle.ts +24 -27
  360. package/packages/bundled-features/src/user-data-rights/run-export-jobs.ts +166 -276
  361. package/packages/bundled-features/src/user-data-rights/run-forget-cleanup.ts +85 -107
  362. package/packages/bundled-features/src/user-data-rights/run-user-export.ts +67 -69
  363. package/packages/bundled-features/src/user-data-rights/schema/download-attempt.ts +11 -11
  364. package/packages/bundled-features/src/user-data-rights/schema/download-token.ts +37 -41
  365. package/packages/bundled-features/src/user-data-rights/schema/export-job.ts +65 -67
  366. package/packages/bundled-features/src/user-data-rights/token-helpers.ts +21 -25
  367. package/packages/bundled-features/src/user-data-rights/web/client-plugin.tsx +6 -6
  368. package/packages/bundled-features/src/user-data-rights/web/confirm-deletion-screen.tsx +6 -5
  369. package/packages/bundled-features/src/user-data-rights/web/constants.ts +1 -1
  370. package/packages/bundled-features/src/user-data-rights/web/index.ts +5 -5
  371. package/packages/bundled-features/src/user-data-rights/web/privacy-center-screen.tsx +14 -13
  372. package/packages/bundled-features/src/user-data-rights/web/public-deletion-gate.tsx +13 -12
  373. package/packages/bundled-features/src/user-data-rights/web/request-deletion-screen.tsx +6 -6
  374. package/packages/bundled-features/src/user-data-rights/zip-path.ts +41 -40
  375. package/packages/bundled-features/src/user-data-rights-defaults/feature.ts +15 -15
  376. package/packages/bundled-features/src/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.ts +3 -5
  377. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +45 -51
  378. package/packages/bundled-features/src/user-data-rights-defaults/hooks/job-run.userdata-hook.ts +2 -2
  379. package/packages/bundled-features/src/user-data-rights-defaults/hooks/notification-preference.userdata-hook.ts +1 -1
  380. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user-session.userdata-hook.ts +3 -3
  381. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +32 -31
  382. package/packages/bundled-features/src/user-profile/handlers/change-email.write.ts +13 -13
  383. package/packages/bundled-features/src/user-profile/index.ts +3 -3
  384. package/packages/bundled-features/src/user-profile/web/client-plugin.ts +1 -1
  385. package/packages/bundled-features/src/user-profile/web/constants.ts +1 -1
  386. package/packages/bundled-features/src/user-profile/web/profile-screen.tsx +1 -1
  387. package/packages/bundled-features/src/workflow-runner/aggregate-id.ts +1 -1
  388. package/packages/bundled-features/src/workflow-runner/event-subscriber.ts +4 -5
  389. package/packages/bundled-features/src/workflow-runner/event-trigger.ts +4 -15
  390. package/packages/bundled-features/src/workflow-runner/feature.ts +2 -2
  391. package/packages/bundled-features/src/workflow-runner/handlers/resume-run.write.ts +4 -4
  392. package/packages/bundled-features/src/workflow-runner/pending-projection.ts +6 -7
  393. package/packages/bundled-features/src/workflow-runner/runner.ts +6 -6
  394. package/packages/bundled-features/src/workflow-runner/tables.ts +6 -6
  395. package/packages/bundled-features/src/workflow-runner/workflow-registry.ts +1 -1
@@ -1,25 +1,26 @@
1
- // Public-Gate für die anonyme Account-Löschung. Matcht window.location.pathname:
1
+ // Public gate for anonymous account deletion. Matches window.location.pathname:
2
2
  // requestPath → RequestAccountDeletionScreen, confirmPath →
3
- // ConfirmAccountDeletionScreen, sonst durch zur App. Spiegelt makeAuthGate
4
- // (auth-email-password) — userDataRightsClient hängt es als Gate ein, die App
5
- // listet den Client VOR dem Auth-Client, damit ein anonymer Besucher die Lösch-
6
- // Maske statt der Login-Maske sieht. Path-Match beim Render: Apex-Übergänge
7
- // (der Verify-Link) sind Full-Page-Loads, kein Client-Router.
3
+ // ConfirmAccountDeletionScreen, otherwise passes through to the app. Mirrors
4
+ // makeAuthGate (auth-email-password) — userDataRightsClient adds it as a gate,
5
+ // and the app lists this client BEFORE the auth client so an anonymous visitor
6
+ // sees the deletion screen instead of the login screen. Matching during render:
7
+ // Apex transitions (the verification link) are full-page loads, not client-router
8
+ // transitions.
8
9
  //
9
- // confirmPath MUSS dem Pfad der server-seitigen deletionVerifyUrl entsprechen —
10
- // der ConfirmScreen liest das ?token aus eben dieser URL.
10
+ // confirmPath MUST match the path of the server-side deletionVerifyUrl —
11
+ // ConfirmScreen reads the ?token from that URL.
11
12
 
12
13
  import type { ComponentType, ReactNode } from "react";
13
14
  import { ConfirmAccountDeletionScreen } from "./confirm-deletion-screen.tsx";
14
15
  import { RequestAccountDeletionScreen } from "./request-deletion-screen.tsx";
15
16
 
16
17
  export type PublicDeletionRoutes = {
17
- /** Login-freie Route für die Email-Antrags-Maske (z.B. "/account/delete"). */
18
+ /** Login-free route for the email request screen (e.g. "/account/delete"). */
18
19
  readonly requestPath: string;
19
- /** Login-freie Route für die Token-Bestätigung; = Pfad der deletionVerifyUrl. */
20
+ /** Login-free route for token confirmation; path of deletionVerifyUrl. */
20
21
  readonly confirmPath: string;
21
- /** Chrome um die Screen-Card. Default: vollflächig zentriert (wie der Auth-
22
- * defaultShell). Apps reichen ihre eigene Shell (z.B. Marketing-Header). */
22
+ /** Shell around the screen card. Default: full-screen centered (like the auth-
23
+ * defaultShell). Apps can provide their own shell (e.g. a marketing header). */
23
24
  readonly shell?: (screen: ReactNode) => ReactNode;
24
25
  };
25
26
 
@@ -1,10 +1,10 @@
1
- // RequestAccountDeletionScreen — anonymer Apex-Screen Schritt 1. Email-Form
2
- // → user-data-rights:write:request-deletion-by-email. Enumeration-safe: zeigt
3
- // unconditional ein "Falls Account existiert, Mail unterwegs"-Confirm, auch
4
- // wenn der Server intern erkannt hat dass die Email nicht existiert.
1
+ // RequestAccountDeletionScreen — anonymous Apex screen, step 1: email form
2
+ // → user-data-rights:write:request-deletion-by-email. Enumeration-safe: always
3
+ // shows a "If an account exists, the email is on its way" confirmation, even
4
+ // when the server has determined internally that the email does not exist.
5
5
  //
6
- // App mountet den Screen unter einer Apex-Route (z.B. /delete-account) via
7
- // createPublicSurface; die Page-Shell liefert die Chrome.
6
+ // The app mounts this screen at an Apex route (e.g. /delete-account) via
7
+ // createPublicSurface; the page shell provides the surrounding chrome.
8
8
 
9
9
  import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
10
10
  import { type FormEvent, type ReactNode, useState } from "react";
@@ -1,52 +1,52 @@
1
- // Shared helper fuer ZIP-Path-Berechnung von fileRefs (S2.U3 Atom 3c).
1
+ // Shared helper for computing ZIP paths from fileRefs.
2
2
  //
3
- // Das Bundle hat zwei Sichten auf die selben fileRefs:
4
- // 1. bundle.json: Eine flat-Liste mit `zipPath` pro fileRef. Reader-
5
- // Tools koennen so JSON ↔ files/-Pfade verlinken.
6
- // 2. ZIP-Entries: Bytes liegen unter genau diesen `zipPath`-Schluesseln.
3
+ // The bundle has two views of the same fileRefs:
4
+ // 1. bundle.json: A flat list with `zipPath` for each fileRef. Reader
5
+ // tools can use this to link JSON to files/-paths.
6
+ // 2. ZIP entries: Bytes are stored under exactly these `zipPath` keys.
7
7
  //
8
- // Damit beide Sichten NICHT auseinander driften, lebt die Pfad-Berechnung
9
- // EXAKT EINMAL hier. run-user-export befuellt zipPath im fileRef-Item,
10
- // run-export-jobs's bundleToZipEntries nutzt dieselben Pfade als Entry-
11
- // Keys.
8
+ // To keep both views synchronized, path computation lives EXACTLY ONCE here.
9
+ // run-user-export fills zipPath in the fileRef item, and
10
+ // run-export-jobs's bundleToZipEntries uses the same paths as entry keys.
12
11
 
13
12
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
14
13
 
15
14
  /**
16
- * Maximale Laenge des sanitized fileName (ohne Extension). Realistic
17
- * Filenames sind <50, 100 ist eine sichere Grenze fuer ZIP-Kompatibilitaet
18
- * (PKWARE-spec keine harte limit, aber viele Reader haengen bei extrem
19
- * langen Namen).
15
+ * Maximum length of the sanitized fileName without its extension. Realistic
16
+ * filenames are <50; 100 is a safe limit for ZIP compatibility
17
+ * (the PKWARE spec has no hard limit, but many readers struggle with
18
+ * extremely long names).
20
19
  */
21
20
  const MAX_SANITIZED_BASENAME_LENGTH = 100;
22
21
 
23
22
  /**
24
- * Erlaubte Filename-Chars: alphanumerisch, dot, dash, underscore. Alles
25
- * andere wird zu underscore replaced. Path-Separator (`/`, `\`),
26
- * relative-traversal (`..`), und null-bytes sind insbesondere ausgeschlossen.
23
+ * Allowed filename chars: alphanumerics, dot, dash, underscore. Everything
24
+ * else is replaced with an underscore. This excludes path separators (`/`,
25
+ * `\`) and null bytes in particular; relative traversal (`..`) is handled
26
+ * by the basename and leading-dot rules below.
27
27
  */
28
28
  const FILENAME_SAFE_CHARS = /[^a-zA-Z0-9._-]/g;
29
29
 
30
30
  /**
31
- * Sanitize einen vom User-Input stammenden fileName fuer Verwendung als
32
- * ZIP-internal-path-Suffix. Defense gegen:
33
- * - Path-Traversal: "../../etc/passwd" → "file.etc_passwd"
34
- * - Null-Bytes: "report\x00.pdf" → "report_.pdf"
35
- * - Path-Separator: "sub/dir/file.txt" → "sub_dir_file.txt"
36
- * - Reserved-Names: "." / ".." / "..." → "file"
31
+ * Sanitizes a user-provided fileName for use as a ZIP-internal-path suffix.
32
+ * - Path traversal: "../../etc/passwd" → "file.etc_passwd"
33
+ * - Null bytes: "report\x00.pdf" → "report_.pdf"
34
+ * - Path separators: "sub/dir/file.txt" → "sub_dir_file.txt"
35
+ * - Reserved names: "." / ".." / "..." → "file"
37
36
  * - Empty input: "" / null / undef → "unnamed"
38
- * - Ueberlange: lange Strings auf MAX_SANITIZED_BASENAME_LENGTH gekappt
39
- * (Extension bleibt erhalten falls vorhanden)
40
- * - Unicode: non-ASCII → underscore. Leading-strip kann auch dazu
41
- * fuehren dass alle-Unicode-Names zu "file" werden.
37
+ * - Excessive length: long strings are truncated to
38
+ * MAX_SANITIZED_BASENAME_LENGTH
39
+ * (the extension is preserved when present)
40
+ * - Unicode: non-ASCII characters → underscores. Leading stripping
41
+ * can also cause all-Unicode names to become "file".
42
42
  *
43
- * Output ist garantiert: nicht leer, kein Path-Separator, max-len enforced,
44
- * keine `..`-Sequenz im finalen String.
43
+ * The output is guaranteed to be non-empty, contain no path separators, obey
44
+ * the maximum length, and contain no `..` sequence.
45
45
  */
46
46
  export function sanitizeZipFilename(raw: string): string {
47
47
  if (raw === undefined || raw === null || raw === "") return "unnamed";
48
48
 
49
- // Extension extrahieren (letzte ".X" wo X kein "." enthaelt).
49
+ // Extract the extension (the last ".X" where X contains no ".").
50
50
  const lastDot = raw.lastIndexOf(".");
51
51
  const hasExt = lastDot > 0 && lastDot < raw.length - 1;
52
52
  const baseName = hasExt ? raw.slice(0, lastDot) : raw;
@@ -55,20 +55,21 @@ export function sanitizeZipFilename(raw: string): string {
55
55
  const safeBase = collapseUnsafe(baseName).slice(0, MAX_SANITIZED_BASENAME_LENGTH);
56
56
  const safeExt = collapseUnsafe(extension).slice(0, 20);
57
57
 
58
- // Empty oder all-underscores → "file" als reproduzierbarer Fallback.
58
+ // Empty or all-underscore input → "file" as a reproducible fallback.
59
59
  const finalBase = safeBase.length === 0 ? "file" : safeBase;
60
60
 
61
61
  return safeExt.length > 0 ? `${finalBase}.${safeExt}` : finalBase;
62
62
  }
63
63
 
64
64
  /**
65
- * 3-step Sanitize:
66
- * 1. Replace alles ausser [a-zA-Z0-9._-] mit "_"
67
- * 2. Collapse `..` (oder mehr) → "_" — verhindert dass `..` nach
68
- * Sanitize uebrig bleibt (z.B. wenn input nur dots+slashes ist).
69
- * 3. Strip leading [._-]+ — verhindert hidden-file-Patterns + leere
70
- * Basenames + leading-segments die nach den ersten zwei Steps
71
- * lauter underscores haetten.
65
+ * Three-step sanitization:
66
+ * 1. Replace everything except [a-zA-Z0-9._-] with "_".
67
+ * 2. Collapse `..` (or more) to "_"—this prevents `..` from surviving
68
+ * sanitization (for example, when the input contains only dots and
69
+ * slashes).
70
+ * 3. Strip leading [._-]+—this prevents hidden-file patterns, empty
71
+ * basenames, and leading segments that would consist entirely of
72
+ * underscores after the first two steps.
72
73
  */
73
74
  function collapseUnsafe(s: string): string {
74
75
  let out = s.replace(FILENAME_SAFE_CHARS, "_");
@@ -78,11 +79,11 @@ function collapseUnsafe(s: string): string {
78
79
  }
79
80
 
80
81
  /**
81
- * Berechnet den ZIP-internal-Pfad fuer einen fileRef. Layout:
82
+ * Computes the ZIP-internal path for a fileRef. Layout:
82
83
  * files/<tenantId>/<fileRefId>-<sanitized-fileName>
83
84
  *
84
- * tenantId + fileRefId sind UUID-shape (sicher); fileName geht durch
85
- * sanitizeZipFilename. Garantiert kein path-traversal.
85
+ * tenantId and fileRefId have UUID shapes and are safe; fileName is passed
86
+ * through sanitizeZipFilename. Path traversal is guaranteed to be excluded.
86
87
  */
87
88
  export function buildFileRefZipPath(args: {
88
89
  readonly tenantId: TenantId;
@@ -36,23 +36,23 @@ import {
36
36
  userSessionExportHook,
37
37
  } from "./hooks/user-session.userdata-hook.ts";
38
38
 
39
- // user-data-rights-defaults — Default-Hooks für die Core-Entities
40
- // `user` (S2.H1) und `fileRef` (S2.H2).
39
+ // user-data-rights-defaults — Default hooks for the core entities
40
+ // `user` and `fileRef`.
41
41
  //
42
- // Architektur-Entscheidung (S2.H1+H2): user-data-rights selbst kann
43
- // nicht r.requires({ features: ["user", "files"] }) + r.useExtension(EXT_USER_DATA, ...)
44
- // machen weil es selbst Provider von EXT_USER_DATA ist (Boot-Validator
45
- // lehnt self-extension ab). Lösung: drittes optional-mountbares Feature
46
- // das requires beide Sources + die useExtension-Calls macht.
42
+ // Architectural decision: user-data-rights itself cannot call
43
+ // r.requires({ features: ["user", "files"] }) + r.useExtension(EXT_USER_DATA, ...)
44
+ // because it provides EXT_USER_DATA itself (the boot validator rejects
45
+ // self-extension). The solution is a third, optionally mountable feature
46
+ // that requires both sources and makes the useExtension calls.
47
47
  //
48
- // App-Author kann dieses Feature weglassen wenn er Custom-Hooks
49
- // stattdessen registrieren will (z.B. "anonymize sollte den User-Row
50
- // hard-delete" — App-spezifische Compliance-Entscheidung). Default-
51
- // Implementierung deckt 95% der Apps ab.
48
+ // App authors can omit this feature if they want to register custom hooks
49
+ // instead (for example, "anonymize should hard-delete the user row" — an
50
+ // app-specific compliance decision). The default implementation covers 95%
51
+ // of apps.
52
52
  //
53
- // Pattern matched file-foundation + file-provider-s3 (separate Plugin-
54
- // Feature), nicht user/files schreiben ihre eigenen Hooks selbst weil
55
- // das circular-requires waere.
53
+ // This follows the file-foundation + file-provider-s3 pattern (separate
54
+ // plugin features): user/files do not define their own hooks because that
55
+ // would create circular requires.
56
56
  // Binary storage for the fileRef delete-hook is resolved at run time from the
57
57
  // mounted file-foundation via ctx.buildStorageProvider (injected by the forget
58
58
  // orchestrator) — no provider is captured here, so a single app-wide store and
@@ -123,7 +123,7 @@ export function createUserDataRightsDefaultsFeature(): FeatureDefinition {
123
123
  delete: configValueDeleteHook,
124
124
  });
125
125
 
126
- // Events-only aggregates (#799): export reads the projected rows, the
126
+ // Events-only aggregates: export reads the projected rows, the
127
127
  // delete hooks are deliberate no-ops — erasure happens via crypto-
128
128
  // shredding (forget erases the user's DEK; recipientAddress / job
129
129
  // payload become unreadable in events AND rows).
@@ -9,11 +9,9 @@ import {
9
9
  } from "../../delivery/index.ts";
10
10
  import { featureMounted } from "./feature-mounted.ts";
11
11
 
12
- // userData-Hooks for delivery's attempt log (deferred from #797, closed by
13
- // #799). deliveryAttempt is an events-only aggregate — the export reads the
14
- // projected rows; recipientAddress may be ciphertext (kumiko-pii:), which
15
- // the export runner's central decrypt sweep resolves to plaintext (or
16
- // [[erased]] after a forget).
12
+ // userData-Hooks for delivery's attempt log. deliveryAttempt is an events-only aggregate — the
13
+ // export reads the projected rows; recipientAddress may be ciphertext (kumiko-pii:), which the
14
+ // export runner's central decrypt sweep resolves to plaintext (or [[erased]] after a forget).
17
15
 
18
16
  export const deliveryAttemptExportHook: UserDataExportHook = async (ctx) => {
19
17
  if (!featureMounted(ctx, "delivery")) return null;
@@ -30,68 +30,64 @@ const ERROR_CONTEXT = "user-data-rights-defaults:fileRef";
30
30
  // per-user forget flows are rare, so per-row events are acceptable.
31
31
  const crud = createEventStoreExecutor(fileRefsTable, fileRefEntity, { entityName: "fileRef" });
32
32
 
33
- // userData-Hook fuer fileRef-entity (S2.H2).
33
+ // User-data hook for the fileRef entity.
34
34
  //
35
- // Export-Hook liefert Metadata aller FileRefs des Users mit Subject-
36
- // Resolver via insertedById. Storage-Provider-binary-Streams kommen
37
- // NICHT direkt — sie werden via signed-Download-URLs separat ins ZIP
38
- // gepackt (S2.U3 Export-Job-Pipeline orchestriert das).
35
+ // The export hook returns metadata for all of the user's FileRefs, with the
36
+ // subject resolved through insertedById. Storage-provider binary streams are
37
+ // not included directly; signed download URLs package them into the ZIP
38
+ // separately.
39
39
  //
40
- // Delete-hook removes the fileRef row + binary:
40
+ // The delete hook removes the fileRef row and binary:
41
41
  // "delete": storageProvider.delete() per file + row hard-delete — but
42
42
  // ONLY for rows whose field is marked as PII of the person
43
- // (isPersonalFileRow, #3005). All other rows (business/
44
- // tenant data, no resolvable field, no annotation) go
45
- // through severPersonLink instead, even when the entity
46
- // strategy is "delete" — the uploader axis (insertedById) is
47
- // not the subject axis.
48
- // "anonymize": insertedById=null, row + binary survive (FK refs can still
49
- // point at it; person-link removed) — applies to ALL rows
43
+ // (isPersonalFileRow). All other rows (business/tenant data,
44
+ // no resolvable field, no annotation) go through
45
+ // severPersonLink instead, even when the entity strategy is
46
+ // "delete" — the uploader axis (insertedById) is not the
47
+ // subject axis.
48
+ // "anonymize": insertedById=null; row and binary survive (FK refs can still
49
+ // point at it; person-link removed). This applies to ALL rows
50
50
  // when a retention override on fileRef (anonymize or
51
51
  // blockDelete, e.g. a statutory retention duty) sets the
52
52
  // strategy, regardless of the field.
53
53
  //
54
- // **Provider-Resolution:** der Provider kommt zur Lauf-Zeit aus
55
- // `ctx.buildStorageProvider(ctx.tenantId)` — der Forget-Orchestrator
56
- // (run-forget-cleanup) baut ihn aus dem gemounteten file-foundation, also aus
57
- // DEMSELBEN Store den Upload + Export nutzen (delete-target == upload-target by
58
- // construction). Kein bei-Mount captured Provider mehr.
54
+ // **Provider resolution:** the provider is obtained at runtime from
55
+ // `ctx.buildStorageProvider(ctx.tenantId)`. The forget orchestrator builds it
56
+ // from the mounted file-foundation, using the SAME store as upload and export
57
+ // (delete-target == upload-target by construction). No provider is captured at
58
+ // mount time.
59
59
  //
60
- // **Zwei Fehlerklassen, bewusst verschieden behandelt:**
61
- // 1. Resolution schlaegt fehl (kein Provider konfiguriert / configResolver
62
- // fehlt) → NICHT fail-closed: Warn pro Aufruf + row-only-delete. Ein
63
- // fehlkonfigurierter Store darf die Art.-17-Loeschung nicht DAUERHAFT
64
- // blockieren (sonst haengt jeder User fuer immer in DeletionRequested);
65
- // der Boot-Guard macht die Fehlkonfiguration sichtbar, Binaries werden
66
- // nachgeholt sobald ein Provider existiert.
67
- // 2. Binary-DELETE schlaegt fehl, OBWOHL ein Provider da ist → FAIL-CLOSED:
68
- // der Hook wirft NACH dem Loop, die per-User-Sub-Tx von runForgetCleanup
69
- // rollt zurueck, der User bleibt DeletionRequested, der naechste Run
70
- // retried (delete ist idempotent → konvergiert). Den Fehler zu schlucken +
71
- // die Row trotzdem zu loeschen wuerde Erasure als "done" markieren waehrend
72
- // die Bytes liegen bleiben — falsche Compliance-Aussage. Das "KEIN globaler
73
- // Rollback" der Sprint-2-Atomicity bleibt gewahrt: nur DIESE Sub-Tx rollt
74
- // zurueck. Der anonymize-Pfad behaelt Row+binary, hat nichts zu schlucken.
60
+ // **Two error classes are handled differently:**
61
+ // 1. Resolution fails (no provider configured / configResolver missing) →
62
+ // NOT fail-closed: warn per invocation and perform a row-only delete. A
63
+ // misconfigured store must not permanently block the Art. 17 deletion;
64
+ // the boot guard exposes the misconfiguration, and binaries are removed
65
+ // once a provider exists.
66
+ // 2. Binary DELETE fails even though a provider exists → FAIL-CLOSED: the
67
+ // hook throws after the loop, the per-user sub-transaction rolls back,
68
+ // the user remains DeletionRequested, and the next run retries (delete is
69
+ // idempotent → converges). Swallowing the error and deleting the row would
70
+ // mark erasure as "done" while leaving the bytes behind. Only this
71
+ // sub-transaction rolls back; there is no global rollback. The anonymize
72
+ // path retains the row and binary, so it has no error to swallow.
75
73
  //
76
- // Caveat: hard-delete via deleteMany emittiert KEIN fileRef.deleted —
77
- // die storage-tracking-MSP dekrementiert nicht. Wenn die zu loeschenden
78
- // Files vorher nicht soft-deleted waren, bleibt `tenant_storage_usage`
79
- // inflated. Forget-Flows sind selten (per-User-Art.-17) und damit
80
- // bounded; ein executor.purge-API folgt mit dem trashed-files-GC.
74
+ // Caveat: hard-delete via deleteMany emits no fileRef.deleted event, so
75
+ // storage-tracking does not decrement. If the files being deleted were not
76
+ // soft-deleted first, `tenant_storage_usage` remains inflated. Forget flows are
77
+ // rare and bounded; an executor.purge API will follow with trashed-files GC.
81
78
 
82
79
  export const fileRefExportHook: UserDataExportHook = async (ctx) => {
83
- // isDeleted:false — soft-deleted (trashed) Files gehören nicht ins
84
- // Auskunfts-Bundle. Forget (delete-Hook unten) erfasst sie trotzdem.
80
+ // isDeleted:false — soft-deleted (trashed) files are excluded from the
81
+ // export bundle. The forget hook below still processes them.
85
82
  const rawRows = await ctx.db.selectMany(fileRefsTable, {
86
83
  tenantId: ctx.tenantId,
87
84
  insertedById: ctx.userId,
88
85
  isDeleted: false,
89
86
  });
90
87
 
91
- // @cast-boundary db-row: drizzle liefert insertedAt als Instant
92
- // (framework-customType). Fuer JSON-Export brauchen wir String —
93
- // .toString() funktioniert sowohl auf Temporal.Instant als auch
94
- // Date.
88
+ // @cast-boundary db-row: drizzle returns insertedAt as an Instant
89
+ // (framework-customType). JSON export requires a string —
90
+ // .toString() works for both Temporal.Instant and Date.
95
91
  const rows = rawRows.map((r) => {
96
92
  const row = r as Record<string, unknown>; // @cast-boundary recursive-walk
97
93
  return {
@@ -115,9 +111,8 @@ export const fileRefExportHook: UserDataExportHook = async (ctx) => {
115
111
  size: r.size,
116
112
  insertedAt: r.insertedAt,
117
113
  })),
118
- // Plus die fileRefs-Liste die Sprint-2-U3 dann zum Storage-Provider
119
- // bringt + signed-URLs erzeugt + ins ZIP packt (siehe S1.9-Z1
120
- // UserDataExportSnippet.fileRefs).
114
+ // The fileRefs list is passed to the storage provider, which generates
115
+ // signed URLs and adds the files to the ZIP.
121
116
  fileRefs: rows.map((r) => ({
122
117
  fileRefId: r.id,
123
118
  storageKey: r.storageKey,
@@ -142,7 +137,7 @@ async function resolveProvider(ctx: UserDataHookCtx): Promise<UserDataStoragePro
142
137
  }
143
138
  }
144
139
 
145
- // Per-row Art.17 decision (kumiko-framework#3005): whether THIS file's field
140
+ // Per-row Art.17 decision: whether THIS file's field
146
141
  // carries personal data of the forgotten person, or is business/tenant data
147
142
  // that merely loses its uploader-attribution. insertedById names who
148
143
  // UPLOADED the file, not whose data it is — a dealer's vehicle photo
@@ -163,8 +158,7 @@ function isPersonalPiiField(field: FieldDefinition | undefined): boolean {
163
158
  );
164
159
  }
165
160
 
166
- // Three cases the field-lookup itself can't resolve (issue #3005's rule for
167
- // the non-resolvable cases):
161
+ // Three cases the field-lookup itself can't resolve:
168
162
  // 1. Unattached upload (entityType/fieldName both null) → hard-delete: a
169
163
  // file with no entity binding belongs to nobody but its uploader.
170
164
  // 2. Field exists but carries no PII annotation → anonymize (the
@@ -244,7 +238,7 @@ export const fileRefDeleteHook: UserDataDeleteHook = async (ctx, strategy) => {
244
238
  }
245
239
 
246
240
  // strategy="delete" decides PER ROW based on the field, not uniformly
247
- // (#3005): only rows whose field is marked as PII of the person (or
241
+ // only rows whose field is marked as PII of the person (or
248
242
  // unattached, see isPersonalFileRow) take the hard path. Everything else
249
243
  // only loses the uploader link.
250
244
  const personalRows: Record<string, unknown>[] = [];
@@ -2,7 +2,7 @@ import type { UserDataDeleteHook, UserDataExportHook } from "@cosmicdrift/kumiko
2
2
  import { jobRunsTable } from "../../jobs/index.ts";
3
3
  import { featureMounted } from "./feature-mounted.ts";
4
4
 
5
- // userData-Hooks for the jobs run log (deferred from #797, closed by #799).
5
+ // userData-Hooks for the jobs run log.
6
6
  // Job runs live on the SYSTEM tenant regardless of who triggered them, so
7
7
  // the export filters by triggeredById only — Art. 15 covers everything the
8
8
  // user caused, across tenants. payload may be ciphertext (kumiko-pii:); the
@@ -29,6 +29,6 @@ export const jobRunExportHook: UserDataExportHook = async (ctx) => {
29
29
  export const jobRunDeleteHook: UserDataDeleteHook = async () => {
30
30
  // Deliberate no-op: erasure runs via crypto-shredding — the forget pipeline
31
31
  // erases the triggering user's DEK, which makes the payload unreadable in
32
- // BOTH the append-only events and the projected rows (#799). triggeredById
32
+ // BOTH the append-only events and the projected rows. triggeredById
33
33
  // itself is a pseudonymous fk (plaintext by design, like config.userId).
34
34
  };
@@ -17,7 +17,7 @@ import { featureMounted } from "./feature-mounted.ts";
17
17
  // the forget verb.
18
18
  //
19
19
  // The delivery ATTEMPTS log is covered separately: export via
20
- // delivery-attempt.userdata-hook.ts, erasure via crypto-shredding (#799).
20
+ // delivery-attempt.userdata-hook.ts, erasure via crypto-shredding.
21
21
 
22
22
  const crud = createEventStoreExecutor(notificationPreferencesTable, notificationPreferenceEntity, {
23
23
  entityName: "notification-preference",
@@ -5,9 +5,9 @@ import { featureMounted } from "./feature-mounted.ts";
5
5
  // userData-Hooks for the sessions feature's user-session rows (ip, userAgent).
6
6
  //
7
7
  // user-session is an unmanaged direct-write store (no event stream, excluded
8
- // from projection rebuilds — see sessions/feature.ts #494/#498), so a direct
9
- // DELETE is legal here and survives rebuilds; the executor path the ES
10
- // entities use does not apply.
8
+ // from projection rebuilds, see sessions/feature.ts), so a direct DELETE is
9
+ // legal here and survives rebuilds; the executor path the ES entities use does
10
+ // not apply.
11
11
  //
12
12
  // Both forget strategies hard-delete: a session row without its user is
13
13
  // worthless (revocation audit trail loses its subject), and ip/userAgent are
@@ -20,25 +20,25 @@ import {
20
20
  // A direct write would be wiped on rebuild — the Art.17 hole this fixes.
21
21
  const crud = createEventStoreExecutor(userTable, userEntity, { entityName: "user" });
22
22
 
23
- // userData-Hook fuer user-entity (S2.H1).
23
+ // The user-data hook for the user entity.
24
24
  //
25
- // Export-Hook liefert Profil-Daten ohne security-sensitive Felder
26
- // (passwordHash, roles, status — DSGVO Art. 20 ist Datenportabilitaet
27
- // fuer das was der User selbst zur Verfuegung gestellt hat, nicht
28
- // Lifecycle-Metadata oder Authorization-State).
25
+ // The export hook returns profile data without security-sensitive fields
26
+ // (passwordHash, roles, status — GDPR Art. 20 covers portability of data
27
+ // the user provided themselves, not lifecycle metadata or authorization
28
+ // state).
29
29
  //
30
- // Delete-Hook anonymisiert PII + setzt status=deleted. Der eigentliche
31
- // softDelete-Flag wird ueber drizzle's deletedAt-Column gesetzt; die
32
- // Row bleibt fuer Audit-Trail erhalten (alle FK-Refs auf user.id
33
- // bleiben gueltig). DSGVO-konform via PII-Anonymisierung.
30
+ // The delete hook anonymizes PII and sets status=deleted. The actual
31
+ // softDelete flag is set through Drizzle's deletedAt column; the row remains
32
+ // for the audit trail (all foreign-key references to user.id remain valid).
33
+ // This complies with GDPR through PII anonymization.
34
34
  //
35
35
  // Strategy:
36
- // "delete": softDelete + email/displayName/passwordHash leeren,
37
- // status=deleted (Login geblockt)
38
- // "anonymize": email/displayName auf Pseudonym, Row bleibt active
39
- // — fuer Cases wo User-Row als FK noch relevant ist
40
- // aber PII raus muss (z.B. anonymize mit blockDelete-
41
- // Frist auf einer FK-target-Entity)
36
+ // "delete": softDelete + clear email/displayName/passwordHash,
37
+ // status=deleted (login blocked)
38
+ // "anonymize": replace email/displayName with pseudonyms; the row remains
39
+ // active when the user row is still needed as a foreign-key
40
+ // target but PII must be removed (for example, anonymization
41
+ // with a blockDelete deadline on a foreign-key target entity)
42
42
 
43
43
  export const userExportHook: UserDataExportHook = async (ctx) => {
44
44
  const row = await ctx.db.fetchOne<{
@@ -66,11 +66,11 @@ export const userExportHook: UserDataExportHook = async (ctx) => {
66
66
  };
67
67
 
68
68
  export const userDeleteHook: UserDataDeleteHook = async (ctx, strategy) => {
69
- // Idempotent: zweiter Call findet die Row schon anonymized + skipt
70
- // implicit (UPDATE mit gleichen Werten). Memory feedback_event_store_
71
- // tenant_consistency: ctx.tenantId muss in der user-table-Zeile
72
- // korrelieren — user.id ist tenant-agnostic (User kann in mehreren
73
- // Tenants Member sein), kein tenantId-Filter noetig.
69
+ // Idempotent: a second call finds the row already anonymized and skips
70
+ // implicitly (UPDATE with the same values). Event-store tenant
71
+ // consistency requires ctx.tenantId to correlate with the row in
72
+ // the user table — user.id is tenant-agnostic (a user can be a member in
73
+ // multiple tenants), so no tenantId filter is needed.
74
74
 
75
75
  // System actor + skipOptimisticLock: the forget pipeline has no read
76
76
  // version and writes privileged identity columns ("system" is privileged).
@@ -81,12 +81,13 @@ export const userDeleteHook: UserDataDeleteHook = async (ctx, strategy) => {
81
81
  const systemUser = createSystemUser(ctx.tenantId);
82
82
 
83
83
  if (strategy === "delete") {
84
- // PII raus + status=deleted (Login geblockt) via Event → Rebuild spielt den
85
- // Forget mit. KEIN softDelete: user ist systemStream (eine tenant-agnostische
86
- // Row), der Forget laeuft pro Tenant — wuerde isDeleted gesetzt, faende der
87
- // loadById (isDeleted:false) die Row beim zweiten Tenant nicht mehr
88
- // (not_found). status=Deleted blockt Login; die Row bleibt findbar +
89
- // idempotent ueber mehrere Tenant-Durchlaeufe (wie der alte raw UPDATE).
84
+ // Remove PII and set status=deleted via an event, so a rebuild replays
85
+ // the forget operation. Do NOT use softDelete: user is systemStream (a
86
+ // tenant-agnostic row), and forgetting runs once per tenant. Setting
87
+ // isDeleted would cause loadById (isDeleted:false) to miss the row for
88
+ // the second tenant (not_found). status=Deleted blocks login; the row
89
+ // remains findable and idempotent across tenant passes, as with the old
90
+ // raw UPDATE.
90
91
  await crud.update(
91
92
  {
92
93
  id: ctx.userId,
@@ -105,11 +106,11 @@ export const userDeleteHook: UserDataDeleteHook = async (ctx, strategy) => {
105
106
  { skipOptimisticLock: true, writePurpose: WritePurposes.erasure },
106
107
  );
107
108
  } else {
108
- // anonymize: PII raus, aber Row bleibt active (damit FK-References
109
- // weiter aufloesbar sind). Account ist effektiv weiter nutzbar
110
- // wenn der User sich neu authentifiziert — pragmatisch akzeptabel
111
- // weil "anonymize" auf user-entity ein seltener Edge-Case ist
112
- // (typisch hard-delete fuer User).
109
+ // Anonymize PII, but keep the row active so foreign-key references
110
+ // remain resolvable. The account can still be used if the user
111
+ // authenticates again — pragmatically acceptable because "anonymize"
112
+ // on the user entity is a rare edge case (hard deletion is typical for
113
+ // users).
113
114
  await crud.update(
114
115
  {
115
116
  id: ctx.userId,
@@ -10,9 +10,9 @@ import { decryptStoredPii, verifyPassword } from "../../shared/index.ts";
10
10
  import { UserErrors, UserHandlers, UserQueries } from "../../user/index.ts";
11
11
  import { UserProfileErrors } from "../web/constants.ts";
12
12
 
13
- // Gleiche Failure-Shape wie auth-email-password (anti-enumeration):
14
- // dessen errors.ts ist nicht Teil des Feature-Barrels, der Reason-Code
15
- // + i18nKey sind aber stabile Public-API.
13
+ // Same failure shape as auth-email-password (anti-enumeration):
14
+ // its errors.ts is not part of the feature barrel, but the reason code
15
+ // and i18nKey are stable public API.
16
16
  // @wrapper-known error-helper
17
17
  function invalidCredentials() {
18
18
  return writeFailure(
@@ -22,13 +22,13 @@ function invalidCredentials() {
22
22
  );
23
23
  }
24
24
 
25
- // Change-email — authenticated, self-only. Der User bestätigt mit seinem
26
- // aktuellen Passwort (Re-Auth wie change-password); die neue Adresse wird
27
- // via ctx.writeAs(system) gegen den user-update-Handler geschrieben, weil
28
- // `email` field-level privileged ist und bei Self-Updates sonst silent
29
- // gestrippt würde. emailVerified flippt auf false — die App triggert
30
- // anschließend den Verification-Flow (request-email-verification ist
31
- // public; der ProfileScreen ruft ihn nach Erfolg auf).
25
+ // Change-email — authenticated, self-only. The user confirms with their
26
+ // current password (re-authentication as with change-password); the new
27
+ // address is written through the user-update handler via ctx.writeAs(system)
28
+ // because `email` is field-level privileged and would otherwise be silently
29
+ // stripped during self-updates. emailVerified is set to false — the app then
30
+ // triggers the verification flow (request-email-verification is public; the
31
+ // ProfileScreen calls it after success).
32
32
  export const changeEmailWrite = defineWriteHandler({
33
33
  name: "change-email",
34
34
  schema: z.object({
@@ -88,9 +88,9 @@ export const changeEmailWrite = defineWriteHandler({
88
88
  );
89
89
  }
90
90
 
91
- // user ist systemStream (#497): der Event-Stream liegt deterministisch
92
- // auf SYSTEM_TENANT_ID. Pre-#497-Streams brauchen einmalig
93
- // backfillUserStreamTenants (#762).
91
+ // user is systemStream: the event stream is deterministically located
92
+ // on SYSTEM_TENANT_ID. Older streams require a one-time
93
+ // backfillUserStreamTenants.
94
94
  const writer = createSystemUser(SYSTEM_TENANT_ID);
95
95
 
96
96
  const writeRes = await ctx.writeAs(writer, UserHandlers.update, {