@cosmicdrift/kumiko-bundled-features 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 (470) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/agent-tools/tool-dispatch.js +0 -2
  4. package/dist/audit/screens.js +1 -1
  5. package/dist/auth-email-password/feature.js +1 -1
  6. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  7. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  8. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  9. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  10. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  11. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  12. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  13. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  14. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  15. package/dist/auth-email-password/handlers/login.write.js +1 -1
  16. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  17. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  18. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  19. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  20. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  21. package/dist/auth-email-password/index.js +5 -5
  22. package/dist/auth-email-password/lockout-store.js +1 -1
  23. package/dist/auth-email-password/seeding.d.ts +42 -45
  24. package/dist/auth-email-password/seeding.js +51 -53
  25. package/dist/auth-email-password/signup-token-store.js +8 -8
  26. package/dist/auth-email-password/testing.js +3 -3
  27. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  28. package/dist/auth-email-password/web/auth-client.js +36 -37
  29. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  30. package/dist/auth-email-password/web/auth-gate.js +15 -16
  31. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  32. package/dist/auth-email-password/web/client-plugin.js +4 -5
  33. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  34. package/dist/auth-email-password/web/constants.js +3 -3
  35. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  36. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  37. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  38. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  39. package/dist/auth-email-password/web/index.js +5 -5
  40. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  41. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  42. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  43. package/dist/auth-email-password/web/login-screen.js +2 -3
  44. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  45. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  46. package/dist/auth-email-password/web/session.d.ts +10 -9
  47. package/dist/auth-email-password/web/session.js +28 -29
  48. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  49. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  50. package/dist/auth-email-password/web/signup-screen.js +13 -13
  51. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  52. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  53. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  54. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  55. package/dist/auth-email-password/web/user-menu.js +12 -13
  56. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  57. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  58. package/dist/auth-foundation/boot-checks.js +4 -4
  59. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  60. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  61. package/dist/auth-foundation/types.js +2 -2
  62. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  63. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  64. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  65. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  66. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  67. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  68. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  69. package/dist/auth-mfa/token-secrets.js +1 -1
  70. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  71. package/dist/auth-mfa/web/client-plugin.js +1 -1
  72. package/dist/auth-mfa/web/i18n.js +3 -3
  73. package/dist/auth-mfa/web/index.js +4 -4
  74. package/dist/auth-mfa/web/mfa-client.js +17 -16
  75. package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
  76. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  77. package/dist/billing-foundation/aggregate-id.js +10 -11
  78. package/dist/billing-foundation/entities.js +27 -27
  79. package/dist/billing-foundation/events.js +18 -17
  80. package/dist/billing-foundation/feature.js +42 -43
  81. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  82. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  83. package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
  84. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  85. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  86. package/dist/billing-foundation/handlers/process-event.write.js +20 -20
  87. package/dist/billing-foundation/projection.d.ts +15 -11
  88. package/dist/billing-foundation/projection.js +38 -37
  89. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  90. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  91. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  92. package/dist/billing-foundation/types.d.ts +40 -41
  93. package/dist/billing-foundation/types.js +20 -20
  94. package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
  95. package/dist/cap-counter/aggregate-id.js +8 -9
  96. package/dist/cap-counter/constants.js +11 -12
  97. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  98. package/dist/cap-counter/enforce-cap.js +47 -48
  99. package/dist/cap-counter/entity.js +29 -29
  100. package/dist/cap-counter/feature.js +34 -35
  101. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  102. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  103. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  104. package/dist/cap-counter/stock-cap-guard.js +1 -1
  105. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  106. package/dist/channel-email/smtp-transport.d.ts +18 -17
  107. package/dist/channel-email/smtp-transport.js +24 -21
  108. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  109. package/dist/compliance-profiles/feature.js +4 -4
  110. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  111. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  112. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  113. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  114. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  115. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  116. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  117. package/dist/compliance-profiles/seeding.js +14 -15
  118. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  119. package/dist/compliance-profiles-ops/index.js +2 -2
  120. package/dist/config/handlers/readiness.query.d.ts +4 -4
  121. package/dist/config/handlers/readiness.query.js +1 -1
  122. package/dist/config/handlers/reencrypt.job.js +4 -5
  123. package/dist/config/handlers/set.write.js +4 -4
  124. package/dist/config/resolver.js +4 -4
  125. package/dist/config/table.js +10 -10
  126. package/dist/config/write-helpers.js +1 -1
  127. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  128. package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
  129. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  130. package/dist/custom-fields/aggregate-id.js +16 -17
  131. package/dist/custom-fields/entity.js +49 -47
  132. package/dist/custom-fields/events.js +7 -8
  133. package/dist/custom-fields/feature.d.ts +14 -14
  134. package/dist/custom-fields/feature.js +53 -54
  135. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  136. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  137. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  138. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  139. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  140. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  141. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  142. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  143. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  144. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  145. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  146. package/dist/custom-fields/lib/field-access.js +2 -2
  147. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  148. package/dist/custom-fields/lib/quota.js +1 -1
  149. package/dist/custom-fields/lib/value-schema.js +10 -12
  150. package/dist/custom-fields/run-retention.js +3 -3
  151. package/dist/custom-fields/schemas.js +14 -14
  152. package/dist/custom-fields/web/client-plugin.js +2 -5
  153. package/dist/custom-fields/web/constants.js +2 -2
  154. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  155. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  156. package/dist/custom-fields/wire-for-entity.js +65 -67
  157. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  158. package/dist/data-retention/_internal/parse-override.js +2 -3
  159. package/dist/data-retention/feature.js +11 -18
  160. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  161. package/dist/data-retention/keep-for.d.ts +7 -7
  162. package/dist/data-retention/keep-for.js +15 -15
  163. package/dist/data-retention/override-schema.d.ts +3 -4
  164. package/dist/data-retention/override-schema.js +13 -15
  165. package/dist/data-retention/presets.d.ts +4 -5
  166. package/dist/data-retention/presets.js +18 -23
  167. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  168. package/dist/data-retention/resolver.d.ts +12 -12
  169. package/dist/data-retention/resolver.js +24 -23
  170. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  171. package/dist/data-retention/run-retention-cleanup.js +61 -51
  172. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  173. package/dist/delivery/feature.js +2 -2
  174. package/dist/delivery/handlers/log.query.js +1 -1
  175. package/dist/delivery/tables.js +9 -8
  176. package/dist/delivery/unsubscribe.js +4 -4
  177. package/dist/document-ingest-foundation/entity.js +4 -4
  178. package/dist/document-ingest-foundation/events.js +2 -2
  179. package/dist/document-ingest-foundation/feature.js +2 -2
  180. package/dist/document-ingest-foundation/pages.js +1 -1
  181. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  182. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  183. package/dist/feature-toggles/feature.js +1 -1
  184. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  185. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  186. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  187. package/dist/feature-toggles/web/constants.js +1 -1
  188. package/dist/file-derivatives/feature.d.ts +1 -1
  189. package/dist/file-derivatives/feature.js +1 -1
  190. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  191. package/dist/file-derivatives/presets.js +1 -1
  192. package/dist/file-foundation/feature.js +6 -6
  193. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  194. package/dist/file-provider-inmemory/feature.js +16 -16
  195. package/dist/file-provider-s3/feature.js +16 -16
  196. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  197. package/dist/files/feature.js +6 -6
  198. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  199. package/dist/files-tenant-data/hooks.js +24 -26
  200. package/dist/files-tenant-data/index.js +1 -1
  201. package/dist/folders/feature.d.ts +1 -1
  202. package/dist/folders/web/folder-manager.js +2 -2
  203. package/dist/folders/web/tree.js +5 -5
  204. package/dist/form-draft/db/queries/cleanup.js +1 -1
  205. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  206. package/dist/form-draft/entity.js +3 -3
  207. package/dist/form-draft/feature.js +4 -5
  208. package/dist/form-draft/handlers/discard.write.js +1 -1
  209. package/dist/form-draft/release-file-refs.js +6 -6
  210. package/dist/form-draft/schemas.js +3 -3
  211. package/dist/form-draft/web/constants.js +0 -2
  212. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  213. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  214. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  215. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  216. package/dist/inbound-mail-foundation/constants.js +30 -33
  217. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  218. package/dist/inbound-mail-foundation/entities.js +47 -48
  219. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  220. package/dist/inbound-mail-foundation/events.js +50 -47
  221. package/dist/inbound-mail-foundation/feature.js +39 -39
  222. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  223. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  224. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  225. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  226. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  227. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  228. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  229. package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
  230. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  231. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  232. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  233. package/dist/inbound-mail-foundation/projection.js +31 -29
  234. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  235. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  236. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  237. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  238. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  239. package/dist/inbound-mail-foundation/types.d.ts +45 -46
  240. package/dist/inbound-mail-foundation/types.js +21 -21
  241. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  242. package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
  243. package/dist/inbound-provider-imap/credential-document.js +13 -13
  244. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  245. package/dist/inbound-provider-imap/feature.js +42 -40
  246. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  247. package/dist/inbound-provider-imap/imap-client.js +20 -19
  248. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  249. package/dist/inbound-provider-inmemory/feature.js +19 -19
  250. package/dist/jobs/db/queries/retention.js +2 -2
  251. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  252. package/dist/jobs/events.js +1 -1
  253. package/dist/jobs/feature.js +5 -6
  254. package/dist/jobs/handlers/detail.query.js +4 -4
  255. package/dist/jobs/handlers/list.query.js +1 -1
  256. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  257. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  258. package/dist/jobs/handlers/retry.write.js +1 -1
  259. package/dist/jobs/job-instant.js +1 -1
  260. package/dist/jobs/job-run-logger.js +10 -11
  261. package/dist/jobs/job-run-table.js +3 -3
  262. package/dist/jobs/screens.js +1 -1
  263. package/dist/jobs/tenant-job-failure-table.js +1 -1
  264. package/dist/jobs/tenant-job-run-table.js +1 -1
  265. package/dist/ledger/entity.js +5 -5
  266. package/dist/ledger/feature.js +3 -3
  267. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  268. package/dist/ledger/recurring.js +12 -12
  269. package/dist/ledger/schemas.js +1 -1
  270. package/dist/ledger/web/constants.js +2 -2
  271. package/dist/ledger/web/index.js +7 -7
  272. package/dist/legal-pages/feature.d.ts +4 -4
  273. package/dist/legal-pages/feature.js +25 -26
  274. package/dist/legal-pages/markdown.js +3 -3
  275. package/dist/legal-pages/web/client-plugin.js +23 -24
  276. package/dist/legal-pages/web/index.js +0 -1
  277. package/dist/mail-foundation/feature.d.ts +2 -2
  278. package/dist/mail-foundation/feature.js +24 -25
  279. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  280. package/dist/mail-transport-inmemory/feature.js +27 -28
  281. package/dist/mail-transport-smtp/feature.js +20 -20
  282. package/dist/managed-pages/branding.js +6 -6
  283. package/dist/managed-pages/feature.d.ts +26 -26
  284. package/dist/managed-pages/feature.js +34 -34
  285. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  286. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  287. package/dist/managed-pages/handlers/set.write.js +5 -7
  288. package/dist/managed-pages/screens/page-screens.js +11 -11
  289. package/dist/managed-pages/seeding.js +8 -8
  290. package/dist/managed-pages/table.js +13 -12
  291. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  292. package/dist/managed-pages/web/client-plugin.js +5 -5
  293. package/dist/managed-pages/web/i18n.js +1 -1
  294. package/dist/notes-history/entity.js +4 -4
  295. package/dist/notes-history/feature.d.ts +2 -2
  296. package/dist/notes-history-user-data/hooks.js +1 -1
  297. package/dist/page-render/layout.js +9 -9
  298. package/dist/page-render/markdown.js +11 -11
  299. package/dist/page-render/security-headers.js +7 -6
  300. package/dist/personal-access-tokens/feature.js +5 -5
  301. package/dist/personal-access-tokens/roles.js +2 -2
  302. package/dist/readiness/handlers/status.query.js +3 -3
  303. package/dist/renderer-foundation/api.js +12 -13
  304. package/dist/renderer-foundation/constants.js +2 -2
  305. package/dist/renderer-foundation/feature.js +7 -7
  306. package/dist/secrets/feature.js +9 -9
  307. package/dist/secrets/web/constants.js +2 -2
  308. package/dist/seo/feature.js +3 -3
  309. package/dist/sessions/constants.d.ts +1 -1
  310. package/dist/sessions/constants.js +1 -1
  311. package/dist/sessions/feature.js +8 -8
  312. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  313. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  314. package/dist/sessions/handlers/revoke.write.js +1 -1
  315. package/dist/sessions/schema/user-session.js +4 -4
  316. package/dist/sessions/screens.js +2 -2
  317. package/dist/sessions/session-callbacks.js +2 -2
  318. package/dist/sessions/session-revoked-event.js +2 -2
  319. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  320. package/dist/shared/decrypt-stored-pii.js +1 -1
  321. package/dist/shared/encrypt-for-direct-write.js +1 -1
  322. package/dist/shared/map-with-concurrency.js +5 -4
  323. package/dist/shared/parent-visibility.js +2 -2
  324. package/dist/shared/password-hashing.js +1 -1
  325. package/dist/shared/signup-handover.js +1 -2
  326. package/dist/shared/single-use-token-store.js +1 -1
  327. package/dist/subscription-mollie/constants.js +15 -17
  328. package/dist/subscription-mollie/feature.d.ts +17 -18
  329. package/dist/subscription-mollie/feature.js +24 -24
  330. package/dist/subscription-mollie/index.js +3 -3
  331. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  332. package/dist/subscription-mollie/plugin-methods.js +15 -14
  333. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  334. package/dist/subscription-mollie/verify-webhook.js +27 -27
  335. package/dist/subscription-stripe/constants.js +4 -6
  336. package/dist/subscription-stripe/feature.d.ts +14 -14
  337. package/dist/subscription-stripe/feature.js +35 -34
  338. package/dist/subscription-stripe/index.js +6 -6
  339. package/dist/subscription-stripe/plugin-methods.js +18 -18
  340. package/dist/subscription-stripe/runtime.d.ts +1 -1
  341. package/dist/subscription-stripe/runtime.js +1 -1
  342. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  343. package/dist/subscription-stripe/verify-webhook.js +59 -61
  344. package/dist/tags/feature.d.ts +3 -3
  345. package/dist/tags/screens.js +1 -1
  346. package/dist/template-resolver/api.js +10 -10
  347. package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
  348. package/dist/template-resolver/handlers/list.query.js +1 -1
  349. package/dist/template-resolver/handlers/shared.js +2 -2
  350. package/dist/template-resolver/handlers/template-write.js +3 -3
  351. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  352. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  353. package/dist/template-resolver/seeding.js +4 -4
  354. package/dist/template-resolver/table.js +10 -11
  355. package/dist/template-resolver/web/client-plugin.js +2 -2
  356. package/dist/tenant/feature.js +7 -7
  357. package/dist/tenant/handlers/member-directory.query.js +1 -1
  358. package/dist/tenant/handlers/members.query.js +1 -1
  359. package/dist/tenant/handlers/team-list.query.js +1 -1
  360. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  361. package/dist/tenant/invitation-table.js +37 -40
  362. package/dist/tenant/membership-table.js +3 -3
  363. package/dist/tenant/schema/tenant.js +7 -9
  364. package/dist/tenant/screens.js +1 -1
  365. package/dist/tenant/seeding.d.ts +6 -5
  366. package/dist/tenant/seeding.js +12 -12
  367. package/dist/tenant/testing.js +5 -6
  368. package/dist/tenant/web/constants.js +2 -2
  369. package/dist/tenant-handover/events.js +5 -7
  370. package/dist/tenant-handover/feature.js +1 -1
  371. package/dist/tenant-handover/grant.js +1 -1
  372. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  373. package/dist/tenant-handover/move-entity-graph.js +8 -9
  374. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  375. package/dist/tenant-handover/transfer-graph.js +4 -5
  376. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  377. package/dist/tenant-lifecycle/feature.js +1 -1
  378. package/dist/tenant-settings/constants.js +1 -1
  379. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  380. package/dist/tenant-settings/tenant-defaults.js +9 -2
  381. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  382. package/dist/tier-engine/aggregate-id.js +15 -16
  383. package/dist/tier-engine/compose-app.d.ts +14 -14
  384. package/dist/tier-engine/compose-app.js +1 -1
  385. package/dist/tier-engine/entity.js +18 -19
  386. package/dist/tier-engine/feature.d.ts +19 -17
  387. package/dist/tier-engine/feature.js +68 -69
  388. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  389. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  390. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
  391. package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
  392. package/dist/tier-engine/tier-resolver.js +2 -2
  393. package/dist/tier-engine/trial.js +8 -8
  394. package/dist/tier-engine/web/index.js +4 -4
  395. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  396. package/dist/user/handlers/create.write.js +4 -4
  397. package/dist/user/schema/user.d.ts +11 -11
  398. package/dist/user/schema/user.js +45 -44
  399. package/dist/user/seeding.d.ts +15 -15
  400. package/dist/user/seeding.js +28 -28
  401. package/dist/user/testing.js +3 -3
  402. package/dist/user-data-rights/audit-download.d.ts +8 -8
  403. package/dist/user-data-rights/audit-download.js +19 -20
  404. package/dist/user-data-rights/boot-checks.js +1 -1
  405. package/dist/user-data-rights/deletion-token.js +1 -1
  406. package/dist/user-data-rights/feature.d.ts +49 -50
  407. package/dist/user-data-rights/feature.js +54 -53
  408. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  409. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  410. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  411. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  412. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  413. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  414. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  415. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  416. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  417. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  418. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  419. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  420. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  421. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  422. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  423. package/dist/user-data-rights/index.js +8 -10
  424. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  425. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  426. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  427. package/dist/user-data-rights/run-export-jobs.js +127 -233
  428. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  429. package/dist/user-data-rights/run-forget-cleanup.js +63 -82
  430. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  431. package/dist/user-data-rights/run-user-export.js +55 -57
  432. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  433. package/dist/user-data-rights/schema/download-token.js +37 -41
  434. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  435. package/dist/user-data-rights/schema/export-job.js +65 -67
  436. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  437. package/dist/user-data-rights/token-helpers.js +21 -25
  438. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  439. package/dist/user-data-rights/web/client-plugin.js +1 -1
  440. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  441. package/dist/user-data-rights/web/constants.js +1 -1
  442. package/dist/user-data-rights/web/index.js +5 -5
  443. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  444. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  445. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  446. package/dist/user-data-rights/zip-path.d.ts +15 -15
  447. package/dist/user-data-rights/zip-path.js +41 -40
  448. package/dist/user-data-rights-defaults/feature.js +15 -15
  449. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  450. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  451. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  452. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  453. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  454. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  455. package/dist/user-profile/handlers/change-email.write.js +13 -13
  456. package/dist/user-profile/index.js +3 -3
  457. package/dist/user-profile/web/client-plugin.js +1 -1
  458. package/dist/user-profile/web/constants.js +1 -1
  459. package/dist/user-profile/web/profile-screen.js +1 -1
  460. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  461. package/dist/workflow-runner/aggregate-id.js +1 -1
  462. package/dist/workflow-runner/event-subscriber.js +4 -5
  463. package/dist/workflow-runner/event-trigger.js +4 -17
  464. package/dist/workflow-runner/feature.js +2 -2
  465. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  466. package/dist/workflow-runner/pending-projection.js +6 -7
  467. package/dist/workflow-runner/runner.js +6 -6
  468. package/dist/workflow-runner/tables.js +6 -6
  469. package/dist/workflow-runner/workflow-registry.js +1 -1
  470. package/package.json +10 -10
@@ -5,75 +5,74 @@ import { type GdprMailDefaults } from "./lib/default-mailers.ts";
5
5
  import { type SendExportFailedEmailFn, type SendExportReadyEmailFn } from "./run-export-jobs.ts";
6
6
  import { type SendDeletionExecutedEmailFn } from "./run-forget-cleanup.ts";
7
7
  /**
8
- * Options fuer createUserDataRightsFeature. Notification-Callbacks
9
- * (Atom 5) folgen dem password-reset-Pattern aus auth-routes.ts.
8
+ * Options for createUserDataRightsFeature. Notification callbacks follow
9
+ * the password-reset pattern in auth-routes.ts.
10
10
  *
11
- * Plain-Token landet NIE in DB/event-store/jobRunsTable — Worker reicht
12
- * ihn ephemeral via Callback-arg an die App-Author-Implementation
13
- * (typisch: `delivery.notify(...)` mit `r.notification`-Templates,
14
- * `mailFoundation.send` direkt, oder Custom Resend/SES).
11
+ * The plain token is never stored in the DB, event store, or jobRunsTable.
12
+ * The worker passes it ephemerally as a callback argument to the app-author
13
+ * implementation (typically `delivery.notify(...)` with `r.notification`
14
+ * templates, `mailFoundation.send` directly, or custom Resend/SES).
15
15
  *
16
- * Worker-Run-Tracking + Retry kommt automatisch via existing
17
- * `jobs`-Feature (siehe CLAUDE.md "Bundled-Features by Concern").
16
+ * Worker-run tracking and retries are provided automatically by the existing
17
+ * `jobs` feature.
18
18
  */
19
19
  export type UserDataRightsOptions = {
20
- /** Email-Notification beim Export-done. App-Author wired das an seinen
21
- * Email-Provider. Best-effort (Atom 5.fix3): send-Throw fuer Job A
22
- * killt den Batch nicht — restliche pending-Jobs werden weiter
23
- * verarbeitet, Failure wird via console.warn sichtbar. (Vorher
24
- * bubbelte der Throw zum r.job-Wrap, was bei mehreren pending Jobs
25
- * zum silent-miss fuehrte: Job A done committed, B/C/D nie
26
- * verarbeitet, retry findet niemand.) */
20
+ /** Email notification when the export completes. The app author connects it
21
+ * to an email provider. Best effort: a send failure for Job A does not stop
22
+ * the batch; remaining pending jobs continue, and the failure is exposed via
23
+ * console.warn. Previously, the error reached the r.job wrapper, so with
24
+ * multiple pending jobs A could commit while B/C/D were never processed and
25
+ * no retry could find them. */
27
26
  readonly sendExportReadyEmail?: SendExportReadyEmailFn;
28
27
  /** Email-Notification beim Export-failed. Best-effort analog
29
28
  * sendExportReadyEmail. */
30
29
  readonly sendExportFailedEmail?: SendExportFailedEmailFn;
31
- /** Base-URL fuer den Magic-Link, z.B.
32
- * "https://app.example.com/user-export/by-token". Worker bauen
33
- * a URL fragment (`#token=<plain>`, issue #1271). Required wenn
34
- * sendExportReadyEmail gesetzt. Per-Tenant via reverse-proxy host
35
- * routing — nicht via per-Tenant-config-key (App-Author-Decision). */
30
+ /** Base URL for the magic link, e.g.
31
+ * "https://app.example.com/user-export/by-token". The worker builds
32
+ * a URL fragment (`#token=<plain>`). Required when
33
+ * sendExportReadyEmail is set. Routing uses the reverse-proxy host per
34
+ * tenant rather than a per-tenant config key. */
36
35
  readonly appExportDownloadUrl?: string;
37
- /** Atom 5b — Email-Notification beim deletion-requested-flip
38
- * ("Account-Loeschung in 30 Tagen"). Best-effort: send-failure killt
39
- * den Status-Flip nicht (siehe handlers/request-deletion.write.ts). */
36
+ /** Email notification when deletion is requested ("account deletion in
37
+ * 30 days"). Best effort: a send failure does not abort the status flip
38
+ * (see handlers/request-deletion.write.ts). */
40
39
  readonly sendDeletionRequestedEmail?: SendDeletionRequestedEmailFn;
41
- /** Atom 5b — Email-Notification beim Cleanup-Runner-done-Pfad
42
- * ("Account wurde geloescht"). Best-effort. Der Versand passiert NACH
43
- * dem User-Hook-Anonymisieren, deshalb cached der Worker
44
- * userEmail+tenantIds PRE-tx und reicht sie ephemeral an die
45
- * Callback-Implementation (siehe run-forget-cleanup.ts). */
40
+ /** Email notification after the cleanup runner completes ("account deleted").
41
+ * Best effort. Delivery occurs after the user hook anonymizes the user, so
42
+ * the worker caches userEmail+tenantIds before the transaction and passes
43
+ * them ephemerally to the callback implementation (see
44
+ * run-forget-cleanup.ts). */
46
45
  readonly sendDeletionExecutedEmail?: SendDeletionExecutedEmailFn;
47
- /** Anonymer, email-verifizierter Apex-Deletion-Flow (Lockout-sicher).
48
- * HMAC-Secret zum Signieren des Verify-Tokens. Ohne Secret bleibt der
49
- * Flow deaktiviert (request-by-email antwortet still success, confirm-
50
- * by-token weist generisch ab). */
46
+ /** Anonymous, email-verified apex deletion flow that is safe against lockout.
47
+ * HMAC secret for signing the verification token. Without a secret, the
48
+ * flow remains disabled: request-by-email returns success silently, while
49
+ * confirm-by-token rejects generically. */
51
50
  readonly deletionTokenSecret?: string;
52
- /** Basis-URL des Apex-Confirm-Screens, z.B.
53
- * "https://app.example.com/delete-account/confirm". Der Handler hängt das
54
- * Token als URL-Fragment an (`#token=<token>`, fw#1554). Required wenn
55
- * deletionTokenSecret gesetzt. */
51
+ /** Base URL of the apex confirmation screen, e.g.
52
+ * "https://app.example.com/delete-account/confirm". The handler appends
53
+ * the token as a URL fragment (`#token=<token>`). Required when
54
+ * deletionTokenSecret is set. */
56
55
  readonly deletionVerifyUrl?: string;
57
- /** Versand des Verify-Magic-Links (Schritt 1 des anonymen Flows).
58
- * Best-effort, app-author-wired. MUSS non-blocking sein (enqueue, z.B.
59
- * delivery.notify) — ein synchroner Send reintroduziert ein Timing-Oracle
60
- * für Account-Enumeration (siehe SendDeletionVerificationEmailFn-Doc).
61
- * Bewusst KEINE mail-foundation-Default: ein synchroner Default-Send
62
- * brächte genau dieses Enumeration-Oracle zurück, deshalb app-wired. */
56
+ /** Sends the verification magic link (step 1 of the anonymous flow).
57
+ * Best effort and wired by the app author. It MUST be non-blocking (enqueue,
58
+ * e.g. via delivery.notify): a synchronous send would reintroduce a timing
59
+ * oracle for account enumeration (see SendDeletionVerificationEmailFn-doc).
60
+ * There is deliberately no mail-foundation default because a synchronous
61
+ * default send would restore that enumeration oracle. */
63
62
  readonly sendDeletionVerificationEmail?: SendDeletionVerificationEmailFn;
64
- /** C6 — Zero-Callback-GDPR-Mails: ist mail-foundation + ein mail-transport-*
65
- * gemountet, versendet user-data-rights die Export-/Loesch-Notifications
66
- * selbst (Export-ready/-failed, Deletion-requested/-executed) ueber die
67
- * Default-Templates (email-templates.ts) — die App schreibt keinen Callback.
68
- * `mailDefaults` brandet diese Default-Mails (Locale + App-Name). Greift NUR
69
- * wenn der jeweilige send*Email-Opt NICHT gesetzt ist; Export-ready braucht
70
- * zusaetzlich appExportDownloadUrl. */
63
+ /** Zero-callback GDPR mail: when mail-foundation and a mail-transport-* are
64
+ * mounted, user-data-rights sends export and deletion notifications itself
65
+ * (export-ready/-failed, deletion-requested/-executed) using the default
66
+ * templates (email-templates.ts), without an app callback.
67
+ * `mailDefaults` brands these default messages (locale and app name). It
68
+ * applies only when the relevant send*Email option is unset; export-ready
69
+ * also requires appExportDownloadUrl. */
71
70
  readonly mailDefaults?: GdprMailDefaults;
72
71
  /** Hides the Art. 17 deletion section + its request-deletion/cancel-deletion
73
72
  * actions on the privacy-center screen — for apps that already offer
74
73
  * account deletion elsewhere (e.g. a profile danger-zone), against
75
74
  * duplication. Default `true` (deletion section shown).
76
- * BREAKING (fw#2312): replaces the removed client-side
75
+ * BREAKING: replaces the removed client-side
77
76
  * `userDataRightsClient({ privacyCenter: { showDeletion } })` option —
78
77
  * the screen is now declared once, server-side (`type: "projectionDetail"`),
79
78
  * so per-app visibility can only be a boot-time option, not a client-side
@@ -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 { createSystemConfig, createSystemUser, defineFeature, EXT_USER_DATA, i18nKey, SYSTEM_USER_ID, } from "@cosmicdrift/kumiko-framework/engine";
4
4
  import { createFallbackLogger } from "@cosmicdrift/kumiko-framework/logging";
@@ -61,16 +61,16 @@ export function createUserDataRightsFeature(opts = {}) {
61
61
  r.envSchema(deletionTokenSecretEnvSchema);
62
62
  r.usesApi("compliance.forTenant");
63
63
  r.usesApi("retention.policyFor");
64
- // S2.U6 — restrict-account ruft sessions.revokeAllForUser cross-feature.
65
- // r.usesApi sorgt fuer Boot-Validation: App ohne sessions-feature wirft
66
- // beim Boot, statt erst beim ersten Restrict-Call ein opaque "handler
67
- // not found" zu werfen.
64
+ // restrict-account calls sessions.revokeAllForUser across features.
65
+ // r.usesApi enables boot validation: without the sessions feature, the app
66
+ // fails at boot instead of raising an opaque "handler not found" error
67
+ // on the first restrict call.
68
68
  r.usesApi("sessions.revokeAllForUser");
69
- // file-foundation ist soft-dep: nur der Export-Worker (Atom 3b)
70
- // braucht ihn fuer Storage-Schreiben. Apps die nur Forget nutzen
71
- // (kein Export) muessen file-foundation nicht mounten.
69
+ // file-foundation is a soft dependency: only the export worker needs it
70
+ // for storage writes. Apps that use only forget (not export) do not need
71
+ // to mount file-foundation.
72
72
  r.extendsRegistrar(EXT_USER_DATA, {});
73
- // GDPR-storage guards V2+V3 (#1314) — moved off the framework-internal
73
+ // GDPR-storage guards V2+V3 — moved off the framework-internal
74
74
  // boot-validator onto this feature's own r.bootCheck(), since it's the
75
75
  // EXT_USER_DATA channel owner: any r.useExtension(EXT_USER_DATA, ...)
76
76
  // usage already requires user-data-rights to be mounted.
@@ -93,20 +93,20 @@ export function createUserDataRightsFeature(opts = {}) {
93
93
  options: ["single-user", "multi-user"],
94
94
  env: "TENANT_MODEL",
95
95
  }));
96
- // S2.U3 Atom 1b — ExportJob-Lifecycle-Entity.
96
+ // ExportJob-Lifecycle-Entity.
97
97
  r.entity({ name: "export-job", ...exportJobEntity });
98
- // S2.U3 Atom 4a — Download-Token-Entity. Worker generiert Token beim
99
- // Flip auf done (siehe run-export-jobs.ts). Hash in DB, plain im
100
- // RunExportJobsResult fuer Atom 5 (Notification per Email).
98
+ // The worker generates the token when flipping the job to done (see
99
+ // run-export-jobs.ts). The hash is stored in the database, while the plain
100
+ // token is kept in RunExportJobsResult for email notification.
101
101
  r.entity({ name: "export-download-token", ...exportDownloadTokenEntity });
102
- // S2.U7 — Audit-Trail invalid Download-Attempts (DPO Brute-Force-Detection).
102
+ // Audit-Trail invalid Download-Attempts (DPO Brute-Force-Detection).
103
103
  r.entity({ name: "download-attempt", ...downloadAttemptEntity });
104
- // S2.U6 — DSGVO Art. 18 Account-Freeze (Verarbeitungs-Pause).
105
- // Endpoints fuer Restrict + Lift. Login-Block fuer Restricted Users
106
- // lebt in auth-email-password/login.write.ts.
104
+ // GDPR Article 18 account freeze (pause processing).
105
+ // The endpoints restrict and lift the restriction. The login block for
106
+ // restricted users lives in auth-email-password/login.write.ts.
107
107
  r.writeHandler(restrictAccountWrite);
108
108
  r.writeHandler(liftRestrictionWrite);
109
- // S2.U5a — Endpoints fuer DSGVO Art. 17 Forget-Pfad mit Grace.
109
+ // Endpoints for the GDPR Article 17 forget path with a grace period.
110
110
  r.writeHandler(createRequestDeletionHandler({
111
111
  ...(opts.sendDeletionRequestedEmail && {
112
112
  sendDeletionRequestedEmail: opts.sendDeletionRequestedEmail,
@@ -129,26 +129,26 @@ export function createUserDataRightsFeature(opts = {}) {
129
129
  r.writeHandler(createConfirmDeletionByTokenHandler(opts.deletionTokenSecret !== undefined
130
130
  ? { deletionTokenSecret: opts.deletionTokenSecret }
131
131
  : {}));
132
- // S2.U5b — Cleanup-Runner als privileged-Handler. Atom 5b: Wenn
133
- // sendDeletionExecutedEmail gesetzt, reicht der Handler den Callback
134
- // an runForgetCleanup weiter (Worker cached userEmail+tenantIds
135
- // PRE-tx, siehe run-forget-cleanup.ts).
132
+ // Cleanup runner as a privileged handler. When
133
+ // sendDeletionExecutedEmail is set, the handler passes the callback to
134
+ // runForgetCleanup; the worker caches userEmail+tenantIds before the
135
+ // transaction (see run-forget-cleanup.ts).
136
136
  r.writeHandler(createRunForgetCleanupHandler(opts.sendDeletionExecutedEmail
137
137
  ? { sendDeletionExecutedEmail: opts.sendDeletionExecutedEmail }
138
138
  : {}));
139
139
  r.exposesApi("userDataRights.runForget");
140
- // S2.U3 Atom 2 — User-Touchpoints fuer Async Export-Pipeline.
140
+ // User touchpoints for the asynchronous export pipeline.
141
141
  r.writeHandler(requestExportWrite);
142
142
  r.queryHandler(exportStatusQuery);
143
143
  r.exposesApi("userDataRights.runExport");
144
- // S2.U3 Atom 4b — Download-Endpoints (Token-Pfad + Session-Pfad).
145
- // Beide query-handlers verifizieren Token/Session, holen signed-URL
146
- // vom Storage-Provider, und persistieren Audit-Felder am Token-Row.
147
- // r.httpRoute-Wrapper unten machen den 302-Redirect zu signedUrl.
144
+ // Download endpoints for token and session paths.
145
+ // Both query handlers verify the token or session, obtain a signed URL
146
+ // from the storage provider, and persist audit fields on the token row.
147
+ // The r.httpRoute wrappers below issue the 302 redirect to signedUrl.
148
148
  r.queryHandler(downloadByTokenQuery);
149
149
  r.queryHandler(downloadByJobQuery);
150
- // S2.U7 — User-Selbstauskunft (Art. 15) + Operator-Sicht auf
151
- // invalid Download-Attempts (DPO).
150
+ // User self-access under Article 15 and operator access to invalid download
151
+ // attempts (DPO).
152
152
  r.queryHandler(myAuditLogQuery);
153
153
  r.queryHandler(listDownloadAttemptsQuery);
154
154
  // Read-only GDPR operator inspector (SystemAdmin) — screens stay inert until an app navs them.
@@ -306,12 +306,12 @@ export function createUserDataRightsFeature(opts = {}) {
306
306
  // Magic-link path (anonymous): the email link carries the token as a
307
307
  // URL fragment (`#token=<plain>`) instead of a query param — fragments
308
308
  // never leave the browser, so they never hit proxy/access logs
309
- // (issue #1271). This route only serves the interstitial page; the
309
+ // This route only serves the interstitial page; the
310
310
  // external script reads the fragment client-side and exchanges the
311
311
  // token via POST for the signed URL.
312
312
  //
313
- // No `?token=` query fallback: framework is zero-legacy (#1512) — no
314
- // live customer data / no pre-#1271 emails in flight that would need
313
+ // No `?token=` query fallback: framework is zero-legacy — no
314
+ // live customer data / no emails in flight that would need
315
315
  // bridging, so there's nothing a fallback would need to cover. A query
316
316
  // param reaches the server as part of the request URL and gets written
317
317
  // to proxy/access logs regardless of what the handler does with it
@@ -353,7 +353,7 @@ export function createUserDataRightsFeature(opts = {}) {
353
353
  },
354
354
  });
355
355
  // Exchange endpoint for the interstitial page: the token arrives here
356
- // as a POST body instead of a query string (issue #1271). A dedicated
356
+ // as a POST body instead of a query string. A dedicated
357
357
  // route rather than letting the browser JS call /api/query directly,
358
358
  // for two reasons:
359
359
  // 1. IP/UA audit — extractAuditMeta needs the raw request headers and
@@ -391,7 +391,7 @@ export function createUserDataRightsFeature(opts = {}) {
391
391
  // defaults to 0, ignoring headers entirely) nor a socket, so every
392
392
  // fragment-POST download would fall to the shared "unknown" bucket,
393
393
  // turning the per-user 30/min backstop into one global bucket an
394
- // attacker can exhaust for everyone (#1307). Passing `clientIp`
394
+ // attacker can exhaust for everyone. Passing `clientIp`
395
395
  // directly as env — the same server-resolved, trustedProxyHops-
396
396
  // aware value the outer request already trusted — reaches
397
397
  // extractSocketAddress() without going through header/hop-count
@@ -417,7 +417,7 @@ export function createUserDataRightsFeature(opts = {}) {
417
417
  unit: "seconds",
418
418
  description: "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.",
419
419
  });
420
- // S2.U3 Atom 3b — Worker fuer Async Export-Pipeline. Cron-getriggert.
420
+ // Worker for the asynchronous export pipeline, triggered by a cron job.
421
421
  const RUN_EXPORT_JOBS_REASON = "processes pending export jobs across every tenant";
422
422
  r.job({
423
423
  name: "run-export-jobs",
@@ -429,9 +429,9 @@ export function createUserDataRightsFeature(opts = {}) {
429
429
  throw new Error("run-export-jobs: ctx.registry required (JobContext incomplete)");
430
430
  }
431
431
  const T = (await import("@cosmicdrift/kumiko-framework/time")).getTemporal();
432
- // SYSTEM_USER_ID ist die framework-weite Konvention. Der job-
433
- // Discriminator wird via handlerName="user-data-rights:run-export-
434
- // jobs" im Secret-Read-Audit erfasst.
432
+ // SYSTEM_USER_ID is the framework-wide convention. The job discriminator is
433
+ // recorded in the secret-read audit through
434
+ // handlerName="user-data-rights:run-export-jobs".
435
435
  const exportUserId = SYSTEM_USER_ID;
436
436
  const exportDb = ctx.db.unsafeRaw(); // @cast-boundary db-operator — jobs never run inside a DbTx
437
437
  const exportRegistry = ctx.registry;
@@ -441,12 +441,13 @@ export function createUserDataRightsFeature(opts = {}) {
441
441
  const exportMetrics = ctx.meter
442
442
  ? createMetricsHandle(ctx.meter, "user-data-rights")
443
443
  : createNoopMetricsHandle();
444
- // C6 — ohne eigene send*Email-Opts aber mit gemountetem mail-transport
445
- // versendet der Cron die Export-Notifications selbst (Default-Templates).
446
- // Der Resolver baut den per-Tenant-Transport aus configResolver — gleiche
447
- // Bruecke wie buildStorageProvider.
448
- // The cron runs across tenants: each mail needs a notify bound to the
449
- // recipient's tenant (template override, channel config).
444
+ // Without explicit send*Email options, a mounted mail transport sends the
445
+ // export notifications itself using the default templates. The resolver
446
+ // builds the per-tenant transport from configResolver, bridging it in
447
+ // the same way as buildStorageProvider.
448
+ // The cron runs across tenants, so each mail needs a notify function
449
+ // bound to the recipient's tenant for template overrides and channel
450
+ // configuration.
450
451
  const notifyFactory = ctx._notifyFactory;
451
452
  const exportNotifyFor = notifyFactory !== undefined && isGdprMailDeliveryAvailable(exportRegistry)
452
453
  ? (tenantId) => notifyFactory(createSystemUser(tenantId), tenantId)
@@ -483,9 +484,9 @@ export function createUserDataRightsFeature(opts = {}) {
483
484
  handlerName: "user-data-rights:run-export-jobs",
484
485
  }),
485
486
  now: T.Now.instant(),
486
- // App-Author-Callbacks haben Vorrang; sonst greift die mail-foundation-
487
- // Default oben. Beide optional: ohne mail-transport + ohne Callback
488
- // bleibt es bei Polling via export-status.query.
487
+ // App-author callbacks take precedence; otherwise the mail-foundation default
488
+ // is used. Both are optional: without a mail transport or callback,
489
+ // clients continue polling via export-status.query.
489
490
  ...(sendExportReadyEmail && { sendExportReadyEmail }),
490
491
  ...(sendExportFailedEmail && { sendExportFailedEmail }),
491
492
  ...(opts.appExportDownloadUrl !== undefined && {
@@ -498,11 +499,11 @@ export function createUserDataRightsFeature(opts = {}) {
498
499
  });
499
500
  },
500
501
  });
501
- // Autonomer Art.17-Forget-Cron. Spiegelt run-export-jobs: nach Ablauf der
502
- // Grace-Period laeuft runForgetCleanup unbeaufsichtigt (der manuelle
503
- // userDataRights.runForget-API bleibt fuer Operator-Runs). Ohne diesen
504
- // Cron bleibt jeder Loesch-Antrag fuer immer in DeletionRequested haengen
505
- // — Art.17 wuerde nie ausgefuehrt.
502
+ // Automatic Article 17 forget cron. After the grace period, it runs
503
+ // runForgetCleanup without supervision; the manual
504
+ // userDataRights.runForget API remains available for operator runs.
505
+ // Without this cron, deletion requests would remain in
506
+ // DeletionRequested indefinitely and Article 17 erasure would never run.
506
507
  const RUN_FORGET_CLEANUP_REASON = "executes overdue Art.17 forget requests across every tenant";
507
508
  r.job({
508
509
  name: "run-forget-cleanup",
@@ -568,7 +569,7 @@ export function createUserDataRightsFeature(opts = {}) {
568
569
  escapeHatchAuditLog: ctx.log,
569
570
  actor: ctx.systemUser.id,
570
571
  });
571
- // Persist each incomplete report on the job-run log (#1572). The write
572
+ // Persist each incomplete report on the job-run log. The write
572
573
  // handler returns incomplete[] in its response; the cron path used to
573
574
  // discard the array (only a console.warn for rolledBack cases).
574
575
  // ctx.log feeds createJobRunLogger → store_job_run_logs.
@@ -5,17 +5,17 @@ import { isWithinGracePeriod } from "../../shared/index.js";
5
5
  import { USER_STATUS, userTable } from "../../user/index.js";
6
6
  import { updateUserLifecycle } from "../lib/update-user-lifecycle.js";
7
7
  const APPEND_LIFECYCLE_EVENT_REASON = "appends the user lifecycle event on the SYSTEM_TENANT_ID user stream";
8
- // POST /api/user/cancel-deletion (S2.U5).
8
+ // POST /api/user/cancel-deletion.
9
9
  //
10
- // Innerhalb der Grace-Period kann User seinen Forget-Antrag zurueck-
11
- // nehmen. Setzt:
10
+ // During the grace period, the user can withdraw a pending deletion request.
11
+ // This restores:
12
12
  // - status = "active"
13
13
  // - gracePeriodEnd = null
14
14
  //
15
- // Nach Grace-Period: 422 (run-forget-cleanup hat in der Zwischenzeit
16
- // die Hooks schon getriggert — Reversal nicht moeglich).
15
+ // After the grace period, return 422 because cleanup may already have triggered
16
+ // irreversible hooks.
17
17
  //
18
- // Sonderfall: Cancel als "active"-User → 422 (kein pending Forget).
18
+ // Cancelling as an "active" user also returns 422 because no deletion is pending.
19
19
  export const cancelDeletionWrite = defineWriteHandler({
20
20
  name: "cancel-deletion",
21
21
  schema: z.object({}),
@@ -48,12 +48,12 @@ export const cancelDeletionWrite = defineWriteHandler({
48
48
  await updateUserLifecycle(ctx.db.unsafeRaw(), event.user.id, {
49
49
  status: USER_STATUS.Active,
50
50
  gracePeriodEnd: null,
51
- // #354/1: closes the replay-after-cancel window — a still-TTL-valid email
51
+ // Closes the replay-after-cancel window — a still-TTL-valid email
52
52
  // token verified against the nulled requestId can no longer arm a second grace period.
53
53
  pendingDeletionRequestId: null,
54
54
  });
55
- // gracePeriodEnd=null im Response symmetrisch zu request-deletion's
56
- // ISO-Timestamp — Frontend kann beide Endpoints uniform behandeln.
55
+ // gracePeriodEnd=null in the response mirrors request-deletion's
56
+ // ISO timestamp so the frontend can handle both endpoints uniformly.
57
57
  const gracePeriodEnd = null;
58
58
  return {
59
59
  isSuccess: true,
@@ -4,15 +4,15 @@ import * as z from "zod";
4
4
  import { USER_STATUS, userTable } from "../../user/index.js";
5
5
  import { redeemDeletionToken } from "../deletion-token.js";
6
6
  import { resolveGracePeriod, startDeletionGracePeriod } from "./deletion-grace-period.js";
7
- // Generischer 422 für jeden Token-Fehlerpfad (malformed / bad_signature /
8
- // expired / kein Secret) — kein Signal ob ein Token zu einem User gehört.
7
+ // Use the same generic 422 for every token-error path (malformed / bad_signature /
8
+ // expired / missing secret) so callers cannot determine whether a token belongs to a user.
9
9
  function invalidToken() {
10
10
  return new UnprocessableError("invalid_or_expired_token");
11
11
  }
12
- // userId stammt aus dem noch-unverifizierten Token (Angreifer-Eingabe). Ein
13
- // fehlgeschlagener Lookup — z.B. eine typfremde id auf einer int/uuid-Spalte —
14
- // darf nicht als 500 durchschlagen; null behandelt der Caller wie "kein offener
15
- // Antrag" (generischer 422). Die HMAC-Prüfung bleibt der eigentliche Gate.
12
+ // userId comes from the not-yet-verified token (attacker-controlled input). A failed
13
+ // lookup—for example, a type-mismatched id on an int/uuid column—must not surface as a
14
+ // 500; null is treated by the caller as "no pending request" (generic 422). HMAC
15
+ // verification remains the actual gate.
16
16
  async function readPendingDeletionRequestId(ctx, userId) {
17
17
  try {
18
18
  const row = await ctx.db
@@ -32,7 +32,7 @@ async function readPendingDeletionRequestId(ctx, userId) {
32
32
  // the actual grace-period transition, so a crash after the spend can no
33
33
  // longer lose the write step.
34
34
  //
35
- // Replay protection (#354/1): the row's requestId is part of the verify key.
35
+ // Replay protection: the row's requestId is part of the verify key.
36
36
  // We read it via the (unverified, lookup-only) userId from the token, reject
37
37
  // a missing entry, and verify the token against the CURRENT requestId. After
38
38
  // a cancel-deletion (status → Active, pendingDeletionRequestId → null), a
@@ -42,7 +42,7 @@ async function readPendingDeletionRequestId(ctx, userId) {
42
42
  // the same requestId and both verify the HMAC — commitDeletion spends the
43
43
  // anchor AND writes the transition atomically (expect: status===Active &&
44
44
  // pendingDeletionRequestId===requestId), so exactly one wins. The loser gets
45
- // the same generic 422 as an invalid token — no status leak (#354/2).
45
+ // the same generic 422 as an invalid token — no status leak.
46
46
  export function createConfirmDeletionByTokenHandler(opts = {}) {
47
47
  return defineWriteHandler({
48
48
  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
  import { requestContext } from "@cosmicdrift/kumiko-framework/api";
26
26
  import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
@@ -44,7 +44,7 @@ export const downloadByJobQuery = defineQueryHandler({
44
44
  reason: "each signed-in user downloads only their own finished export job; the job " +
45
45
  "lookup checks jobRow.userId against the caller's own id and 404s otherwise",
46
46
  },
47
- }, // openToAll = auth-required, kein anonymous
47
+ }, // openToAll requires authentication; anonymous access is not allowed
48
48
  description: "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.",
49
49
  escapeHatch: {
50
50
  grants: ["unsafeRaw"],
@@ -56,9 +56,8 @@ export const downloadByJobQuery = defineQueryHandler({
56
56
  const userId = query.user.id;
57
57
  const jobId = query.payload.jobId;
58
58
  const tenantId = query.user.tenantId;
59
- // IP + UA aus dem request-scoped Kontext (von requestIdMiddleware
60
- // befuellt) — server-trusted, anders als ein vom Client mitgeschickter
61
- // Wert (603/2).
59
+ // IP and UA from the request-scoped context populated by
60
+ // requestIdMiddleware; these are server-trusted rather than client-supplied.
62
61
  const auditIp = requestContext.get()?.ip ?? null;
63
62
  const auditUa = requestContext.get()?.userAgent ?? null;
64
63
  const runner = ctx.db.unsafeRaw();
@@ -149,10 +148,10 @@ export const downloadByJobQuery = defineQueryHandler({
149
148
  contentDisposition: `attachment; filename="user-data-export-${jobRow.id}.zip"`,
150
149
  });
151
150
  const signedUrlExpiresAt = T.Instant.fromEpochMilliseconds(now.epochMilliseconds + SIGNED_URL_TTL_SECONDS * 1000);
152
- // Step 6: Audit-Update via tokenRow-lookup. UI-Pfad benutzt nicht
153
- // den plain-Token, aber wir wollen den useCount inkrementieren
154
- // damit die Audit-Felder konsistent sind (UI-clicks zaehlen auch
155
- // als Use). Lookup via jobId — UNIQUE-Index garantiert max 1 Row.
151
+ // Step 6: Look up tokenRow for the audit update. The UI flow has no plain
152
+ // token, but its useCount must still be incremented so audit fields remain
153
+ // consistent and UI clicks count as uses. The jobId lookup is safe because
154
+ // the UNIQUE index guarantees at most one row.
156
155
  const tokenRow = await fetchOne(runner, exportDownloadTokensTable, {
157
156
  jobId,
158
157
  });
@@ -168,9 +167,9 @@ export const downloadByJobQuery = defineQueryHandler({
168
167
  userAgent: auditUa,
169
168
  });
170
169
  }
171
- // Wenn tokenRow fehlt (sollte nicht passieren wenn Atom 4a sauber
172
- // lief): Audit-Update skipped, Download laeuft weiter. Niemand wird
173
- // hier durch Audit-Failure blockiert.
170
+ // If tokenRow is missing (which should not happen when the preceding token
171
+ // creation flow completed), skip the audit update and continue the download;
172
+ // an audit failure must not block the user.
174
173
  return {
175
174
  url: signedUrl,
176
175
  expiresAt: signedUrlExpiresAt.toString(),