@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,4 +1,4 @@
1
- // kumiko-lint-ignore app-feature-structure Phase-3 conversion tracked in #2312 (feature.ts > 300 lines)
1
+ // kumiko-lint-ignore app-feature-structure feature.ts is over 300 lines and not yet split
2
2
  import { UNKNOWN_CLIENT_IP } from "@cosmicdrift/kumiko-framework/api";
3
3
  import {
4
4
  createSystemConfig,
@@ -83,87 +83,85 @@ import {
83
83
  } from "./web/constants.ts";
84
84
  import { USER_DATA_RIGHTS_I18N } from "./web/i18n.ts";
85
85
 
86
- // user-data-rights — DSGVO Art. 15 (Auskunft) + Art. 17 (Löschung) +
87
- // Art. 18 (Restriction) + Art. 20 (Portabilität) als Core-Feature.
86
+ // user-data-rights — GDPR Articles 15 (access), 17 (erasure),
87
+ // 18 (restriction), and 20 (portability) as a core feature.
88
88
  //
89
- // Pattern (Plan-Roadmap docs/plans/datenschutz/user-data-rights.md):
90
- // Statt jedes Feature seine eigene Forget-/Export-Logik schreibt,
91
- // haengt es sich via `r.useExtension(EXT_USER_DATA, "<entity>", {
92
- // export, delete })` an. user-data-rights orchestriert:
93
- // - Export-Job: iteriert alle Extension-Registrierungen, sammelt JSON
94
- // - Forget-Job: iteriert alle, ruft delete-Hook mit Strategy aus
95
- // retention.policyFor (data-retention)
96
- // - Restriction: status-Flip auf user-Schema, Auth-Middleware-Guard
89
+ // Instead of making each feature implement its own forget/export logic,
90
+ // it registers through `r.useExtension(EXT_USER_DATA, "<entity>", {
91
+ // export, delete })`. user-data-rights orchestrates:
92
+ // - Export job: iterates over all extension registrations and collects JSON
93
+ // - Forget job: iterates over all registrations and calls each delete hook
94
+ // with the strategy from `retention.policyFor` (data-retention)
95
+ // - Restriction: flips the user-schema status and enables the auth guard
97
96
  /**
98
- * Options fuer createUserDataRightsFeature. Notification-Callbacks
99
- * (Atom 5) folgen dem password-reset-Pattern aus auth-routes.ts.
97
+ * Options for createUserDataRightsFeature. Notification callbacks follow
98
+ * the password-reset pattern in auth-routes.ts.
100
99
  *
101
- * Plain-Token landet NIE in DB/event-store/jobRunsTable — Worker reicht
102
- * ihn ephemeral via Callback-arg an die App-Author-Implementation
103
- * (typisch: `delivery.notify(...)` mit `r.notification`-Templates,
104
- * `mailFoundation.send` direkt, oder Custom Resend/SES).
100
+ * The plain token is never stored in the DB, event store, or jobRunsTable.
101
+ * The worker passes it ephemerally as a callback argument to the app-author
102
+ * implementation (typically `delivery.notify(...)` with `r.notification`
103
+ * templates, `mailFoundation.send` directly, or custom Resend/SES).
105
104
  *
106
- * Worker-Run-Tracking + Retry kommt automatisch via existing
107
- * `jobs`-Feature (siehe CLAUDE.md "Bundled-Features by Concern").
105
+ * Worker-run tracking and retries are provided automatically by the existing
106
+ * `jobs` feature.
108
107
  */
109
108
  export type UserDataRightsOptions = {
110
- /** Email-Notification beim Export-done. App-Author wired das an seinen
111
- * Email-Provider. Best-effort (Atom 5.fix3): send-Throw fuer Job A
112
- * killt den Batch nicht — restliche pending-Jobs werden weiter
113
- * verarbeitet, Failure wird via console.warn sichtbar. (Vorher
114
- * bubbelte der Throw zum r.job-Wrap, was bei mehreren pending Jobs
115
- * zum silent-miss fuehrte: Job A done committed, B/C/D nie
116
- * verarbeitet, retry findet niemand.) */
109
+ /** Email notification when the export completes. The app author connects it
110
+ * to an email provider. Best effort: a send failure for Job A does not stop
111
+ * the batch; remaining pending jobs continue, and the failure is exposed via
112
+ * console.warn. Previously, the error reached the r.job wrapper, so with
113
+ * multiple pending jobs A could commit while B/C/D were never processed and
114
+ * no retry could find them. */
117
115
  readonly sendExportReadyEmail?: SendExportReadyEmailFn;
118
116
  /** Email-Notification beim Export-failed. Best-effort analog
119
117
  * sendExportReadyEmail. */
120
118
  readonly sendExportFailedEmail?: SendExportFailedEmailFn;
121
- /** Base-URL fuer den Magic-Link, z.B.
122
- * "https://app.example.com/user-export/by-token". Worker bauen
123
- * a URL fragment (`#token=<plain>`, issue #1271). Required wenn
124
- * sendExportReadyEmail gesetzt. Per-Tenant via reverse-proxy host
125
- * routing — nicht via per-Tenant-config-key (App-Author-Decision). */
119
+ /** Base URL for the magic link, e.g.
120
+ * "https://app.example.com/user-export/by-token". The worker builds
121
+ * a URL fragment (`#token=<plain>`). Required when
122
+ * sendExportReadyEmail is set. Routing uses the reverse-proxy host per
123
+ * tenant rather than a per-tenant config key. */
126
124
  readonly appExportDownloadUrl?: string;
127
- /** Atom 5b — Email-Notification beim deletion-requested-flip
128
- * ("Account-Loeschung in 30 Tagen"). Best-effort: send-failure killt
129
- * den Status-Flip nicht (siehe handlers/request-deletion.write.ts). */
125
+ /** Email notification when deletion is requested ("account deletion in
126
+ * 30 days"). Best effort: a send failure does not abort the status flip
127
+ * (see handlers/request-deletion.write.ts). */
130
128
  readonly sendDeletionRequestedEmail?: SendDeletionRequestedEmailFn;
131
- /** Atom 5b — Email-Notification beim Cleanup-Runner-done-Pfad
132
- * ("Account wurde geloescht"). Best-effort. Der Versand passiert NACH
133
- * dem User-Hook-Anonymisieren, deshalb cached der Worker
134
- * userEmail+tenantIds PRE-tx und reicht sie ephemeral an die
135
- * Callback-Implementation (siehe run-forget-cleanup.ts). */
129
+ /** Email notification after the cleanup runner completes ("account deleted").
130
+ * Best effort. Delivery occurs after the user hook anonymizes the user, so
131
+ * the worker caches userEmail+tenantIds before the transaction and passes
132
+ * them ephemerally to the callback implementation (see
133
+ * run-forget-cleanup.ts). */
136
134
  readonly sendDeletionExecutedEmail?: SendDeletionExecutedEmailFn;
137
- /** Anonymer, email-verifizierter Apex-Deletion-Flow (Lockout-sicher).
138
- * HMAC-Secret zum Signieren des Verify-Tokens. Ohne Secret bleibt der
139
- * Flow deaktiviert (request-by-email antwortet still success, confirm-
140
- * by-token weist generisch ab). */
135
+ /** Anonymous, email-verified apex deletion flow that is safe against lockout.
136
+ * HMAC secret for signing the verification token. Without a secret, the
137
+ * flow remains disabled: request-by-email returns success silently, while
138
+ * confirm-by-token rejects generically. */
141
139
  readonly deletionTokenSecret?: string;
142
- /** Basis-URL des Apex-Confirm-Screens, z.B.
143
- * "https://app.example.com/delete-account/confirm". Der Handler hängt das
144
- * Token als URL-Fragment an (`#token=<token>`, fw#1554). Required wenn
145
- * deletionTokenSecret gesetzt. */
140
+ /** Base URL of the apex confirmation screen, e.g.
141
+ * "https://app.example.com/delete-account/confirm". The handler appends
142
+ * the token as a URL fragment (`#token=<token>`). Required when
143
+ * deletionTokenSecret is set. */
146
144
  readonly deletionVerifyUrl?: string;
147
- /** Versand des Verify-Magic-Links (Schritt 1 des anonymen Flows).
148
- * Best-effort, app-author-wired. MUSS non-blocking sein (enqueue, z.B.
149
- * delivery.notify) — ein synchroner Send reintroduziert ein Timing-Oracle
150
- * für Account-Enumeration (siehe SendDeletionVerificationEmailFn-Doc).
151
- * Bewusst KEINE mail-foundation-Default: ein synchroner Default-Send
152
- * brächte genau dieses Enumeration-Oracle zurück, deshalb app-wired. */
145
+ /** Sends the verification magic link (step 1 of the anonymous flow).
146
+ * Best effort and wired by the app author. It MUST be non-blocking (enqueue,
147
+ * e.g. via delivery.notify): a synchronous send would reintroduce a timing
148
+ * oracle for account enumeration (see SendDeletionVerificationEmailFn-doc).
149
+ * There is deliberately no mail-foundation default because a synchronous
150
+ * default send would restore that enumeration oracle. */
153
151
  readonly sendDeletionVerificationEmail?: SendDeletionVerificationEmailFn;
154
- /** C6 — Zero-Callback-GDPR-Mails: ist mail-foundation + ein mail-transport-*
155
- * gemountet, versendet user-data-rights die Export-/Loesch-Notifications
156
- * selbst (Export-ready/-failed, Deletion-requested/-executed) ueber die
157
- * Default-Templates (email-templates.ts) — die App schreibt keinen Callback.
158
- * `mailDefaults` brandet diese Default-Mails (Locale + App-Name). Greift NUR
159
- * wenn der jeweilige send*Email-Opt NICHT gesetzt ist; Export-ready braucht
160
- * zusaetzlich appExportDownloadUrl. */
152
+ /** Zero-callback GDPR mail: when mail-foundation and a mail-transport-* are
153
+ * mounted, user-data-rights sends export and deletion notifications itself
154
+ * (export-ready/-failed, deletion-requested/-executed) using the default
155
+ * templates (email-templates.ts), without an app callback.
156
+ * `mailDefaults` brands these default messages (locale and app name). It
157
+ * applies only when the relevant send*Email option is unset; export-ready
158
+ * also requires appExportDownloadUrl. */
161
159
  readonly mailDefaults?: GdprMailDefaults;
162
160
  /** Hides the Art. 17 deletion section + its request-deletion/cancel-deletion
163
161
  * actions on the privacy-center screen — for apps that already offer
164
162
  * account deletion elsewhere (e.g. a profile danger-zone), against
165
163
  * duplication. Default `true` (deletion section shown).
166
- * BREAKING (fw#2312): replaces the removed client-side
164
+ * BREAKING: replaces the removed client-side
167
165
  * `userDataRightsClient({ privacyCenter: { showDeletion } })` option —
168
166
  * the screen is now declared once, server-side (`type: "projectionDetail"`),
169
167
  * so per-app visibility can only be a boot-time option, not a client-side
@@ -202,18 +200,18 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
202
200
  r.envSchema(deletionTokenSecretEnvSchema);
203
201
  r.usesApi("compliance.forTenant");
204
202
  r.usesApi("retention.policyFor");
205
- // S2.U6 — restrict-account ruft sessions.revokeAllForUser cross-feature.
206
- // r.usesApi sorgt fuer Boot-Validation: App ohne sessions-feature wirft
207
- // beim Boot, statt erst beim ersten Restrict-Call ein opaque "handler
208
- // not found" zu werfen.
203
+ // restrict-account calls sessions.revokeAllForUser across features.
204
+ // r.usesApi enables boot validation: without the sessions feature, the app
205
+ // fails at boot instead of raising an opaque "handler not found" error
206
+ // on the first restrict call.
209
207
  r.usesApi("sessions.revokeAllForUser");
210
- // file-foundation ist soft-dep: nur der Export-Worker (Atom 3b)
211
- // braucht ihn fuer Storage-Schreiben. Apps die nur Forget nutzen
212
- // (kein Export) muessen file-foundation nicht mounten.
208
+ // file-foundation is a soft dependency: only the export worker needs it
209
+ // for storage writes. Apps that use only forget (not export) do not need
210
+ // to mount file-foundation.
213
211
 
214
212
  r.extendsRegistrar(EXT_USER_DATA, {});
215
213
 
216
- // GDPR-storage guards V2+V3 (#1314) — moved off the framework-internal
214
+ // GDPR-storage guards V2+V3 — moved off the framework-internal
217
215
  // boot-validator onto this feature's own r.bootCheck(), since it's the
218
216
  // EXT_USER_DATA channel owner: any r.useExtension(EXT_USER_DATA, ...)
219
217
  // usage already requires user-data-rights to be mounted.
@@ -243,24 +241,24 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
243
241
  }),
244
242
  );
245
243
 
246
- // S2.U3 Atom 1b — ExportJob-Lifecycle-Entity.
244
+ // ExportJob-Lifecycle-Entity.
247
245
  r.entity({ name: "export-job", ...exportJobEntity });
248
246
 
249
- // S2.U3 Atom 4a — Download-Token-Entity. Worker generiert Token beim
250
- // Flip auf done (siehe run-export-jobs.ts). Hash in DB, plain im
251
- // RunExportJobsResult fuer Atom 5 (Notification per Email).
247
+ // The worker generates the token when flipping the job to done (see
248
+ // run-export-jobs.ts). The hash is stored in the database, while the plain
249
+ // token is kept in RunExportJobsResult for email notification.
252
250
  r.entity({ name: "export-download-token", ...exportDownloadTokenEntity });
253
251
 
254
- // S2.U7 — Audit-Trail invalid Download-Attempts (DPO Brute-Force-Detection).
252
+ // Audit-Trail invalid Download-Attempts (DPO Brute-Force-Detection).
255
253
  r.entity({ name: "download-attempt", ...downloadAttemptEntity });
256
254
 
257
- // S2.U6 — DSGVO Art. 18 Account-Freeze (Verarbeitungs-Pause).
258
- // Endpoints fuer Restrict + Lift. Login-Block fuer Restricted Users
259
- // lebt in auth-email-password/login.write.ts.
255
+ // GDPR Article 18 account freeze (pause processing).
256
+ // The endpoints restrict and lift the restriction. The login block for
257
+ // restricted users lives in auth-email-password/login.write.ts.
260
258
  r.writeHandler(restrictAccountWrite);
261
259
  r.writeHandler(liftRestrictionWrite);
262
260
 
263
- // S2.U5a — Endpoints fuer DSGVO Art. 17 Forget-Pfad mit Grace.
261
+ // Endpoints for the GDPR Article 17 forget path with a grace period.
264
262
  r.writeHandler(
265
263
  createRequestDeletionHandler({
266
264
  ...(opts.sendDeletionRequestedEmail && {
@@ -293,10 +291,10 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
293
291
  ),
294
292
  );
295
293
 
296
- // S2.U5b — Cleanup-Runner als privileged-Handler. Atom 5b: Wenn
297
- // sendDeletionExecutedEmail gesetzt, reicht der Handler den Callback
298
- // an runForgetCleanup weiter (Worker cached userEmail+tenantIds
299
- // PRE-tx, siehe run-forget-cleanup.ts).
294
+ // Cleanup runner as a privileged handler. When
295
+ // sendDeletionExecutedEmail is set, the handler passes the callback to
296
+ // runForgetCleanup; the worker caches userEmail+tenantIds before the
297
+ // transaction (see run-forget-cleanup.ts).
300
298
  r.writeHandler(
301
299
  createRunForgetCleanupHandler(
302
300
  opts.sendDeletionExecutedEmail
@@ -306,20 +304,20 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
306
304
  );
307
305
  r.exposesApi("userDataRights.runForget");
308
306
 
309
- // S2.U3 Atom 2 — User-Touchpoints fuer Async Export-Pipeline.
307
+ // User touchpoints for the asynchronous export pipeline.
310
308
  r.writeHandler(requestExportWrite);
311
309
  r.queryHandler(exportStatusQuery);
312
310
  r.exposesApi("userDataRights.runExport");
313
311
 
314
- // S2.U3 Atom 4b — Download-Endpoints (Token-Pfad + Session-Pfad).
315
- // Beide query-handlers verifizieren Token/Session, holen signed-URL
316
- // vom Storage-Provider, und persistieren Audit-Felder am Token-Row.
317
- // r.httpRoute-Wrapper unten machen den 302-Redirect zu signedUrl.
312
+ // Download endpoints for token and session paths.
313
+ // Both query handlers verify the token or session, obtain a signed URL
314
+ // from the storage provider, and persist audit fields on the token row.
315
+ // The r.httpRoute wrappers below issue the 302 redirect to signedUrl.
318
316
  r.queryHandler(downloadByTokenQuery);
319
317
  r.queryHandler(downloadByJobQuery);
320
318
 
321
- // S2.U7 — User-Selbstauskunft (Art. 15) + Operator-Sicht auf
322
- // invalid Download-Attempts (DPO).
319
+ // User self-access under Article 15 and operator access to invalid download
320
+ // attempts (DPO).
323
321
  r.queryHandler(myAuditLogQuery);
324
322
  r.queryHandler(listDownloadAttemptsQuery);
325
323
 
@@ -483,12 +481,12 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
483
481
  // Magic-link path (anonymous): the email link carries the token as a
484
482
  // URL fragment (`#token=<plain>`) instead of a query param — fragments
485
483
  // never leave the browser, so they never hit proxy/access logs
486
- // (issue #1271). This route only serves the interstitial page; the
484
+ // This route only serves the interstitial page; the
487
485
  // external script reads the fragment client-side and exchanges the
488
486
  // token via POST for the signed URL.
489
487
  //
490
- // No `?token=` query fallback: framework is zero-legacy (#1512) — no
491
- // live customer data / no pre-#1271 emails in flight that would need
488
+ // No `?token=` query fallback: framework is zero-legacy — no
489
+ // live customer data / no emails in flight that would need
492
490
  // bridging, so there's nothing a fallback would need to cover. A query
493
491
  // param reaches the server as part of the request URL and gets written
494
492
  // to proxy/access logs regardless of what the handler does with it
@@ -532,7 +530,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
532
530
  });
533
531
 
534
532
  // Exchange endpoint for the interstitial page: the token arrives here
535
- // as a POST body instead of a query string (issue #1271). A dedicated
533
+ // as a POST body instead of a query string. A dedicated
536
534
  // route rather than letting the browser JS call /api/query directly,
537
535
  // for two reasons:
538
536
  // 1. IP/UA audit — extractAuditMeta needs the raw request headers and
@@ -571,7 +569,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
571
569
  // defaults to 0, ignoring headers entirely) nor a socket, so every
572
570
  // fragment-POST download would fall to the shared "unknown" bucket,
573
571
  // turning the per-user 30/min backstop into one global bucket an
574
- // attacker can exhaust for everyone (#1307). Passing `clientIp`
572
+ // attacker can exhaust for everyone. Passing `clientIp`
575
573
  // directly as env — the same server-resolved, trustedProxyHops-
576
574
  // aware value the outer request already trusted — reaches
577
575
  // extractSocketAddress() without going through header/hop-count
@@ -602,7 +600,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
602
600
  "Unix timestamp of the last export storage-cleanup pass that completed. Alert on time() minus this value exceeding the cron interval plus a buffer; the backlog-age gauge alone stays at its last value when the cron stops.",
603
601
  });
604
602
 
605
- // S2.U3 Atom 3b — Worker fuer Async Export-Pipeline. Cron-getriggert.
603
+ // Worker for the asynchronous export pipeline, triggered by a cron job.
606
604
  const RUN_EXPORT_JOBS_REASON = "processes pending export jobs across every tenant";
607
605
  r.job({
608
606
  name: "run-export-jobs",
@@ -614,9 +612,9 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
614
612
  throw new Error("run-export-jobs: ctx.registry required (JobContext incomplete)");
615
613
  }
616
614
  const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
617
- // SYSTEM_USER_ID ist die framework-weite Konvention. Der job-
618
- // Discriminator wird via handlerName="user-data-rights:run-export-
619
- // jobs" im Secret-Read-Audit erfasst.
615
+ // SYSTEM_USER_ID is the framework-wide convention. The job discriminator is
616
+ // recorded in the secret-read audit through
617
+ // handlerName="user-data-rights:run-export-jobs".
620
618
  const exportUserId = SYSTEM_USER_ID;
621
619
  const exportDb =
622
620
  ctx.db.unsafeRaw() as import("@cosmicdrift/kumiko-framework/db").DbConnection; // @cast-boundary db-operator — jobs never run inside a DbTx
@@ -628,12 +626,13 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
628
626
  ? createMetricsHandle(ctx.meter, "user-data-rights")
629
627
  : createNoopMetricsHandle();
630
628
 
631
- // C6 — ohne eigene send*Email-Opts aber mit gemountetem mail-transport
632
- // versendet der Cron die Export-Notifications selbst (Default-Templates).
633
- // Der Resolver baut den per-Tenant-Transport aus configResolver — gleiche
634
- // Bruecke wie buildStorageProvider.
635
- // The cron runs across tenants: each mail needs a notify bound to the
636
- // recipient's tenant (template override, channel config).
629
+ // Without explicit send*Email options, a mounted mail transport sends the
630
+ // export notifications itself using the default templates. The resolver
631
+ // builds the per-tenant transport from configResolver, bridging it in
632
+ // the same way as buildStorageProvider.
633
+ // The cron runs across tenants, so each mail needs a notify function
634
+ // bound to the recipient's tenant for template overrides and channel
635
+ // configuration.
637
636
  const notifyFactory = ctx._notifyFactory;
638
637
  const exportNotifyFor =
639
638
  notifyFactory !== undefined && isGdprMailDeliveryAvailable(exportRegistry)
@@ -678,9 +677,9 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
678
677
  handlerName: "user-data-rights:run-export-jobs",
679
678
  }),
680
679
  now: T.Now.instant(),
681
- // App-Author-Callbacks haben Vorrang; sonst greift die mail-foundation-
682
- // Default oben. Beide optional: ohne mail-transport + ohne Callback
683
- // bleibt es bei Polling via export-status.query.
680
+ // App-author callbacks take precedence; otherwise the mail-foundation default
681
+ // is used. Both are optional: without a mail transport or callback,
682
+ // clients continue polling via export-status.query.
684
683
  ...(sendExportReadyEmail && { sendExportReadyEmail }),
685
684
  ...(sendExportFailedEmail && { sendExportFailedEmail }),
686
685
  ...(opts.appExportDownloadUrl !== undefined && {
@@ -694,11 +693,11 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
694
693
  },
695
694
  });
696
695
 
697
- // Autonomer Art.17-Forget-Cron. Spiegelt run-export-jobs: nach Ablauf der
698
- // Grace-Period laeuft runForgetCleanup unbeaufsichtigt (der manuelle
699
- // userDataRights.runForget-API bleibt fuer Operator-Runs). Ohne diesen
700
- // Cron bleibt jeder Loesch-Antrag fuer immer in DeletionRequested haengen
701
- // — Art.17 wuerde nie ausgefuehrt.
696
+ // Automatic Article 17 forget cron. After the grace period, it runs
697
+ // runForgetCleanup without supervision; the manual
698
+ // userDataRights.runForget API remains available for operator runs.
699
+ // Without this cron, deletion requests would remain in
700
+ // DeletionRequested indefinitely and Article 17 erasure would never run.
702
701
  const RUN_FORGET_CLEANUP_REASON = "executes overdue Art.17 forget requests across every tenant";
703
702
  r.job({
704
703
  name: "run-forget-cleanup",
@@ -779,7 +778,7 @@ export function createUserDataRightsFeature(opts: UserDataRightsOptions = {}): F
779
778
  actor: ctx.systemUser.id,
780
779
  });
781
780
 
782
- // Persist each incomplete report on the job-run log (#1572). The write
781
+ // Persist each incomplete report on the job-run log. The write
783
782
  // handler returns incomplete[] in its response; the cron path used to
784
783
  // discard the array (only a console.warn for rolledBack cases).
785
784
  // ctx.log feeds createJobRunLogger → store_job_run_logs.
@@ -8,17 +8,17 @@ import { updateUserLifecycle } from "../lib/update-user-lifecycle.ts";
8
8
  const APPEND_LIFECYCLE_EVENT_REASON =
9
9
  "appends the user lifecycle event on the SYSTEM_TENANT_ID user stream";
10
10
 
11
- // POST /api/user/cancel-deletion (S2.U5).
11
+ // POST /api/user/cancel-deletion.
12
12
  //
13
- // Innerhalb der Grace-Period kann User seinen Forget-Antrag zurueck-
14
- // nehmen. Setzt:
13
+ // During the grace period, the user can withdraw a pending deletion request.
14
+ // This restores:
15
15
  // - status = "active"
16
16
  // - gracePeriodEnd = null
17
17
  //
18
- // Nach Grace-Period: 422 (run-forget-cleanup hat in der Zwischenzeit
19
- // die Hooks schon getriggert — Reversal nicht moeglich).
18
+ // After the grace period, return 422 because cleanup may already have triggered
19
+ // irreversible hooks.
20
20
  //
21
- // Sonderfall: Cancel als "active"-User → 422 (kein pending Forget).
21
+ // Cancelling as an "active" user also returns 422 because no deletion is pending.
22
22
  export const cancelDeletionWrite = defineWriteHandler({
23
23
  name: "cancel-deletion",
24
24
  schema: z.object({}),
@@ -64,13 +64,13 @@ export const cancelDeletionWrite = defineWriteHandler({
64
64
  await updateUserLifecycle(ctx.db.unsafeRaw(), event.user.id, {
65
65
  status: USER_STATUS.Active,
66
66
  gracePeriodEnd: null,
67
- // #354/1: closes the replay-after-cancel window — a still-TTL-valid email
67
+ // Closes the replay-after-cancel window — a still-TTL-valid email
68
68
  // token verified against the nulled requestId can no longer arm a second grace period.
69
69
  pendingDeletionRequestId: null,
70
70
  });
71
71
 
72
- // gracePeriodEnd=null im Response symmetrisch zu request-deletion's
73
- // ISO-Timestamp — Frontend kann beide Endpoints uniform behandeln.
72
+ // gracePeriodEnd=null in the response mirrors request-deletion's
73
+ // ISO timestamp so the frontend can handle both endpoints uniformly.
74
74
  const gracePeriodEnd: string | null = null;
75
75
  return {
76
76
  isSuccess: true as const,
@@ -9,16 +9,16 @@ export type ConfirmDeletionByTokenOptions = {
9
9
  readonly deletionTokenSecret?: string;
10
10
  };
11
11
 
12
- // Generischer 422 für jeden Token-Fehlerpfad (malformed / bad_signature /
13
- // expired / kein Secret) — kein Signal ob ein Token zu einem User gehört.
12
+ // Use the same generic 422 for every token-error path (malformed / bad_signature /
13
+ // expired / missing secret) so callers cannot determine whether a token belongs to a user.
14
14
  function invalidToken(): UnprocessableError {
15
15
  return new UnprocessableError("invalid_or_expired_token");
16
16
  }
17
17
 
18
- // userId stammt aus dem noch-unverifizierten Token (Angreifer-Eingabe). Ein
19
- // fehlgeschlagener Lookup — z.B. eine typfremde id auf einer int/uuid-Spalte —
20
- // darf nicht als 500 durchschlagen; null behandelt der Caller wie "kein offener
21
- // Antrag" (generischer 422). Die HMAC-Prüfung bleibt der eigentliche Gate.
18
+ // userId comes from the not-yet-verified token (attacker-controlled input). A failed
19
+ // lookup—for example, a type-mismatched id on an int/uuid column—must not surface as a
20
+ // 500; null is treated by the caller as "no pending request" (generic 422). HMAC
21
+ // verification remains the actual gate.
22
22
  async function readPendingDeletionRequestId(
23
23
  ctx: HandlerContext,
24
24
  userId: string,
@@ -41,7 +41,7 @@ async function readPendingDeletionRequestId(
41
41
  // the actual grace-period transition, so a crash after the spend can no
42
42
  // longer lose the write step.
43
43
  //
44
- // Replay protection (#354/1): the row's requestId is part of the verify key.
44
+ // Replay protection: the row's requestId is part of the verify key.
45
45
  // We read it via the (unverified, lookup-only) userId from the token, reject
46
46
  // a missing entry, and verify the token against the CURRENT requestId. After
47
47
  // a cancel-deletion (status → Active, pendingDeletionRequestId → null), a
@@ -51,7 +51,7 @@ async function readPendingDeletionRequestId(
51
51
  // the same requestId and both verify the HMAC — commitDeletion spends the
52
52
  // anchor AND writes the transition atomically (expect: status===Active &&
53
53
  // pendingDeletionRequestId===requestId), so exactly one wins. The loser gets
54
- // the same generic 422 as an invalid token — no status leak (#354/2).
54
+ // the same generic 422 as an invalid token — no status leak.
55
55
  export function createConfirmDeletionByTokenHandler(opts: ConfirmDeletionByTokenOptions = {}) {
56
56
  return defineWriteHandler({
57
57
  name: "confirm-deletion-by-token",
@@ -1,26 +1,26 @@
1
- // GET /api/query → user-data-rights:query:download-by-job (S2.U3 Atom 4b).
1
+ // GET /api/query → user-data-rights:query:download-by-job
2
2
  //
3
- // **UI-Klick-Pfad** (session-auth): User pollt status, sieht "done",
4
- // klickt "Download" im UI mit jobId. Server checkt session.userId ==
5
- // job.userId — kein Token noetig (Session IS the auth).
3
+ // **UI download flow** (session-auth): The user polls the status, sees
4
+ // "done", and clicks "Download" with the jobId. The server checks
5
+ // `session.userId == job.userId`; no token is needed because the session
6
+ // provides authentication.
6
7
  //
7
- // **Cross-Tenant-Same-User:** Job ist tenant-agnostisch (1 Job pro
8
- // userId ueber alle Memberships). Alice triggert Export aus Tenant A,
9
- // loggt sich spaeter in Tenant B ein, klickt Download. Server akzeptiert
10
- // — `session.userId == job.userId` reicht, kein Tenant-Match-Check.
11
- // Plan-Decision (Atom 4b Plan, User-Choice).
8
+ // **Cross-tenant same user:** Jobs are tenant-agnostic (one job per userId
9
+ // across all memberships). If Alice starts an export in Tenant A, later
10
+ // signs in to Tenant B, and clicks Download, the server accepts it:
11
+ // `session.userId == job.userId` is sufficient; no tenant-match check applies.
12
12
  //
13
- // **Cross-User-Isolation:** Wenn session.userId != job.userId → 404
14
- // (NICHT 403, kein Existenz-Leak). Selber error wie "Job-ID nicht
15
- // gefunden".
13
+ // **Cross-user isolation:** If session.userId != job.userId, return 404
14
+ // (not 403) to avoid leaking whether the job exists. Use the same error as
15
+ // for an unknown job ID.
16
16
  //
17
- // Verify-Pipeline:
18
- // 1. fetchOne job by jobId
19
- // 2. job.userId === session.userId (cross-user-isolation)
20
- // 3. job.status === "done"
21
- // 4. job.downloadStorageKey != null
22
- // 5. tokenRow lookup (audit-row update only)
23
- // 6. Audit-Update: useCount + 1, IP, UA, lastUsedAt (best-effort)
17
+ // Verification pipeline:
18
+ // 1. Fetch the job by jobId
19
+ // 2. Check job.userId === session.userId (cross-user isolation)
20
+ // 3. Check job.status === "done"
21
+ // 4. Check job.downloadStorageKey != null
22
+ // 5. Look up tokenRow (audit-row update only)
23
+ // 6. Best-effort audit update: useCount + 1, IP, UA, lastUsedAt
24
24
  // 7. Return {url, expiresAt}
25
25
 
26
26
  import { requestContext } from "@cosmicdrift/kumiko-framework/api";
@@ -69,7 +69,7 @@ export const downloadByJobQuery = defineQueryHandler({
69
69
  "each signed-in user downloads only their own finished export job; the job " +
70
70
  "lookup checks jobRow.userId against the caller's own id and 404s otherwise",
71
71
  },
72
- }, // openToAll = auth-required, kein anonymous
72
+ }, // openToAll requires authentication; anonymous access is not allowed
73
73
  description:
74
74
  "Returns a short-lived signed download URL for the calling user's own finished data-export job named by job id, backing the download button in the privacy center once export-status reports the job done.",
75
75
  escapeHatch: {
@@ -82,9 +82,8 @@ export const downloadByJobQuery = defineQueryHandler({
82
82
  const userId = query.user.id;
83
83
  const jobId = query.payload.jobId;
84
84
  const tenantId = query.user.tenantId;
85
- // IP + UA aus dem request-scoped Kontext (von requestIdMiddleware
86
- // befuellt) — server-trusted, anders als ein vom Client mitgeschickter
87
- // Wert (603/2).
85
+ // IP and UA from the request-scoped context populated by
86
+ // requestIdMiddleware; these are server-trusted rather than client-supplied.
88
87
  const auditIp = requestContext.get()?.ip ?? null;
89
88
  const auditUa = requestContext.get()?.userAgent ?? null;
90
89
  const runner = ctx.db.unsafeRaw();
@@ -187,10 +186,10 @@ export const downloadByJobQuery = defineQueryHandler({
187
186
  now.epochMilliseconds + SIGNED_URL_TTL_SECONDS * 1000,
188
187
  );
189
188
 
190
- // Step 6: Audit-Update via tokenRow-lookup. UI-Pfad benutzt nicht
191
- // den plain-Token, aber wir wollen den useCount inkrementieren
192
- // damit die Audit-Felder konsistent sind (UI-clicks zaehlen auch
193
- // als Use). Lookup via jobId — UNIQUE-Index garantiert max 1 Row.
189
+ // Step 6: Look up tokenRow for the audit update. The UI flow has no plain
190
+ // token, but its useCount must still be incremented so audit fields remain
191
+ // consistent and UI clicks count as uses. The jobId lookup is safe because
192
+ // the UNIQUE index guarantees at most one row.
194
193
  const tokenRow = await fetchOne<TokenRow>(runner, exportDownloadTokensTable, {
195
194
  jobId,
196
195
  });
@@ -207,9 +206,9 @@ export const downloadByJobQuery = defineQueryHandler({
207
206
  userAgent: auditUa,
208
207
  });
209
208
  }
210
- // Wenn tokenRow fehlt (sollte nicht passieren wenn Atom 4a sauber
211
- // lief): Audit-Update skipped, Download laeuft weiter. Niemand wird
212
- // hier durch Audit-Failure blockiert.
209
+ // If tokenRow is missing (which should not happen when the preceding token
210
+ // creation flow completed), skip the audit update and continue the download;
211
+ // an audit failure must not block the user.
213
212
 
214
213
  return {
215
214
  url: signedUrl,