@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
@@ -5,10 +5,10 @@ import {
5
5
  createTimestampField,
6
6
  } from "@cosmicdrift/kumiko-framework/engine";
7
7
 
8
- // Audit-Trail invalid Download-Attempts (S2.U7).
9
- // Schreibt eine Row pro 4xx im download-by-{token,job}-Pfad. DPO erkennt
10
- // damit Brute-Force / Anomalien (gleiche IP, viele invalid-Versuche).
11
- // Success-Downloads landen in download-token.lastUsedAt — nicht hier.
8
+ // Audit trail for rejected download attempts.
9
+ // Writes one row per 4xx response on the download-by-{token,job} path, allowing the DPO
10
+ // to detect brute-force probing and anomalies such as many invalid attempts from one IP.
11
+ // Successful downloads are recorded in download-token.lastUsedAt instead.
12
12
  export const downloadAttemptEntity = createEntity({
13
13
  table: "read_download_attempts",
14
14
  idType: "uuid",
@@ -29,11 +29,11 @@ export const downloadAttemptEntity = createEntity({
29
29
  personal: false,
30
30
  reason: "technical_reference",
31
31
  }),
32
- // Token-Hash (token-Pfad) oder NULL (job-Pfad / unbekannter Token).
32
+ // Token hash for the token path, or NULL for the job path or an unknown token.
33
33
  tokenHash: createTextField({ maxLength: 64, personal: false, reason: "technical_reference" }),
34
- // Job-ID wenn der attempt einen kannte. NULL bei unbekanntem Token.
34
+ // Job ID when the attempt identified one; NULL for an unknown token.
35
35
  jobId: createTextField({ personal: false, reason: "technical_reference" }),
36
- // User-ID wenn auth-Pfad (job). NULL bei anonymous (token-Pfad).
36
+ // User ID for the authenticated job path; NULL for anonymous token-path requests.
37
37
  attemptedByUserId: createTextField({ personal: false, reason: "pseudonymous_fk" }),
38
38
  // The anonymous token path has no owner, so those rows fall back to the tenant key;
39
39
  // find "exact" on ip because list-download-attempts filters by IP.
@@ -49,10 +49,10 @@ export const downloadAttemptEntity = createEntity({
49
49
  }),
50
50
  attemptedAt: createTimestampField({ required: true }),
51
51
  },
52
- // 90d hardDelete: unbounded growth = disk-bomb genau gegen das System
53
- // das den Brute-Force erkennen soll. Brute-Force-Patterns sind kurzfristig
54
- // (Stunden bis Tage) — 90d Window deckt forensik-Reviews + DPO-quartal-
55
- // Audits. Tenant kann via override verlängern (HR-Compliance).
52
+ // 90d hardDelete: unbounded growth would create a disk bomb targeting the system
53
+ // that detects brute-force activity. Brute-force patterns are short-lived (hours to days),
54
+ // while a 90d window covers forensic reviews and quarterly DPO audits.
55
+ // The tenant can extend retention through an override for HR compliance.
56
56
  retention: { keepFor: "90d", strategy: "hardDelete", reference: "attemptedAt" },
57
57
  });
58
58
 
@@ -6,43 +6,42 @@ import {
6
6
  createTimestampField,
7
7
  } from "@cosmicdrift/kumiko-framework/engine";
8
8
 
9
- // Export-Download-Token (S2.U3 Atom 4a).
9
+ // Export-Download-Token.
10
10
  //
11
- // Sicherheits-Token fuer den Download-Endpoint (Atom 4b). Pattern:
12
- // 1. Worker generiert plain-Token (32 byte random base64url) +
13
- // Hash (SHA256 hex) beim Flip auf done.
14
- // 2. crud.create(downloadTokenEntity, ...) emittiert
15
- // `exportDownloadToken.created`-Event in den event-store. DB-Row
16
- // wird via Projection synchron geschrieben (Marten-Pattern, NICHT
17
- // direct-INSERT). Memory `feedback_event_store_tenant_consistency`.
18
- // 3. Plain bleibt im Worker-Memory + wird via RunExportJobsResult an
19
- // Atom 5 (Notification) weitergegeben. NIEMALS plain in DB.
20
- // 4. Atom 4b's Download-Endpoint: hashed incoming-Token + sucht den
21
- // Hash-Eintrag. Konstanter-Zeit-Vergleich gegen timing-attacks.
11
+ // Security token for the download endpoint. Pattern:
12
+ // 1. Worker generates a plain token (32 random bytes, base64url) +
13
+ // hash (SHA256 hex) when flipping to done.
14
+ // 2. crud.create(downloadTokenEntity, ...) emits
15
+ // `exportDownloadToken.created`-Event in the event store. The DB row
16
+ // is written synchronously via the projection (Marten pattern, NOT
17
+ // direct INSERT).
18
+ // 3. Plain token remains in worker memory + is passed via
19
+ // RunExportJobsResult to the notification flow. NEVER plain in DB.
20
+ // 4. The download endpoint hashes the incoming token + looks up the
21
+ // hash entry. Constant-time comparison against timing attacks.
22
22
  //
23
- // **Multi-use within TTL** (Plan-Decision 4a): Token wird beim Download
24
- // nicht "consumed". Mehrfach-Download bis expiresAt erlaubt — UX bei
25
- // Connection-Abbrueche, kein Re-Export-Zwang. Pattern matched Google-
26
- // Takeout (7d) + Facebook-Data-Download (4d).
23
+ // **Multi-use within TTL**: Token is not "consumed" on download.
24
+ // Multiple downloads until expiresAt are allowed — better UX for connection
25
+ // interruptions, no forced re-export. Pattern matches Google Takeout (7d)
26
+ // + Facebook Data Download (4d).
27
27
  //
28
- // **TTL = job.expiresAt** (denormalized, gleicher Wert wie Job-Row).
29
- // Storage-Cleanup-Pass nullt downloadStorageKey nach
30
- // expiresAt + exportStorageCleanupGraceHours. Token-Row bleibt liegen
31
- // (Audit-Trail) — Atom 4b's Download-Endpoint check't job.downloadStorageKey
32
- // != null vor Streaming + returns 410 Gone wenn Storage cleared.
28
+ // **TTL = job.expiresAt** (denormalized, same value as the job row).
29
+ // Storage cleanup nulls downloadStorageKey after
30
+ // expiresAt + exportStorageCleanupGraceHours. The token row remains
31
+ // (audit trail) — the download endpoint checks job.downloadStorageKey
32
+ // != null before streaming + returns 410 Gone when storage is cleared.
33
33
  //
34
- // **idType: "uuid"** matched ExportJob — Token-IDs reisen ueber
35
- // Process-Grenzen (audit-events fuer DPO, ggf. Re-Issue-Pfade).
34
+ // **idType: "uuid"** matches ExportJob — token IDs cross process
35
+ // boundaries (audit events for the DPO, possible re-issue paths).
36
36
 
37
37
  export const exportDownloadTokenEntity = createEntity({
38
38
  table: "read_export_download_tokens",
39
39
  idType: "uuid",
40
40
 
41
41
  fields: {
42
- // FK auf export-jobs. UNIQUE (siehe indexes) — 1 Token pro Job.
43
- // Audit-Trail-Argument: separate Token-Row statt Job-Spalten weil
44
- // Audit-Felder (lastUsedAt/IP/UA) semantisch zum Token, nicht zum
45
- // Job gehoeren.
42
+ // Foreign key to export jobs. UNIQUE (see indexes) enforces one token per
43
+ // job. A separate token row keeps token-specific audit fields
44
+ // (`lastUsedAt`/IP/UA) separate from the job.
46
45
  jobId: createTextField({
47
46
  required: true,
48
47
  personal: false,
@@ -58,25 +57,24 @@ export const exportDownloadTokenEntity = createEntity({
58
57
  reason: "technical_reference",
59
58
  }),
60
59
 
61
- // Wann wurde das Token ausgegeben (= Job-Done-Flip-Zeit).
60
+ // The time the token was issued, when the job was marked done.
62
61
  issuedAt: createTimestampField({
63
62
  required: true,
64
63
  }),
65
64
 
66
- // Wann laeuft das Token ab. Identisch zu job.expiresAt
67
- // (denormalized — Worker setzt beide gleich beim Done-Flip).
65
+ // The token expires at the same time as `job.expiresAt`; the worker sets both
66
+ // values when marking the job done.
68
67
  expiresAt: createTimestampField({
69
68
  required: true,
70
69
  }),
71
70
 
72
- // Audit: wann wurde das Token zuletzt fuer einen Download genutzt.
73
- // NULL solange noch nie heruntergeladen. Atom 4b's Download-Endpoint
74
- // setzt es bei jedem successful Stream.
71
+ // Audit timestamp for the most recent download. NULL means the token has
72
+ // never been downloaded; the endpoint updates it after each successful
73
+ // stream.
75
74
  lastUsedAt: createTimestampField({}),
76
75
 
77
- // Audit: Anzahl der Downloads. Atom 4b incrementiert bei jedem
78
- // Stream. bigInt fuer fall einer pathologischer Re-Download-Schleife
79
- // (z.B. broken Sync-Tool).
76
+ // Audit count of downloads. `bigInt` accommodates pathological re-download
77
+ // loops, such as those caused by a broken sync tool.
80
78
  useCount: createBigIntField({}),
81
79
 
82
80
  // Audit: source IP of the last download. Helps the DPO investigate
@@ -99,11 +97,9 @@ export const exportDownloadTokenEntity = createEntity({
99
97
  }),
100
98
  },
101
99
 
102
- // 1 Token pro Job. UNIQUE auf jobId — Backstop fuer Worker-Idempotency
103
- // (Atom 3b's "2× run done-Job → no-op"). Der Worker created NIE ein
104
- // zweites Aggregat fuers gleiche jobId: Re-Runs rotieren das Token
105
- // in place via update (fw#832) — sonst kollidiert der Projection-
106
- // Rebuild an genau diesem Index.
100
+ // UNIQUE on `jobId` provides an idempotency backstop: rerunning a completed
101
+ // job must not create a second token aggregate. Re-runs update the existing
102
+ // token in place; otherwise projection rebuilds would collide on this index.
107
103
  indexes: [
108
104
  {
109
105
  unique: true,
@@ -8,19 +8,18 @@ import {
8
8
  createTimestampField,
9
9
  } from "@cosmicdrift/kumiko-framework/engine";
10
10
 
11
- // Export-Job-Lifecycle (S2.U3+U4 Atom 1).
11
+ // Export-job lifecycle.
12
12
  //
13
- // Spec: docs/plans/architecture/user-data-rights.md "Async Export-Pipeline".
14
- // User triggert `request-export` → ExportJob (status="pending"). Worker
15
- // pickt auf → "running" → erfolgreich "done" + downloadStorageKey gesetzt
13
+ // User triggers `request-export` → ExportJob (status="pending"). The worker
14
+ // picks it up → "running" → on success, "done" + downloadStorageKey set
16
15
  // + expiresAt = completedAt + compliance-profile.userRights.exportDownloadTtl
17
- // (per-Tenant-konfigurierbar via Override, Default 7 Tage). Bei Throw
18
- // oder Stale-Timeout → "failed" mit errorMessage. Stale-Timeout +
19
- // Storage-Cleanup-Grace ebenfalls aus dem compliance-profile.
16
+ // (configurable per tenant via override, default 7 days). On throw or stale
17
+ // timeout → "failed" with errorMessage. Stale timeout and storage-cleanup
18
+ // grace are also read from the compliance profile.
20
19
  //
21
- // Status-Werte als Constants — Single source of truth fuer Worker,
22
- // Application-Code (request-export-Handler), UI-Banner (Polling) und
23
- // Drift-Guard im Test.
20
+ // Status values are constants—the single source of truth for the worker,
21
+ // application code (`request-export` handler), UI polling banner, and test
22
+ // drift guard.
24
23
  export const EXPORT_JOB_STATUS = {
25
24
  Pending: "pending",
26
25
  Running: "running",
@@ -31,10 +30,10 @@ export const EXPORT_JOB_STATUS = {
31
30
  export type ExportJobStatus = (typeof EXPORT_JOB_STATUS)[keyof typeof EXPORT_JOB_STATUS];
32
31
 
33
32
  /**
34
- * DB-Constraint-Name fuer den Partial-UNIQUE-Index (1 aktiver Job pro
35
- * User). Single source of truth — request-export.write catched 23505
36
- * mit diesem Namen als Race-Schutz, Tests pinnen ihn als
37
- * `expectUniqueViolation`-Argument. Rename hier propagiert automatisch.
33
+ * Database constraint name for the partial UNIQUE index (one active job per
34
+ * user). This is the single source of truth: request-export.write catches
35
+ * 23505 with this name as race protection, and tests pin it as the
36
+ * `expectUniqueViolation` argument. Renaming it propagates automatically.
38
37
  */
39
38
  export const ACTIVE_JOB_CONSTRAINT = "read_export_jobs_one_active_per_user";
40
39
 
@@ -48,17 +47,16 @@ const EXPORT_JOB_STATUS_OPTIONS = [
48
47
  // **Tenant-agnostic** like userTable — one job per userId across all
49
48
  // memberships; the worker iterates cross-tenant via ctx.db.unsafeRaw (same pattern as runForgetCleanup).
50
49
  //
51
- // **Idempotency:** Partial-UNIQUE-Index auf `(userId)` WHERE
52
- // `status IN ('pending', 'running')`. User mit pending-Job kann keinen
53
- // zweiten parallelen Job starten — der Insert faellt mit Constraint-
54
- // Violation auf, der request-export-Handler (Atom 2) faengt das ab und
55
- // returnt den existing pending-Job (Insert-or-Return). Race-Window
56
- // null. Done/Failed-Jobs koennen beliebig viele pro User existieren
57
- // (Audit-Historie).
50
+ // **Idempotency:** Partial UNIQUE index on `(userId)` WHERE
51
+ // `status IN ('pending', 'running')`. A user with a pending job cannot start
52
+ // a second parallel job—the insert fails with a constraint violation, which
53
+ // the request-export handler catches and uses to return the existing pending
54
+ // job (insert-or-return). This closes the race window. Done/failed jobs can
55
+ // be retained indefinitely per user for audit history.
58
56
  //
59
- // **idType: "uuid"** — Job-IDs reisen ueber Process-Grenzen
60
- // (BullMQ-Payload, Job-Run-Logger, Audit-Events fuer DPO). Serial-IDs
61
- // sind nur prozess-lokal verlaesslich, UUIDs cross-process stabil.
57
+ // **idType: "uuid"** — job IDs cross process boundaries (BullMQ payloads,
58
+ // job-run logger, and audit events for the DPO). Serial IDs are only reliable
59
+ // within one process; UUIDs remain stable across processes.
62
60
  export const exportJobEntity = createEntity({
63
61
  table: "read_export_jobs",
64
62
  idType: "uuid",
@@ -66,11 +64,11 @@ export const exportJobEntity = createEntity({
66
64
  "One user's GDPR Art. 20 data-export request and its lifecycle: who asked, from which tenant, the pending/running/done/failed status, the timestamps, the download storage key and expiry, and any error the export worker hit.",
67
65
 
68
66
  fields: {
69
- // Tenant-agnostisch: Wert wird beim Schreiben gesetzt (Framework
70
- // braucht eine tenant_id-Spalte), domain-mäßig ignoriert.
71
- // Kein maxLength — folgt userTable.id + tenantMembershipsTable.userId
72
- // (beide ohne maxLength). UserId-Form ist Plattform-Konzern, hier
73
- // nur Storage.
67
+ // Tenant-agnostic: set when writing because the framework requires a
68
+ // tenant_id column, but ignored at the domain level.
69
+ // No maxLength — follows userTable.id and tenantMembershipsTable.userId
70
+ // (both have no maxLength). The userId shape is platform-wide; here it is
71
+ // only used for storage.
74
72
  userId: createTextField({
75
73
  required: true,
76
74
  searchable: true,
@@ -78,19 +76,19 @@ export const exportJobEntity = createEntity({
78
76
  reason: "pseudonymous_fk",
79
77
  }),
80
78
 
81
- // **requestedFromTenantId** — der Tenant aus dem der User den Antrag
82
- // gestellt hat. Persistierter Audit-Pfad fuer den Worker (welches
83
- // Compliance-Profile gilt fuer Job-TTL/Stale/Cleanup) — DSGVO-
84
- // konsistent: 1 User = 1 effektives Profile pro Antrag, nicht "wechselt
85
- // mit jedem Cross-Tenant-Klick". Plan-Doc-Decision: Tenant aus 1. Klick
86
- // (Option a). Spalte heisst nicht einfach "tenantId" damit kein
87
- // Verwechseln mit der Framework-Auto-Spalte tenant_id.
79
+ // **requestedFromTenantId** — the tenant from which the user submitted the
80
+ // request. This persisted audit path tells the worker which compliance
81
+ // profile applies to the job TTL, stale timeout, and cleanup. This keeps
82
+ // one effective profile per request instead of changing with every
83
+ // cross-tenant click. The tenant is taken from the first click (option a).
84
+ // The column is not simply named "tenantId" to avoid confusion with the
85
+ // framework-generated tenant_id column.
88
86
  //
89
- // **Atom 3b Worker-Hinweis:** Profile-Resolution muss ueber
90
- // `requestedFromTenantId` laufen (`queryAs(systemUserOf(requestedFromTenantId),
91
- // "compliance-profiles:query:for-tenant", {})`), NICHT ueber
92
- // `executor.tenantId` — sonst kriegt ein Job-Pickup aus einem anderen
93
- // Tenant-Context ein falsches Profile.
87
+ // **Worker note:** Profile resolution must use `requestedFromTenantId`
88
+ // (`queryAs(systemUserOf(requestedFromTenantId),
89
+ // "compliance-profiles:query:for-tenant", {})`), not
90
+ // `executor.tenantId`; otherwise a job picked up from another tenant
91
+ // context would use the wrong profile.
94
92
  requestedFromTenantId: createTextField({
95
93
  required: true,
96
94
  personal: false,
@@ -103,40 +101,40 @@ export const exportJobEntity = createEntity({
103
101
  options: EXPORT_JOB_STATUS_OPTIONS,
104
102
  }),
105
103
 
106
- // Wann hat der User den Job angefordert. Required — kein Job-Row
107
- // entsteht ohne Klick.
104
+ // When the user requested the job. Required because no job row exists
105
+ // without a request.
108
106
  requestedAt: createTimestampField({
109
107
  required: true,
110
108
  sortable: true,
111
109
  }),
112
110
 
113
- // Wann hat der Worker mit dem Pickup angefangen. NULL solange
114
- // `pending`. Stale-Detection nutzt das +
111
+ // When the worker began processing the job. NULL while `pending`.
112
+ // Stale detection uses this together with
115
113
  // compliance-profile.userRights.exportStaleTimeoutMinutes.
116
114
  startedAt: createTimestampField({}),
117
115
 
118
- // Wann hat der Worker abgeschlossen (success oder fail). NULL
119
- // solange running.
116
+ // When the worker completed the job, successfully or with failure. NULL
117
+ // while `running`.
120
118
  completedAt: createTimestampField({}),
121
119
 
122
- // Storage-Key des fertigen ZIP-Files. NULL solange nicht `done`.
123
- // Worker setzt das + die ZIP-Bytes via storage-provider.write(key).
124
- // Dies ist KEIN signed-URL — der Download-Endpoint generiert den
125
- // signed-URL on demand vom Storage-Provider (Atom 4).
120
+ // Storage key of the completed ZIP file. NULL until `done`.
121
+ // The worker sets this and writes the ZIP bytes via
122
+ // storage-provider.write(key).
123
+ // This is not a signed URL—the download endpoint generates the signed URL
124
+ // on demand through the storage provider.
126
125
  downloadStorageKey: createTextField({
127
126
  maxLength: 500,
128
127
  personal: false,
129
128
  reason: "technical_reference",
130
129
  }),
131
130
 
132
- // Ab wann ist der Download nicht mehr abrufbar. Worker setzt
131
+ // When the download is no longer available. The worker sets
133
132
  // `completedAt + compliance-profile.userRights.exportDownloadTtl`
134
- // beim Flip auf `done`. NULL fuer pending/running/failed.
133
+ // when switching to `done`. NULL for pending, running, and failed jobs.
135
134
  //
136
- // Storage-Cleanup-Pflicht: Worker laesst nach
137
- // `expiresAt + compliance-profile.userRights.exportStorageCleanupGraceHours`
138
- // einen separaten Pass loeschen damit abgelaufene ZIPs nicht auf S3
139
- // verbleiben.
135
+ // Storage cleanup requirement: after
136
+ // `expiresAt + compliance-profile.userRights.exportStorageCleanupGraceHours`,
137
+ // a separate pass deletes expired ZIPs so they do not remain on S3.
140
138
  expiresAt: createTimestampField({}),
141
139
 
142
140
  // Failed-state diagnostics. longText because hook errors with stack
@@ -147,20 +145,20 @@ export const exportJobEntity = createEntity({
147
145
  reason: "is_business_data",
148
146
  }),
149
147
 
150
- // Audit-Info fuer Operator: wie gross war der Export. Hilft beim
151
- // Capacity-Planning + erkennt pathologische Cases (Streaming-ZIP
152
- // mit 5 GB Files schreibt mehrere Mrd Bytes, integer-Overflow waere
153
- // silent + Audit-Drift).
148
+ // Audit information for operators: the export size. This supports capacity
149
+ // planning and detects pathological cases (a streaming ZIP containing 5 GB
150
+ // of files writes several billion bytes, so integer overflow would cause
151
+ // silent audit drift).
154
152
  //
155
- // bigInt liefert JS-`number` Round-trip via mode:"number" — sicher
156
- // bis 2^53 ≈ 9 PB, JSON-tauglich fuer das Status-Polling.
153
+ // bigInt provides a JS-`number` round trip via mode:"number", safe up to
154
+ // 2^53 ≈ 9 PB and suitable for JSON-based status polling.
157
155
  bytesWritten: createBigIntField({}),
158
156
  },
159
157
 
160
- // Partial-UNIQUE-Index: nur 1 aktiver Job pro User, Done/Failed-
161
- // Historie ist unbeschraenkt. request-export.write nutzt App-side-
162
- // Pre-Check als primaeren Pfad + 23505-Catch dieser Constraint als
163
- // Race-Schutz fuer das <1ms-Window zwischen fetchOne + crud.create.
158
+ // Partial UNIQUE index: only one active job per user; done/failed history
159
+ // is unlimited. request-export.write uses an application-side pre-check as
160
+ // the primary path and catches this constraint's 23505 as race protection
161
+ // for the <1ms window between fetchOne and crud.create.
164
162
  indexes: [
165
163
  {
166
164
  unique: true,
@@ -1,30 +1,27 @@
1
- // Download-Token-Helper (S2.U3 Atom 4a).
1
+ // Generates a cryptographically secure token to authorize the export ZIP download.
2
+ // Follows the Magic-Link/Bearer-Token pattern with a hash stored in the database:
2
3
  //
3
- // Generiert ein kryptographisch-sicheres Token zur Authorisierung des
4
- // Export-ZIP-Downloads. Pattern matched Magic-Link/Bearer-Token mit DB-
5
- // gespeichertem Hash:
6
- //
7
- // 1. Worker generiert plain-Token (32 byte random base64url) + Hash
4
+ // 1. The worker generates a plain token (32 random bytes, base64url) and its hash
8
5
  // (SHA256 hex).
9
- // 2. DB speichert NUR den Hash. Plain bleibt im Worker-Memory.
10
- // 3. Atom 5 (Notification) versendet plain via Email an User.
11
- // 4. Atom 4b (Download-Endpoint) hashet incoming-Token + vergleicht
12
- // mit DB-Hash → konstantes-Zeit-Vergleich gegen timing-attacks.
6
+ // 2. The database stores ONLY the hash. The plain token remains in worker memory.
7
+ // 3. The notification step sends the plain token to the user by email.
8
+ // 4. The download endpoint hashes the incoming token and compares it with the
9
+ // database hash using a constant-time comparison to prevent timing attacks.
13
10
  //
14
- // **Multi-use within TTL** (User-Choice 4a-Plan): Token wird NICHT
15
- // "consumed" beim Download — User kann mehrfach downloaden bis expiresAt.
16
- // Pattern matched Google-Takeout (7d) + Facebook-Data-Download (4d).
11
+ // **Multi-use within TTL:** The token is NOT "consumed" on download, so the user
12
+ // can download repeatedly until expiresAt. This matches Google-Takeout (7d) and
13
+ // Facebook-Data-Download (4d).
17
14
  //
18
15
  // **Universal Web-Crypto API:** crypto.getRandomValues + crypto.subtle.digest
19
- // laeuft in Bun + Node 19+ + Browser identisch — keine plattform-
20
- // spezifischen Imports (Memory `feedback_universal_deps`).
16
+ // runs identically in Bun, Node 19+, and browsers, avoiding platform-specific
17
+ // imports.
21
18
 
22
19
  /**
23
- * Generiert ein neues Download-Token. plain wird dem User via Email
24
- * zugestellt (Atom 5); hash landet in der Token-DB-Row.
20
+ * Generates a new download token. The plain token is sent to the user by email;
21
+ * the hash is stored in the token database row.
25
22
  *
26
- * Token-Format: 32 byte random → base64url-encoded (~43 chars). URL-safe
27
- * fuer Magic-Link-Verwendung (kein +/= das URL-encoded werden muesste).
23
+ * Token format: 32 random bytes → base64url-encoded (~43 chars). URL-safe for
24
+ * Magic-Link use (no +/= characters that would need to be URL-encoded).
28
25
  */
29
26
  export async function generateDownloadToken(): Promise<{
30
27
  readonly plain: string;
@@ -37,11 +34,10 @@ export async function generateDownloadToken(): Promise<{
37
34
  }
38
35
 
39
36
  /**
40
- * Hashed einen plain-Token zu seiner DB-Repraesentation. Verify-Pfad
41
- * (Atom 4b's Download-Endpoint): hashed incoming-Token + sucht den Hash
42
- * in DB. Konstante-Zeit-String-Vergleich verhindert timing-attacks
43
- * (das macht der Caller via `crypto.subtle`-vergleich oder secure-
44
- * compare-helper).
37
+ * Hashes a plain token into its database representation. In the verification path,
38
+ * the download endpoint hashes the incoming token and looks up the hash in the
39
+ * database. A constant-time string comparison prevents timing attacks; the caller
40
+ * performs it via `crypto.subtle` or a secure comparison helper.
45
41
  */
46
42
  export async function hashDownloadToken(plain: string): Promise<string> {
47
43
  const encoded = new TextEncoder().encode(plain);
@@ -50,7 +46,7 @@ export async function hashDownloadToken(plain: string): Promise<string> {
50
46
  }
51
47
 
52
48
  function uint8ArrayToBase64Url(bytes: Uint8Array): string {
53
- // btoa erwartet binary-string. atob/btoa sind universal in Bun + Node + Browser.
49
+ // btoa expects a binary string. atob/btoa are universal in Bun, Node, and browsers.
54
50
  let binary = "";
55
51
  for (let i = 0; i < bytes.length; i++) {
56
52
  binary += String.fromCharCode(bytes[i] as number); // @cast-boundary dynamic-key
@@ -6,7 +6,7 @@
6
6
  // createKumikoApp({ clientFeatures: [userDataRightsClient()] }); the screen
7
7
  // has no own r.nav, the app places it via r.nav.
8
8
  //
9
- // fw#2312: the former `privacyCenter: { showDeletion }` option is gone — a
9
+ // The former `privacyCenter: { showDeletion }` option is gone — a
10
10
  // declarative screen is now registered server-side once for all apps, so a
11
11
  // client prop can no longer toggle its sections/actions per app. Its
12
12
  // replacement is the server-side
@@ -22,12 +22,12 @@ import { ExportSection } from "./privacy-center-screen.tsx";
22
22
  import { makePublicDeletionGate, type PublicDeletionRoutes } from "./public-deletion-gate.tsx";
23
23
 
24
24
  export type UserDataRightsClientOptions = {
25
- /** Key-weise Overrides über die Default-Bundles (de/en). */
25
+ /** Overrides merged into the default bundles (de/en). */
26
26
  readonly translations?: TranslationsByLocale;
27
- /** Wenn gesetzt: registriert die anonymen (login-freien) Lösch-Screens als
28
- * Gate auf den angegebenen Pfaden. Weglassen → nur der eingeloggte
29
- * privacy-center-Screen. Den Client VOR dem Auth-Client listen, sonst
30
- * landet der anonyme Besucher auf der Login-Maske. */
27
+ /** When set, registers the anonymous (login-free) deletion screens as a
28
+ * gate on the specified paths. If omitted, only the authenticated
29
+ * privacy-center screen is available. Register this client BEFORE the auth
30
+ * client; otherwise, anonymous visitors are redirected to the login screen. */
31
31
  readonly publicDeletion?: PublicDeletionRoutes;
32
32
  };
33
33
 
@@ -1,9 +1,10 @@
1
- // ConfirmAccountDeletionScreen — anonymer Apex-Screen Schritt 2. Liest das
2
- // Token aus dem URL-Fragment (`#token=…`, nie an den Server gesendet — landet
3
- // so nicht in Proxy-/Access-Logs, fw#1554) und dispatcht beim Bestätigen
4
- // user-data-rights:write:confirm-deletion-by-token → startet die Grace-Period.
1
+ // ConfirmAccountDeletionScreen — anonymous Apex screen, step 2. Reads the
2
+ // token from the URL fragment (`#token=…`, never sent to the server, so it does
3
+ // not appear in proxy/access logs) and dispatches
4
+ // user-data-rights:write:confirm-deletion-by-token on confirmation to start the
5
+ // grace period.
5
6
  //
6
- // App mountet den Screen unter der deletionVerifyUrl-Route (z.B.
7
+ // The app mounts this screen at the deletionVerifyUrl route (for example,
7
8
  // /delete-account/confirm) via createPublicSurface.
8
9
 
9
10
  import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
@@ -17,7 +17,7 @@ export const PRIVACY_CENTER_SCREEN_ID = "privacy-center" as const;
17
17
  export const EXPORT_SECTION_EXTENSION_NAME = "UserDataRightsExportSection" as const;
18
18
 
19
19
  // enumOption keyPrefix for the privacy-center screen's `status` field
20
- // (fw#2315 pattern) — resolves the raw user-lifecycle enum value
20
+ // pattern — resolves the raw user-lifecycle enum value
21
21
  // (active/restricted/deletionRequested/deleted) to a translated label
22
22
  // instead of showing the raw string.
23
23
  export const STATUS_OPTION_KEY_PREFIX =
@@ -1,8 +1,8 @@
1
- // Public exports für die Browser-Seite des user-data-rights Features —
2
- // die anonymen Apex-Deletion-Screens. Konsumiert via Sub-Path-Export
3
- // `@cosmicdrift/kumiko-bundled-features/user-data-rights/web`. Die Server-
4
- // Seite (defineFeature, Handler) lebt unter `.../user-data-rights` und hat
5
- // keine React-/DOM-Deps.
1
+ // Public exports for the browser side of the user-data-rights feature —
2
+ // the anonymous Apex deletion screens. Consumed via the subpath export
3
+ // `@cosmicdrift/kumiko-bundled-features/user-data-rights/web`. The server
4
+ // side (defineFeature, Handler) lives under `.../user-data-rights` and has
5
+ // no React/DOM dependencies.
6
6
 
7
7
  export { type UserDataRightsClientOptions, userDataRightsClient } from "./client-plugin.tsx";
8
8
  export type { ConfirmAccountDeletionScreenProps } from "./confirm-deletion-screen.tsx";
@@ -1,6 +1,6 @@
1
1
  import { EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-renderer/headless";
2
2
  // Export section (Art. 20) — the one part of user-data-rights' privacy-center
3
- // screen that stays custom (fw#2312). Registered as an EditExtensionSection
3
+ // screen that stays custom. Registered as an EditExtensionSection
4
4
  // component (see web/client-plugin.tsx); the projectionDetail screen
5
5
  // (feature.ts) supplies the surrounding Section chrome (title, testId), so
6
6
  // this component renders only its own body content.
@@ -26,9 +26,9 @@ import {
26
26
  UserDataRightsQueries,
27
27
  } from "./constants.ts";
28
28
 
29
- // Export-Job läuft async (worker-Lane-Cron, ~1 Min). Solange er pending/running
30
- // ist, pollt der Screen den Status, damit der Download ohne manuellen Reload
31
- // erscheint.
29
+ // The export job runs asynchronously (worker-Lane-Cron, ~1 Min). While it is
30
+ // pending/running, the screen polls its status so the download appears without
31
+ // a manual reload.
32
32
  const EXPORT_POLL_MS = 4000;
33
33
 
34
34
  type ExportJob = {
@@ -47,15 +47,16 @@ type SectionStatus =
47
47
  | { kind: "success"; messageKey: string }
48
48
  | { kind: "error"; messageKey: string };
49
49
 
50
- // Dispatcher-Failures tragen i18nKey nur wenn der Handler einen setzt —
51
- // Boundary-Read mit generischem Fallback.
50
+ // Dispatcher failures include i18nKey only when the handler sets one; read it
51
+ // at the boundary with a generic fallback.
52
52
  function failureKey(error: unknown): string {
53
53
  const key = propertyOf(error, "i18nKey");
54
54
  return typeof key === "string" ? key : "userDataRights.privacyCenter.errors.generic";
55
55
  }
56
56
 
57
- // Roher ISO-Instant → nur der Datums-Teil ist relevant; reiner String-Slice,
58
- // kein Date-API (no-date-api-Guard) und universell. Leer/null → "—".
57
+ // Only the date portion of the raw ISO instant is relevant; use a string slice
58
+ // instead of the Date API (no-date-api-Guard) for universal support. Empty/null
59
+ // values become "—".
59
60
  export function formatDate(iso: string | null | undefined): string {
60
61
  if (!iso) return EMPTY_VALUE_PLACEHOLDER;
61
62
  const tIndex = iso.indexOf("T");
@@ -97,10 +98,10 @@ export function ExportSection(): ReactNode {
97
98
  void statusQuery.refetch?.();
98
99
  };
99
100
 
100
- // Download laeuft ueber den Dispatcher (traegt X-CSRF-Token) statt ueber
101
- // eine <a>-Navigation: download-by-job liefert eine signed URL zurueck, auf
102
- // die postWithDownload den Browser navigiert (content-disposition:
103
- // attachment → laedt herunter).
101
+ // Download runs through the dispatcher (which supplies X-CSRF-Token) instead of
102
+ // an <a>-navigation: download-by-job returns a signed URL, which
103
+ // postWithDownload navigates the browser to (content-disposition:
104
+ // attachment → triggers a download).
104
105
  const downloadExport = async (jobId: string): Promise<void> => {
105
106
  const err = await postWithDownload(dispatcher, UserDataRightsQueries.downloadByJob, { jobId });
106
107
  if (err) setStatus({ kind: "error", messageKey: failureKey(err) });
@@ -116,7 +117,7 @@ export function ExportSection(): ReactNode {
116
117
 
117
118
  // While the job is running: poll until Done/Failed, then auto-stop.
118
119
  const refetch = statusQuery.refetch;
119
- // kumiko-lint-ignore no-raw-hooks Phase-3 conversion tracked in #2312
120
+ // kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
120
121
  useEffect(() => {
121
122
  if (!inProgress || !refetch) return;
122
123
  const id = setInterval(() => void refetch(), EXPORT_POLL_MS);