@cosmicdrift/kumiko-bundled-features 0.386.0 → 0.388.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 (643) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/agent-tools/tool-dispatch.d.ts +7 -7
  4. package/dist/agent-tools/tool-dispatch.js +9 -9
  5. package/dist/audit/handlers/audit-events.js +1 -1
  6. package/dist/audit/screens.js +1 -1
  7. package/dist/auth-email-password/feature.js +1 -1
  8. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  9. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  10. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  11. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  12. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  13. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  14. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  15. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  16. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  17. package/dist/auth-email-password/handlers/login.write.js +1 -1
  18. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  19. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  20. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  21. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  22. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  23. package/dist/auth-email-password/index.js +5 -5
  24. package/dist/auth-email-password/lockout-store.js +1 -1
  25. package/dist/auth-email-password/seeding.d.ts +42 -45
  26. package/dist/auth-email-password/seeding.js +51 -53
  27. package/dist/auth-email-password/signup-token-store.js +8 -8
  28. package/dist/auth-email-password/testing.js +3 -3
  29. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  30. package/dist/auth-email-password/web/auth-client.js +36 -37
  31. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  32. package/dist/auth-email-password/web/auth-gate.js +15 -16
  33. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  34. package/dist/auth-email-password/web/client-plugin.js +4 -5
  35. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  36. package/dist/auth-email-password/web/constants.js +3 -3
  37. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  38. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  39. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  40. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  41. package/dist/auth-email-password/web/index.js +5 -5
  42. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  43. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  44. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  45. package/dist/auth-email-password/web/login-screen.js +2 -3
  46. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  47. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  48. package/dist/auth-email-password/web/session.d.ts +10 -9
  49. package/dist/auth-email-password/web/session.js +28 -29
  50. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  51. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  52. package/dist/auth-email-password/web/signup-screen.js +13 -13
  53. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  54. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  55. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  56. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  57. package/dist/auth-email-password/web/user-menu.js +12 -13
  58. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  59. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  60. package/dist/auth-foundation/boot-checks.js +4 -4
  61. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  62. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  63. package/dist/auth-foundation/types.js +2 -2
  64. package/dist/auth-mfa/feature-exports.d.ts +2 -2
  65. package/dist/auth-mfa/feature.js +8 -0
  66. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  67. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  68. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  69. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  70. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  71. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  72. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  73. package/dist/auth-mfa/token-secrets.js +1 -1
  74. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  75. package/dist/auth-mfa/web/client-plugin.js +1 -1
  76. package/dist/auth-mfa/web/i18n.js +8 -4
  77. package/dist/auth-mfa/web/index.js +4 -4
  78. package/dist/auth-mfa/web/mfa-client.js +17 -16
  79. package/dist/auth-mfa/web/mfa-code-or-recovery-field.d.ts +11 -0
  80. package/dist/auth-mfa/web/mfa-code-or-recovery-field.js +12 -0
  81. package/dist/auth-mfa/web/mfa-disable-dialog.js +14 -3
  82. package/dist/auth-mfa/web/mfa-regenerate-recovery-dialog.js +14 -3
  83. package/dist/auth-mfa/web/mfa-setup-preauth-screen.js +10 -5
  84. package/dist/auth-mfa/web/mfa-verify-screen.js +32 -11
  85. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  86. package/dist/billing-foundation/aggregate-id.js +10 -11
  87. package/dist/billing-foundation/checkout-core.d.ts +9 -14
  88. package/dist/billing-foundation/checkout-core.js +24 -39
  89. package/dist/billing-foundation/consumer-protection/confirmation-mail.js +8 -2
  90. package/dist/billing-foundation/consumer-protection/consent-gate.d.ts +1 -0
  91. package/dist/billing-foundation/consumer-protection/consent-gate.js +1 -0
  92. package/dist/billing-foundation/consumer-protection/issue-confirmation.js +9 -3
  93. package/dist/billing-foundation/consumer-protection/mail-notifications.js +3 -1
  94. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.d.ts +4 -2
  95. package/dist/billing-foundation/consumer-protection/termination-receipt-limit.js +6 -5
  96. package/dist/billing-foundation/consumer-protection/termination-record.d.ts +5 -1
  97. package/dist/billing-foundation/consumer-protection/termination-record.js +27 -17
  98. package/dist/billing-foundation/consumer-protection/termination-request.js +12 -7
  99. package/dist/billing-foundation/consumer-protection/termination-revoke.js +12 -7
  100. package/dist/billing-foundation/consumer-protection/termination-texts.d.ts +1 -1
  101. package/dist/billing-foundation/consumer-protection/termination-texts.js +3 -0
  102. package/dist/billing-foundation/consumer-protection/withdrawal-period.d.ts +5 -2
  103. package/dist/billing-foundation/consumer-protection/withdrawal-period.js +8 -9
  104. package/dist/billing-foundation/entities.js +27 -27
  105. package/dist/billing-foundation/events.d.ts +1 -0
  106. package/dist/billing-foundation/events.js +19 -17
  107. package/dist/billing-foundation/feature.js +45 -44
  108. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  109. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  110. package/dist/billing-foundation/handlers/billing-plans.query.js +35 -5
  111. package/dist/billing-foundation/handlers/create-checkout-session.write.js +19 -17
  112. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  113. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  114. package/dist/billing-foundation/handlers/plan-switch-preview.query.d.ts +13 -0
  115. package/dist/billing-foundation/handlers/plan-switch-preview.query.js +48 -0
  116. package/dist/billing-foundation/handlers/process-event.write.d.ts +6 -0
  117. package/dist/billing-foundation/handlers/process-event.write.js +28 -22
  118. package/dist/billing-foundation/handlers/start-plan-checkout.write.js +32 -5
  119. package/dist/billing-foundation/handlers/switch-plan.write.d.ts +2 -2
  120. package/dist/billing-foundation/handlers/switch-plan.write.js +56 -64
  121. package/dist/billing-foundation/handlers/sync-subscription.write.js +12 -1
  122. package/dist/billing-foundation/i18n.js +22 -0
  123. package/dist/billing-foundation/index.d.ts +1 -1
  124. package/dist/billing-foundation/plan-catalog.d.ts +21 -5
  125. package/dist/billing-foundation/plan-catalog.js +25 -16
  126. package/dist/billing-foundation/plan-switch.d.ts +12 -0
  127. package/dist/billing-foundation/plan-switch.js +60 -0
  128. package/dist/billing-foundation/projection.d.ts +15 -11
  129. package/dist/billing-foundation/projection.js +38 -37
  130. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  131. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  132. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  133. package/dist/billing-foundation/types.d.ts +97 -42
  134. package/dist/billing-foundation/types.js +29 -20
  135. package/dist/billing-foundation/validate-options.js +17 -0
  136. package/dist/billing-foundation/web/billing-plans-panel.js +82 -36
  137. package/dist/billing-foundation/web/checkout-consent-dialog.d.ts +17 -3
  138. package/dist/billing-foundation/web/checkout-consent-dialog.js +14 -10
  139. package/dist/billing-foundation/web/constants.d.ts +4 -0
  140. package/dist/billing-foundation/web/constants.js +4 -0
  141. package/dist/billing-foundation/web/plan-price.d.ts +15 -0
  142. package/dist/billing-foundation/web/plan-price.js +32 -0
  143. package/dist/billing-foundation/web/plan-switch-confirm-dialog.d.ts +15 -0
  144. package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +66 -0
  145. package/dist/cap-counter/aggregate-id.js +8 -9
  146. package/dist/cap-counter/cap-reservation.js +5 -1
  147. package/dist/cap-counter/constants.js +11 -12
  148. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  149. package/dist/cap-counter/enforce-cap.js +49 -49
  150. package/dist/cap-counter/entity.js +29 -29
  151. package/dist/cap-counter/feature.js +34 -35
  152. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  153. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  154. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  155. package/dist/cap-counter/stock-cap-guard.js +8 -2
  156. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  157. package/dist/channel-email/feature.js +1 -1
  158. package/dist/channel-email/smtp-transport.d.ts +18 -17
  159. package/dist/channel-email/smtp-transport.js +24 -21
  160. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  161. package/dist/compliance-profiles/feature.js +4 -4
  162. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  163. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  164. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  165. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  166. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  167. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  168. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  169. package/dist/compliance-profiles/seeding.js +14 -15
  170. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  171. package/dist/compliance-profiles-ops/index.js +2 -2
  172. package/dist/config/handlers/cascade.query.d.ts +5 -0
  173. package/dist/config/handlers/cascade.query.js +4 -3
  174. package/dist/config/handlers/readiness.query.d.ts +4 -4
  175. package/dist/config/handlers/readiness.query.js +1 -1
  176. package/dist/config/handlers/reencrypt.job.js +4 -5
  177. package/dist/config/handlers/set.write.js +4 -4
  178. package/dist/config/handlers/values.query.d.ts +5 -0
  179. package/dist/config/handlers/values.query.js +4 -3
  180. package/dist/config/resolver.js +4 -4
  181. package/dist/config/table.js +10 -10
  182. package/dist/config/write-helpers.d.ts +1 -0
  183. package/dist/config/write-helpers.js +19 -10
  184. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  185. package/dist/crypto-shredding/handlers/forget-subject.write.js +25 -21
  186. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  187. package/dist/custom-fields/aggregate-id.js +16 -17
  188. package/dist/custom-fields/entity.js +49 -47
  189. package/dist/custom-fields/events.js +7 -8
  190. package/dist/custom-fields/feature.d.ts +14 -14
  191. package/dist/custom-fields/feature.js +53 -54
  192. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  193. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  194. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  195. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  196. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  197. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  198. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  199. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  200. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  201. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  202. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  203. package/dist/custom-fields/lib/field-access.js +2 -2
  204. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  205. package/dist/custom-fields/lib/quota.js +1 -1
  206. package/dist/custom-fields/lib/value-schema.js +10 -12
  207. package/dist/custom-fields/run-retention.js +3 -3
  208. package/dist/custom-fields/schemas.js +14 -14
  209. package/dist/custom-fields/web/client-plugin.js +2 -5
  210. package/dist/custom-fields/web/constants.js +2 -2
  211. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  212. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  213. package/dist/custom-fields/wire-for-entity.js +65 -67
  214. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  215. package/dist/data-retention/_internal/parse-override.js +2 -3
  216. package/dist/data-retention/feature.js +11 -18
  217. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  218. package/dist/data-retention/keep-for.d.ts +7 -7
  219. package/dist/data-retention/keep-for.js +15 -15
  220. package/dist/data-retention/override-schema.d.ts +3 -4
  221. package/dist/data-retention/override-schema.js +13 -15
  222. package/dist/data-retention/presets.d.ts +4 -5
  223. package/dist/data-retention/presets.js +18 -23
  224. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  225. package/dist/data-retention/resolver.d.ts +12 -12
  226. package/dist/data-retention/resolver.js +24 -23
  227. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  228. package/dist/data-retention/run-retention-cleanup.js +61 -51
  229. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  230. package/dist/delivery/channel-context.js +6 -3
  231. package/dist/delivery/db/queries/preferences.js +2 -2
  232. package/dist/delivery/delivery-service.js +22 -7
  233. package/dist/delivery/feature.js +2 -2
  234. package/dist/delivery/handlers/log.query.js +1 -1
  235. package/dist/delivery/handlers/preferences.query.d.ts +1 -1
  236. package/dist/delivery/handlers/preferences.query.js +20 -1
  237. package/dist/delivery/handlers/unsubscribe-page-chrome.query.js +1 -1
  238. package/dist/delivery/tables.js +9 -8
  239. package/dist/delivery/unsubscribe-link.d.ts +3 -1
  240. package/dist/delivery/unsubscribe-page-strings.d.ts +1 -0
  241. package/dist/delivery/unsubscribe-page-strings.js +1 -0
  242. package/dist/delivery/unsubscribe-page.d.ts +2 -0
  243. package/dist/delivery/unsubscribe-page.js +5 -0
  244. package/dist/delivery/unsubscribe.js +29 -11
  245. package/dist/document-ingest-foundation/entity.js +4 -4
  246. package/dist/document-ingest-foundation/events.js +2 -2
  247. package/dist/document-ingest-foundation/feature.js +2 -2
  248. package/dist/document-ingest-foundation/pages.js +1 -1
  249. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  250. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  251. package/dist/feature-toggles/feature.js +1 -1
  252. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  253. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  254. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  255. package/dist/feature-toggles/web/constants.js +1 -1
  256. package/dist/file-derivatives/feature.d.ts +1 -1
  257. package/dist/file-derivatives/feature.js +1 -1
  258. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  259. package/dist/file-derivatives/presets.js +1 -1
  260. package/dist/file-foundation/feature.js +6 -6
  261. package/dist/file-foundation/index.d.ts +1 -1
  262. package/dist/file-foundation/index.js +1 -1
  263. package/dist/file-foundation/read-file-ref-content.d.ts +3 -0
  264. package/dist/file-foundation/read-file-ref-content.js +6 -1
  265. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  266. package/dist/file-provider-inmemory/feature.js +16 -16
  267. package/dist/file-provider-s3/env-named-feature.d.ts +0 -2
  268. package/dist/file-provider-s3/feature.js +16 -16
  269. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  270. package/dist/files/feature.js +6 -6
  271. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  272. package/dist/files-tenant-data/hooks.js +24 -26
  273. package/dist/files-tenant-data/index.js +1 -1
  274. package/dist/folders/feature.d.ts +1 -1
  275. package/dist/folders/web/folder-manager.js +2 -2
  276. package/dist/folders/web/tree.js +5 -5
  277. package/dist/form-draft/db/queries/cleanup.js +3 -3
  278. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  279. package/dist/form-draft/decrypt-draft.js +5 -1
  280. package/dist/form-draft/entity.js +3 -3
  281. package/dist/form-draft/feature.js +4 -5
  282. package/dist/form-draft/handlers/discard.write.js +1 -1
  283. package/dist/form-draft/release-file-refs.js +6 -6
  284. package/dist/form-draft/schemas.js +3 -3
  285. package/dist/form-draft/web/constants.js +0 -2
  286. package/dist/host-routing/dispatch.js +11 -20
  287. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  288. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  289. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  290. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  291. package/dist/inbound-mail-foundation/constants.js +30 -33
  292. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  293. package/dist/inbound-mail-foundation/entities.js +47 -48
  294. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  295. package/dist/inbound-mail-foundation/events.js +50 -47
  296. package/dist/inbound-mail-foundation/feature.js +39 -39
  297. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  298. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  299. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  300. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  301. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  302. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  303. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  304. package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +2 -2
  305. package/dist/inbound-mail-foundation/handlers/update-account.write.js +22 -14
  306. package/dist/inbound-mail-foundation/i18n.js +0 -1
  307. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  308. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  309. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  310. package/dist/inbound-mail-foundation/projection.js +31 -29
  311. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  312. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  313. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  314. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  315. package/dist/inbound-mail-foundation/screens.js +0 -3
  316. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  317. package/dist/inbound-mail-foundation/types.d.ts +49 -49
  318. package/dist/inbound-mail-foundation/types.js +21 -21
  319. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  320. package/dist/inbound-mail-foundation/watch-supervisor.js +85 -67
  321. package/dist/inbound-provider-imap/credential-document.js +13 -13
  322. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  323. package/dist/inbound-provider-imap/feature.js +42 -40
  324. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  325. package/dist/inbound-provider-imap/imap-client.js +20 -19
  326. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  327. package/dist/inbound-provider-inmemory/feature.js +19 -19
  328. package/dist/jobs/db/queries/retention.js +2 -2
  329. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  330. package/dist/jobs/events.js +1 -1
  331. package/dist/jobs/feature.d.ts +1 -0
  332. package/dist/jobs/feature.js +13 -10
  333. package/dist/jobs/handlers/detail.query.js +4 -4
  334. package/dist/jobs/handlers/list.query.js +1 -1
  335. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  336. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  337. package/dist/jobs/handlers/retry.write.js +1 -1
  338. package/dist/jobs/handlers/tenant-failures.query.d.ts +1 -1
  339. package/dist/jobs/handlers/tenant-failures.query.js +45 -41
  340. package/dist/jobs/handlers/tenant-runs.query.d.ts +1 -1
  341. package/dist/jobs/handlers/tenant-runs.query.js +54 -50
  342. package/dist/jobs/job-instant.js +1 -1
  343. package/dist/jobs/job-run-logger.js +15 -15
  344. package/dist/jobs/job-run-table.js +3 -3
  345. package/dist/jobs/screens.js +1 -1
  346. package/dist/jobs/tenant-job-failure-table.js +1 -1
  347. package/dist/jobs/tenant-job-run-table.js +1 -1
  348. package/dist/ledger/entity.js +5 -5
  349. package/dist/ledger/feature.js +3 -3
  350. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  351. package/dist/ledger/recurring.js +12 -12
  352. package/dist/ledger/schemas.js +1 -1
  353. package/dist/ledger/web/constants.js +2 -2
  354. package/dist/ledger/web/index.js +7 -7
  355. package/dist/legal-pages/feature.d.ts +4 -4
  356. package/dist/legal-pages/feature.js +25 -26
  357. package/dist/legal-pages/markdown.js +3 -3
  358. package/dist/legal-pages/web/client-plugin.js +23 -24
  359. package/dist/legal-pages/web/index.js +0 -1
  360. package/dist/mail-foundation/feature.d.ts +5 -5
  361. package/dist/mail-foundation/feature.js +27 -25
  362. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  363. package/dist/mail-transport-inmemory/feature.js +27 -28
  364. package/dist/mail-transport-smtp/feature.js +20 -20
  365. package/dist/managed-pages/branding.js +6 -6
  366. package/dist/managed-pages/feature.d.ts +26 -26
  367. package/dist/managed-pages/feature.js +34 -34
  368. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  369. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  370. package/dist/managed-pages/handlers/set.write.js +5 -7
  371. package/dist/managed-pages/screens/page-screens.js +11 -11
  372. package/dist/managed-pages/seeding.js +8 -8
  373. package/dist/managed-pages/table.js +13 -12
  374. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  375. package/dist/managed-pages/web/client-plugin.js +5 -5
  376. package/dist/managed-pages/web/i18n.js +1 -1
  377. package/dist/notes-history/entity.js +4 -4
  378. package/dist/notes-history/feature.d.ts +2 -2
  379. package/dist/notes-history-user-data/hooks.js +1 -1
  380. package/dist/page-render/layout.js +9 -9
  381. package/dist/page-render/markdown.js +11 -11
  382. package/dist/page-render/security-headers.js +7 -6
  383. package/dist/personal-access-tokens/feature.d.ts +1 -1
  384. package/dist/personal-access-tokens/feature.js +9 -5
  385. package/dist/personal-access-tokens/roles.js +2 -2
  386. package/dist/readiness/handlers/status.query.js +3 -3
  387. package/dist/renderer-foundation/api.js +12 -13
  388. package/dist/renderer-foundation/constants.js +2 -2
  389. package/dist/renderer-foundation/feature.js +7 -7
  390. package/dist/renderer-pdf/render-table-pdf.d.ts +1 -1
  391. package/dist/renderer-pdf/render-table-pdf.js +22 -10
  392. package/dist/secrets/feature.js +9 -9
  393. package/dist/secrets/web/constants.js +2 -2
  394. package/dist/seo/feature.js +3 -3
  395. package/dist/sessions/constants.d.ts +1 -1
  396. package/dist/sessions/constants.js +1 -1
  397. package/dist/sessions/feature.d.ts +2 -2
  398. package/dist/sessions/feature.js +12 -8
  399. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  400. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  401. package/dist/sessions/handlers/revoke.write.js +1 -1
  402. package/dist/sessions/schema/user-session.js +4 -4
  403. package/dist/sessions/screens.js +2 -2
  404. package/dist/sessions/session-callbacks.js +2 -2
  405. package/dist/sessions/session-revoked-event.js +2 -2
  406. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  407. package/dist/shared/decrypt-stored-pii.d.ts +1 -0
  408. package/dist/shared/decrypt-stored-pii.js +7 -2
  409. package/dist/shared/encrypt-for-direct-write.js +1 -1
  410. package/dist/shared/index.d.ts +1 -1
  411. package/dist/shared/index.js +1 -1
  412. package/dist/shared/mail-template-body.d.ts +6 -2
  413. package/dist/shared/mail-template-body.js +7 -4
  414. package/dist/shared/map-with-concurrency.js +5 -4
  415. package/dist/shared/parent-visibility.js +2 -2
  416. package/dist/shared/password-hashing.js +1 -1
  417. package/dist/shared/signup-handover.js +1 -2
  418. package/dist/shared/single-use-token-store.js +1 -1
  419. package/dist/step-dispatcher/feature.js +1 -0
  420. package/dist/subscription-dodo/client.d.ts +17 -0
  421. package/dist/subscription-dodo/client.js +31 -0
  422. package/dist/subscription-dodo/constants.d.ts +12 -0
  423. package/dist/subscription-dodo/constants.js +19 -0
  424. package/dist/subscription-dodo/feature.d.ts +37 -0
  425. package/dist/subscription-dodo/feature.js +144 -0
  426. package/dist/subscription-dodo/index.d.ts +2 -0
  427. package/dist/subscription-dodo/index.js +4 -0
  428. package/dist/subscription-dodo/plugin-methods.d.ts +23 -0
  429. package/dist/subscription-dodo/plugin-methods.js +260 -0
  430. package/dist/subscription-dodo/runtime.d.ts +27 -0
  431. package/dist/subscription-dodo/runtime.js +89 -0
  432. package/dist/subscription-dodo/verify-webhook.d.ts +37 -0
  433. package/dist/subscription-dodo/verify-webhook.js +189 -0
  434. package/dist/subscription-mollie/constants.js +15 -17
  435. package/dist/subscription-mollie/feature.d.ts +17 -18
  436. package/dist/subscription-mollie/feature.js +24 -24
  437. package/dist/subscription-mollie/index.js +3 -3
  438. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  439. package/dist/subscription-mollie/plugin-methods.js +15 -14
  440. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  441. package/dist/subscription-mollie/verify-webhook.js +27 -27
  442. package/dist/subscription-stripe/constants.js +4 -6
  443. package/dist/subscription-stripe/feature.d.ts +14 -14
  444. package/dist/subscription-stripe/feature.js +36 -34
  445. package/dist/subscription-stripe/index.js +6 -6
  446. package/dist/subscription-stripe/plugin-methods.js +18 -18
  447. package/dist/subscription-stripe/runtime.d.ts +1 -1
  448. package/dist/subscription-stripe/runtime.js +8 -7
  449. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  450. package/dist/subscription-stripe/verify-webhook.js +59 -61
  451. package/dist/tags/feature.d.ts +3 -3
  452. package/dist/tags/screens.js +1 -1
  453. package/dist/template-resolver/api.d.ts +3 -2
  454. package/dist/template-resolver/api.js +34 -12
  455. package/dist/template-resolver/compile-document-body.js +1 -0
  456. package/dist/template-resolver/feature.js +2 -2
  457. package/dist/template-resolver/handlers/bundle-import.js +3 -3
  458. package/dist/template-resolver/handlers/copy-locale.write.d.ts +5 -1
  459. package/dist/template-resolver/handlers/copy-locale.write.js +22 -7
  460. package/dist/template-resolver/handlers/diff-to-system.query.js +3 -2
  461. package/dist/template-resolver/handlers/document-base.js +3 -2
  462. package/dist/template-resolver/handlers/find-by-id.query.js +8 -7
  463. package/dist/template-resolver/handlers/list.query.js +6 -7
  464. package/dist/template-resolver/handlers/overview.query.d.ts +3 -0
  465. package/dist/template-resolver/handlers/overview.query.js +6 -3
  466. package/dist/template-resolver/handlers/shared.js +2 -2
  467. package/dist/template-resolver/handlers/template-write.js +3 -3
  468. package/dist/template-resolver/handlers/tenant-override-counts.query.js +1 -3
  469. package/dist/template-resolver/handlers/tenant-override-selection.d.ts +2 -1
  470. package/dist/template-resolver/handlers/tenant-overrides.query.js +28 -5
  471. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  472. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  473. package/dist/template-resolver/handlers/usage.query.d.ts +2 -1
  474. package/dist/template-resolver/handlers/usage.query.js +26 -16
  475. package/dist/template-resolver/handlers/validate.query.js +7 -2
  476. package/dist/template-resolver/seeding.js +30 -14
  477. package/dist/template-resolver/store-template-resource.d.ts +1 -0
  478. package/dist/template-resolver/store-template-resource.js +19 -4
  479. package/dist/template-resolver/table.js +10 -11
  480. package/dist/template-resolver/template-delivery-policy.d.ts +0 -5
  481. package/dist/template-resolver/template-delivery-policy.js +0 -6
  482. package/dist/template-resolver/template-meta.js +7 -4
  483. package/dist/template-resolver/template-preview.js +4 -3
  484. package/dist/template-resolver/web/client-plugin.js +2 -2
  485. package/dist/template-resolver/web/constants.d.ts +2 -2
  486. package/dist/template-resolver/web/constants.js +3 -3
  487. package/dist/template-resolver/web/index.d.ts +1 -0
  488. package/dist/template-resolver/web/index.js +1 -0
  489. package/dist/template-resolver/web/mail-layout-constants.d.ts +5 -0
  490. package/dist/template-resolver/web/mail-layout-constants.js +7 -0
  491. package/dist/tenant/feature.js +7 -7
  492. package/dist/tenant/handlers/member-directory.query.d.ts +1 -0
  493. package/dist/tenant/handlers/member-directory.query.js +11 -4
  494. package/dist/tenant/handlers/members.query.js +1 -1
  495. package/dist/tenant/handlers/team-list.query.js +1 -1
  496. package/dist/tenant/handlers/tenant-directory.query.d.ts +1 -0
  497. package/dist/tenant/handlers/tenant-directory.query.js +9 -5
  498. package/dist/tenant/invitation-table.js +37 -40
  499. package/dist/tenant/membership-table.js +3 -3
  500. package/dist/tenant/schema/tenant.js +7 -9
  501. package/dist/tenant/screens.js +1 -1
  502. package/dist/tenant/seeding.d.ts +6 -5
  503. package/dist/tenant/seeding.js +12 -12
  504. package/dist/tenant/testing.js +5 -6
  505. package/dist/tenant/web/constants.js +2 -2
  506. package/dist/tenant-handover/events.js +5 -7
  507. package/dist/tenant-handover/feature.js +1 -1
  508. package/dist/tenant-handover/grant.js +1 -1
  509. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  510. package/dist/tenant-handover/move-entity-graph.js +8 -9
  511. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  512. package/dist/tenant-handover/transfer-graph.js +4 -5
  513. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  514. package/dist/tenant-lifecycle/constants.d.ts +1 -0
  515. package/dist/tenant-lifecycle/constants.js +4 -0
  516. package/dist/tenant-lifecycle/feature.js +1 -1
  517. package/dist/tenant-lifecycle/run-tenant-destroy.js +2 -2
  518. package/dist/tenant-settings/constants.js +1 -1
  519. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  520. package/dist/tenant-settings/tenant-defaults.js +9 -2
  521. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  522. package/dist/tier-engine/aggregate-id.js +15 -16
  523. package/dist/tier-engine/compose-app.d.ts +14 -14
  524. package/dist/tier-engine/compose-app.js +1 -1
  525. package/dist/tier-engine/entity.js +18 -19
  526. package/dist/tier-engine/feature.d.ts +19 -17
  527. package/dist/tier-engine/feature.js +68 -69
  528. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  529. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  530. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +7 -8
  531. package/dist/tier-engine/handlers/set-tenant-tier.write.js +7 -4
  532. package/dist/tier-engine/tier-resolver.js +2 -2
  533. package/dist/tier-engine/trial.js +8 -8
  534. package/dist/tier-engine/web/constants.js +2 -2
  535. package/dist/tier-engine/web/index.js +4 -4
  536. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  537. package/dist/user/handlers/create.write.js +4 -4
  538. package/dist/user/schema/user.d.ts +11 -11
  539. package/dist/user/schema/user.js +45 -44
  540. package/dist/user/seeding.d.ts +15 -15
  541. package/dist/user/seeding.js +28 -28
  542. package/dist/user/testing.js +3 -3
  543. package/dist/user-data-rights/audit-download.d.ts +8 -8
  544. package/dist/user-data-rights/audit-download.js +19 -20
  545. package/dist/user-data-rights/boot-checks.js +1 -1
  546. package/dist/user-data-rights/deletion-token.js +1 -1
  547. package/dist/user-data-rights/feature.d.ts +49 -50
  548. package/dist/user-data-rights/feature.js +54 -53
  549. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  550. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  551. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  552. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  553. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  554. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  555. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  556. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  557. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  558. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  559. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  560. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  561. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  562. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  563. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  564. package/dist/user-data-rights/index.js +8 -10
  565. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  566. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  567. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  568. package/dist/user-data-rights/run-export-jobs.js +130 -237
  569. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  570. package/dist/user-data-rights/run-forget-cleanup.js +65 -83
  571. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  572. package/dist/user-data-rights/run-user-export.js +55 -57
  573. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  574. package/dist/user-data-rights/schema/download-token.js +37 -41
  575. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  576. package/dist/user-data-rights/schema/export-job.js +65 -67
  577. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  578. package/dist/user-data-rights/token-helpers.js +21 -25
  579. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  580. package/dist/user-data-rights/web/client-plugin.js +1 -1
  581. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  582. package/dist/user-data-rights/web/constants.js +1 -1
  583. package/dist/user-data-rights/web/index.js +5 -5
  584. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  585. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  586. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  587. package/dist/user-data-rights/zip-path.d.ts +15 -15
  588. package/dist/user-data-rights/zip-path.js +41 -40
  589. package/dist/user-data-rights-defaults/feature.js +15 -15
  590. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  591. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  592. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  593. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  594. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  595. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  596. package/dist/user-profile/handlers/change-email.write.js +13 -13
  597. package/dist/user-profile/index.js +3 -3
  598. package/dist/user-profile/web/client-plugin.js +1 -1
  599. package/dist/user-profile/web/constants.js +1 -1
  600. package/dist/user-profile/web/profile-screen.js +1 -1
  601. package/dist/waitlist/handlers/export-purge.write.js +2 -1
  602. package/dist/waitlist/handlers/submit.write.js +5 -5
  603. package/dist/waitlist/import.d.ts +1 -0
  604. package/dist/waitlist/import.js +4 -0
  605. package/dist/waitlist/legacy-migrate.js +17 -6
  606. package/dist/waitlist/link-on-signup.js +18 -6
  607. package/dist/waitlist/options.d.ts +3 -0
  608. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  609. package/dist/workflow-runner/aggregate-id.js +1 -1
  610. package/dist/workflow-runner/event-subscriber.js +4 -5
  611. package/dist/workflow-runner/event-trigger.js +4 -17
  612. package/dist/workflow-runner/feature.js +2 -2
  613. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  614. package/dist/workflow-runner/pending-projection.js +6 -7
  615. package/dist/workflow-runner/runner.js +6 -6
  616. package/dist/workflow-runner/tables.js +6 -6
  617. package/dist/workflow-runner/workflow-registry.js +1 -1
  618. package/package.json +20 -10
  619. package/src/agent-tools/changes.json +6 -0
  620. package/src/audit/changes.json +12 -0
  621. package/src/auth-mfa/changes.json +6 -0
  622. package/src/billing-foundation/changes.json +55 -0
  623. package/src/cap-counter/changes.json +18 -0
  624. package/src/channel-email/changes.json +6 -0
  625. package/src/config/changes.json +12 -0
  626. package/src/crypto-shredding/changes.json +6 -0
  627. package/src/delivery/changes.json +30 -0
  628. package/src/form-draft/changes.json +6 -0
  629. package/src/host-routing/changes.json +6 -0
  630. package/src/inbound-mail-foundation/changes.json +18 -0
  631. package/src/jobs/changes.json +13 -0
  632. package/src/mail-foundation/changes.json +6 -0
  633. package/src/renderer-pdf/changes.json +6 -0
  634. package/src/step-dispatcher/changes.json +6 -0
  635. package/src/subscription-dodo/changes.json +14 -0
  636. package/src/subscription-stripe/changes.json +12 -0
  637. package/src/template-resolver/changes.json +48 -0
  638. package/src/tenant/changes.json +6 -0
  639. package/src/tenant-lifecycle/changes.json +6 -0
  640. package/src/tier-engine/changes.json +6 -0
  641. package/src/waitlist/changes.json +18 -0
  642. package/dist/billing-foundation/consumer-protection/stored-user-email.d.ts +0 -1
  643. package/dist/billing-foundation/consumer-protection/stored-user-email.js +0 -8
@@ -4,10 +4,10 @@ import { eventsTable } from "@cosmicdrift/kumiko-framework/event-store";
4
4
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
5
5
  import * as z from "zod";
6
6
  import { redactPiiCiphertext } from "../../shared/index.js";
7
- // DSGVO Art. 15 Selbstauskunft — User reads HIS OWN audit-log.
8
- // WHERE createdBy = ctx.user.id ist hard-coded (kein userId-Param,
9
- // anti-cross-user-Snooping). KEIN tenantId-Filter: User hat Anspruch
10
- // auf account-weite Sicht ueber alle Memberships — analog Forget-Pfad.
7
+ // GDPR Art. 15 self-disclosure: users may read only their own audit log.
8
+ // `createdBy = ctx.user.id` is hard-coded to prevent cross-user snooping;
9
+ // no `tenantId` filter is applied because the user is entitled to an
10
+ // account-wide view across all memberships, as in the forget path.
11
11
  const MAX_LIMIT = 100;
12
12
  const MY_AUDIT_LOG_REASON = "reads the caller's own events across all tenant memberships, bounded by createdBy = caller";
13
13
  export const myAuditLogQuery = defineQueryHandler({
@@ -5,12 +5,12 @@ export type SendDeletionVerificationEmailFn = (args: {
5
5
  readonly expiresAt: string;
6
6
  }) => Promise<void>;
7
7
  export type RequestDeletionByEmailOptions = {
8
- /** HMAC-Secret zum Signieren des Verify-Tokens. Ohne Secret ist der Flow
9
- * deaktiviert (Handler antwortet still mit success, kein Link). */
8
+ /** HMAC secret used to sign the verification token. Without a secret, the flow
9
+ * is disabled (the handler silently responds with success and no link). */
10
10
  readonly deletionTokenSecret?: string;
11
- /** Basis-URL des Apex-Confirm-Screens, z.B.
12
- * "https://app.example.com/delete-account/confirm". Der Handler hängt das
13
- * Token als URL-Fragment an (`#token=<token>`, fw#1554). Ohne URL kein Link. */
11
+ /** Base URL of the Apex confirmation screen, e.g.
12
+ * "https://app.example.com/delete-account/confirm". The handler appends the
13
+ * token as a URL fragment (`#token=<token>`). Without a URL, no link is sent. */
14
14
  readonly deletionVerifyUrl?: string;
15
15
  readonly sendDeletionVerificationEmail?: SendDeletionVerificationEmailFn;
16
16
  };
@@ -3,13 +3,13 @@ import * as z from "zod";
3
3
  import { USER_STATUS, userTable } from "../../user/index.js";
4
4
  import { signDeletionToken } from "../deletion-token.js";
5
5
  import { updateUserLifecycle } from "../lib/update-user-lifecycle.js";
6
- // TTL des Verify-Links. 60 min — lang genug für einen Mail-Roundtrip,
7
- // kurz genug dass ein abgefangener Link nicht ewig gültig ist.
6
+ // Verification-link TTL: 60 minutes — long enough for an email round trip,
7
+ // but short enough that an intercepted link does not remain valid indefinitely.
8
8
  const DELETION_VERIFY_TTL_MINUTES = 60;
9
9
  // Token goes in the URL fragment, not a query param — fragments never leave
10
10
  // the browser (not sent to the server, so they never land in proxy/access
11
11
  // logs, unlike `?token=`). Same convention as the export-download link
12
- // (feature.ts, issue #1271). Preserves any existing query params on `base`
12
+ // (feature.ts). Preserves any existing query params on `base`
13
13
  // (`?lang=de` stays a query param; only the token is a fragment).
14
14
  const APPEND_LIFECYCLE_EVENT_REASON = "appends the user lifecycle event on the SYSTEM_TENANT_ID user stream";
15
15
  export function buildDeletionVerifyUrl(base, token) {
@@ -17,14 +17,14 @@ export function buildDeletionVerifyUrl(base, token) {
17
17
  url.hash = `token=${encodeURIComponent(token)}`;
18
18
  return url.toString();
19
19
  }
20
- // Anonymer Apex-Flow Schritt 1: "Account-Löschung beantragen" per Email.
21
- // DSGVO-relevant gerade wenn der User sich NICHT mehr einloggen kann
22
- // (Lockout). Email → Magic-Link → confirm-deletion-by-token.
20
+ // Anonymous Apex flow step 1: request account deletion by email.
21
+ // This is especially relevant for GDPR when the user can no longer log in
22
+ // (lockout). Email → magic link → confirm-deletion-by-token.
23
23
  //
24
- // Enumeration-safe (content): antwortet IMMER mit derselben success-Shape,
25
- // egal ob die Email existiert, der User aktiv ist oder der Flow konfiguriert
26
- // ist. Ein Link wird nur für einen existierenden, aktiven User generiert.
27
- // Timing-Safety hängt am non-blocking Callback (siehe Type-Doc oben).
24
+ // Enumeration-safe (content): always returns the same success shape,
25
+ // regardless of whether the email exists, the user is active, or the flow is
26
+ // configured. A link is generated only for an existing, active user.
27
+ // Timing safety depends on the non-blocking callback (see the type doc above).
28
28
  export function createRequestDeletionByEmailHandler(opts = {}) {
29
29
  return defineWriteHandler({
30
30
  name: "request-deletion-by-email",
@@ -33,7 +33,7 @@ export function createRequestDeletionByEmailHandler(opts = {}) {
33
33
  description: "Mails an account-deletion verification link to the given address, for a user who wants to be erased but can no longer log in; it answers identically whether or not the address belongs to an active account and never returns the link.",
34
34
  // Mails a deletion link to any address the caller names.
35
35
  agent: { risk: "high" },
36
- // Defense-in-depth gegen Email-Probing auf dem anonymen Endpoint.
36
+ // Defense in depth against email probing on the anonymous endpoint.
37
37
  rateLimit: { per: "ip+handler", limit: 10, windowSeconds: 60 },
38
38
  escapeHatch: {
39
39
  grants: ["unsafeRaw", "globalWrites"],
@@ -41,7 +41,8 @@ export function createRequestDeletionByEmailHandler(opts = {}) {
41
41
  },
42
42
  handler: async (event, ctx) => {
43
43
  const success = { isSuccess: true, data: { kind: "requested" } };
44
- // not-configured-safe: ohne Secret/URL kein Link, aber gleiche Antwort.
44
+ // Safe when not configured: without a secret or URL, no link is sent, but the response is
45
+ // unchanged.
45
46
  if (!opts.deletionTokenSecret || !opts.deletionVerifyUrl)
46
47
  return success;
47
48
  const userRow = await ctx.db
@@ -53,9 +54,9 @@ export function createRequestDeletionByEmailHandler(opts = {}) {
53
54
  if (!userRow || userRow["status"] !== USER_STATUS.Active || !userRow["email"]) {
54
55
  return success;
55
56
  }
56
- // Replay-Schutz (#354/1): pro Antrag eine frische requestId, die auf der
57
- // user-Row landet und in die Token-HMAC-Purpose gefaltet wird. cancel
58
- // nullt sie → ein nach Cancel nachgespieltes Token verifiziert nicht mehr.
57
+ // Replay protection: each request gets a fresh requestId, which is stored on
58
+ // the user row and incorporated into the token HMAC purpose. cancel
59
+ // nulls it, so a token replayed after cancellation no longer verifies.
59
60
  const requestId = crypto.randomUUID();
60
61
  await updateUserLifecycle(ctx.db.unsafeRaw(), userRow["id"], {
61
62
  pendingDeletionRequestId: requestId,
@@ -11,8 +11,8 @@ export type SendDeletionRequestedEmailFn = (args: {
11
11
  }) => Promise<void>;
12
12
  export type RequestDeletionOptions = {
13
13
  readonly sendDeletionRequestedEmail?: SendDeletionRequestedEmailFn;
14
- /** Branding fuer die Default-Mail wenn kein sendDeletionRequestedEmail
15
- * gesetzt ist + mail-foundation gemountet ist. */
14
+ /** Branding for the default email when sendDeletionRequestedEmail is not set
15
+ * and mail-foundation is mounted. */
16
16
  readonly mailDefaults?: GdprMailDefaults;
17
17
  };
18
18
  export declare function createRequestDeletionHandler(opts?: RequestDeletionOptions): import("@cosmicdrift/kumiko-types/define-handler").WriteHandlerDefinition<"request-deletion", z.ZodObject<{}, z.core.$strip>, {
@@ -4,11 +4,10 @@ import * as z from "zod";
4
4
  import { USER_STATUS } from "../../user/index.js";
5
5
  import { isGdprMailDeliveryAvailable, makeDefaultDeletionRequestedEmail, } from "../lib/default-mailers.js";
6
6
  import { resolveGracePeriod, startDeletionGracePeriod } from "./deletion-grace-period.js";
7
- // POST /api/user/request-deletion (S2.U5a) — DSGVO Art. 17 Forget-Antrag.
8
- // Flippt status=Active → deletionRequested, setzt gracePeriodEnd aus dem
9
- // Compliance-Profile (geteilte Logik: startDeletionGracePeriod). Account-
10
- // weite Semantik (1 User-Row global), siehe docs/plans/architecture/
11
- // user-data-rights.md "Cross-Tenant-Semantik".
7
+ // POST /api/user/request-deletion — GDPR Art. 17 erasure request.
8
+ // Changes status=Active → deletionRequested and sets gracePeriodEnd from the compliance
9
+ // profile using the shared startDeletionGracePeriod logic. The operation applies to the
10
+ // account-wide user row, so the user identity is global across tenants.
12
11
  export function createRequestDeletionHandler(opts = {}) {
13
12
  return defineWriteHandler({
14
13
  name: "request-deletion",
@@ -39,8 +38,7 @@ export function createRequestDeletionHandler(opts = {}) {
39
38
  (ctx.notify !== undefined && isGdprMailDeliveryAvailable(ctx.registry)
40
39
  ? makeDefaultDeletionRequestedEmail(ctx.notify, opts.mailDefaults)
41
40
  : undefined);
42
- // Best-effort Email-Notification. Send-Failure darf das Write nicht
43
- // killen — siehe Type-Doc oben.
41
+ // Best-effort email notification: a send failure must not abort the write.
44
42
  if (send && userEmail.length > 0) {
45
43
  try {
46
44
  await send({
@@ -56,8 +54,8 @@ export function createRequestDeletionHandler(opts = {}) {
56
54
  console.warn(`[user-data-rights:request-deletion] sendDeletionRequestedEmail failed userId=${event.user.id} tenantId=${event.user.tenantId} err=${err instanceof Error ? err.message : String(err)}`);
57
55
  }
58
56
  }
59
- // Response liefert den absoluten gracePeriodEnd-Timestamp damit
60
- // Frontend/Audit/Cleanup-Runner alle denselben Wert lesen.
57
+ // Returns the absolute gracePeriodEnd timestamp so the frontend, audit, and cleanup
58
+ // runner all use the same value.
61
59
  return {
62
60
  isSuccess: true,
63
61
  data: {
@@ -1,24 +1,25 @@
1
- // POST /api/user/request-export (S2.U3 Atom 2) — DSGVO Art. 15 + 20 Trigger.
1
+ // POST /api/user/request-export — GDPR Art. 15 and 20 trigger.
2
2
  //
3
- // User triggert Export-Job. Persistenz via createEventStoreExecutor
4
- // (ES-Pattern, Memory: ES kein CRUD). Idempotency-Strategie zweistufig:
3
+ // The user triggers an export job, persisted through
4
+ // createEventStoreExecutor (event-sourced pattern; ES has no CRUD).
5
+ // Idempotency uses two stages:
5
6
  //
6
- // 1) **App-side-Pre-Check (primaerer Pfad):** fetchOne aktive Jobs
7
- // (status pending|running) fuer den userId. Wenn existing,
8
- // return `{jobId, isExisting: true}` — KEIN neues Event,
9
- // sauberer Audit-Trail (1 Klick-Storm = 1 Event, nicht N).
7
+ // 1) **App-side pre-check (primary path):** fetch active jobs with
8
+ // (status pending|running) for the userId. If one exists, return
9
+ // `{jobId, isExisting: true}` without creating an event, so a click
10
+ // storm produces one audit event rather than N.
10
11
  //
11
- // 2) **DB-Constraint als Race-Schutz (Sekundaerpfad):** Bei parallelem
12
- // Klick zwischen fetchOne + crud.create wirft die Tx 23505 mit
13
- // constraint_name === "read_export_jobs_one_active_per_user".
14
- // Catch + re-fetch + return existing als isExisting=true. Race-
15
- // Window <1ms, in Production extrem selten.
12
+ // 2) **DB constraint as race protection (secondary path):** if a parallel
13
+ // click occurs between fetchOne and crud.create, the transaction raises
14
+ // 23505 with constraint_name === "read_export_jobs_one_active_per_user".
15
+ // Catch, re-fetch, and return the existing job with isExisting=true.
16
16
  //
17
- // **Cross-Tenant-Semantik:** ExportJob is tenant-agnostic (1 job per userId
18
- // across all memberships) — the pre-check uses ctx.db.unsafeRaw (no TenantDb filter) so a click from tenant B still finds the job from tenant A.
19
- // `requestedFromTenantId` persistiert den Initial-Tenant aus dem
20
- // 1. Klick — Worker liest sein Compliance-Profile aus DIESEM Tenant
21
- // fuer Job-TTL/Stale/Cleanup.
17
+ // **Cross-tenant semantics:** ExportJob is tenant-agnostic (one job per
18
+ // userId across all memberships), so the pre-check uses ctx.db.unsafeRaw
19
+ // (no TenantDb filter) and a click from tenant B can find the job from tenant
20
+ // A. `requestedFromTenantId` persists the tenant from the first click; the
21
+ // worker reads its compliance profile from this tenant for job TTL, stale
22
+ // handling, and cleanup.
22
23
  import { createEventStoreExecutor, fetchOne } from "@cosmicdrift/kumiko-framework/db";
23
24
  import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
24
25
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
@@ -29,11 +30,11 @@ const crud = createEventStoreExecutor(exportJobsTable, exportJobEntity, {
29
30
  });
30
31
  const REQUEST_EXPORT_REASON = "export jobs are keyed by userId across all of the user's tenant memberships, not the caller's current tenant";
31
32
  /**
32
- * Race-Loss-Detection: createEventStoreExecutor.create catched 23505
33
- * intern + returnt `WriteFailure(UniqueViolationError)`, **kein throw**.
34
- * Wir checken den Failure-Code + constraintName um den App-side-vs-Race-
35
- * Pfad zu unterscheiden. Andere Failures (validation, version-conflict,
36
- * ...) propagieren unveraendert.
33
+ * `createEventStoreExecutor.create` catches 23505 internally and returns
34
+ * `WriteFailure(UniqueViolationError)` rather than throwing. Check the
35
+ * failure code and constraintName to distinguish the app-side and race
36
+ * paths; propagate other failures (validation, version conflicts, ...)
37
+ * unchanged.
37
38
  */
38
39
  function isActiveJobConflict(failure) {
39
40
  const error = failure.error; // @cast-boundary error-details
@@ -62,9 +63,9 @@ export const requestExportWrite = defineWriteHandler({
62
63
  // TenantDb-Wrapper would hide cross-tenant jobs.
63
64
  const existing = await findActiveJob(exportJobRunner, userId);
64
65
  if (existing) {
65
- // Snapshot-Status (kann zwischen fetchOne + Response stale werden
66
- // wenn Worker parallel den State flippt; window minimal). User
67
- // pollt fuer Live-Wahrheit ueber export-status.query.
66
+ // The returned status is a snapshot and can become stale between fetchOne
67
+ // and the response if the worker changes the state concurrently. The
68
+ // window is minimal; clients poll export-status.query for live status.
68
69
  return {
69
70
  isSuccess: true,
70
71
  data: {
@@ -74,9 +75,9 @@ export const requestExportWrite = defineWriteHandler({
74
75
  },
75
76
  };
76
77
  }
77
- // Kein active Job — neuen anlegen via crud.create. requestedFromTenantId
78
- // = aktueller Tenant des Users; Worker liest sein Compliance-Profile
79
- // aus diesem Tenant.
78
+ // No active job exists, so create one through crud.create. Persist the
79
+ // user's current tenant in requestedFromTenantId so the worker reads the
80
+ // compliance profile from that tenant.
80
81
  const result = await crud.create({
81
82
  userId,
82
83
  requestedFromTenantId: event.user.tenantId,
@@ -84,16 +85,16 @@ export const requestExportWrite = defineWriteHandler({
84
85
  tenantId: event.user.tenantId,
85
86
  }, event.user, ctx.db);
86
87
  if (!result.isSuccess) {
87
- // Race-Pfad: paralleler Klick hat zwischen findActiveJob + crud.create
88
- // einen aktiven Job angelegt → UniqueViolationError mit unserem
89
- // Constraint. Re-fetch + return existing als isExisting=true.
90
- // Andere Failures (validation, version-conflict, ...) propagieren.
88
+ // A parallel click may create an active job between findActiveJob and
89
+ // crud.create, causing UniqueViolationError for our constraint. Re-fetch
90
+ // and return the existing job with isExisting=true. Propagate other
91
+ // failures (validation, version conflicts, ...) unchanged.
91
92
  if (isActiveJobConflict(result)) {
92
93
  const winner = await findActiveJob(exportJobRunner, userId);
93
94
  if (!winner) {
94
- // Sollte nie passieren — Constraint-Violation ohne existing
95
- // active Job hiesse der Constraint matcht etwas anderes.
96
- // Original-Failure zurueckgeben damit das auffaellt.
95
+ // This should be impossible: a constraint violation without an existing
96
+ // active job would mean the constraint matched something else.
97
+ // Return the original failure so the inconsistency is visible.
97
98
  return result;
98
99
  }
99
100
  return {
@@ -107,17 +108,17 @@ export const requestExportWrite = defineWriteHandler({
107
108
  }
108
109
  return result;
109
110
  }
110
- // Happy path: neuer Job. SaveContext.id ist EntityId (number | string);
111
- // exportJobEntity hat idType:"uuid" → garantiert string, String()
112
- // schuetzt vor Drift falls jemand die Entity auf serial migriert.
111
+ // SaveContext.id is EntityId (number | string), while exportJobEntity has
112
+ // idType:"uuid" and therefore guarantees a string. String() protects
113
+ // against drift if the entity is migrated to serial.
113
114
  const created = result.data; // @cast-boundary engine-payload
114
115
  return {
115
116
  isSuccess: true,
116
117
  data: {
117
118
  jobId: String(created.id),
118
- // Snapshot: just-created → pending. Live-Wahrheit kommt ueber
119
- // export-status.query, status hier ist nice-to-have fuer das
120
- // initial UI-Render ("Anfrage angenommen, currently pending").
119
+ // This is a snapshot: a just-created job is pending. Live status comes
120
+ // from export-status.query; this value is only a convenience for the
121
+ // initial UI render ("Anfrage angenommen, currently pending").
121
122
  status: EXPORT_JOB_STATUS.Pending,
122
123
  isExisting: false,
123
124
  },
@@ -5,15 +5,16 @@ import { USER_STATUS, userTable } from "../../user/index.js";
5
5
  import { denyIfTargetOutsideAdminTenant } from "../lib/deny-if-target-outside-admin-tenant.js";
6
6
  import { isAdminActor } from "../lib/is-admin-actor.js";
7
7
  import { updateUserLifecycle } from "../lib/update-user-lifecycle.js";
8
- // POST /api/user/restrict (S2.U6) — DSGVO Art. 18 Account-Freeze.
9
- // Flippt status=Active → Restricted und revoked alle live sessions
10
- // des Users via cross-feature ctx.writeAs(sessions.revokeAllForUser).
8
+ // POST /api/user/restrict — GDPR Art. 18 account freeze.
9
+ // Flips status=Active → Restricted and revokes all live sessions
10
+ // for the user via cross-feature ctx.writeAs(sessions.revokeAllForUser).
11
11
  //
12
- // Plan-Doc-Verhalten ("Schreib-API geblockt"):
13
- // - Login geblockt: login.write.ts checked status=Restricted (Atom 3).
14
- // - Active sessions: revoked durch cross-feature-call (sessions-feature
15
- // muss gemountet sein). App-Author ohne sessions-feature kriegt einen
16
- // Boot-Resolver-Error via r.usesApi("sessions.revokeAllForUser").
12
+ // Write API behaviour:
13
+ // - Login is blocked: login.write.ts checks status=Restricted (Atom 3).
14
+ // - Active sessions are revoked through a cross-feature call (the
15
+ // sessions feature must be mounted). An app author without the
16
+ // sessions feature gets a boot resolver error via
17
+ // r.usesApi("sessions.revokeAllForUser").
17
18
  //
18
19
  // Self-service by default (userId omitted → event.user.id). An admin can
19
20
  // also target someone else's account — needed once a user is already
@@ -22,14 +23,16 @@ import { updateUserLifecycle } from "../lib/update-user-lifecycle.js";
22
23
  // themselves; only an operator path reaches it at that point.
23
24
  //
24
25
  // Tenant scope: `isAdminActor` accepts access.admin, which includes TenantAdmin
25
- // (tenant-scoped) even though the User-entity is global — see user-data-rights.md "Cross-Tenant-Semantik". Without a membership check, a TenantAdmin from tenant A could restrict/unrestrict a user who
26
- // has never been a member of tenant A. Only SystemAdmin (platform-wide)
27
- // skips the check; the target must have a membership row in the acting
28
- // admin's `event.user.tenantId` (row existence only — no active-status field).
26
+ // (tenant-scoped) even though the User entity is global — see user-data-rights.md
27
+ // "Cross-Tenant-Semantik". Without a membership check, a TenantAdmin from tenant A
28
+ // could restrict or unrestrict a user who has never been a member of tenant A.
29
+ // Only SystemAdmin (platform-wide) skips the check; the target must have a
30
+ // membership row in the acting admin's `event.user.tenantId` (row existence only —
31
+ // no active-status field).
29
32
  //
30
- // State-Transitions:
31
- // Active → Restricted ✓ (dieser Handler)
32
- // Restricted → Restricted ✗ 422 already_restricted (Idempotenz-Guard)
33
+ // State transitions:
34
+ // Active → Restricted ✓ (this handler)
35
+ // Restricted → Restricted ✗ 422 already_restricted (idempotency guard)
33
36
  // DeletionRequested → ... ✗ 422 user_not_in_active_state
34
37
  // Deleted → ... ✗ 422 user_not_in_active_state
35
38
  export const restrictAccountWrite = defineWriteHandler({
@@ -83,10 +86,10 @@ export const restrictAccountWrite = defineWriteHandler({
83
86
  }));
84
87
  }
85
88
  await updateUserLifecycle(ctx.db.unsafeRaw(), targetUserId, { status: USER_STATUS.Restricted });
86
- // Cross-Feature: alle live sessions revoken — sonst koennte der User
87
- // mit existierendem JWT bis zur Token-Expiry weiter schreiben.
88
- // ctx.writeAs(systemUser, ...) damit der privileged-Handler die
89
- // System-User-Roles im access-gate hat.
89
+ // Cross-feature: all live sessions are revoked; otherwise the user could
90
+ // continue writing with an existing JWT until token expiry.
91
+ // ctx.writeAs(systemUser, ...) gives the privileged handler the
92
+ // System user roles required by its access gate.
90
93
  const systemUser = createSystemUser(event.user.tenantId);
91
94
  await ctx.writeAs(systemUser, "sessions:write:user-session:revoke-all-for-user", {
92
95
  userId: targetUserId,
@@ -1,14 +1,14 @@
1
- // POST /userDataRights/run-forget-cleanup (S2.U5b).
1
+ // POST /userDataRights/run-forget-cleanup.
2
2
  //
3
- // Cron-Trigger fuer den Forget-Cleanup-Pipeline. Der Handler wrapt nur
4
- // `runForgetCleanup` damit er via dispatcher (System-User) aufrufbar
5
- // wird — die Pipeline-Logik selbst lebt im pure-function Modul
6
- // `run-forget-cleanup.ts` (testbar ohne dispatcher).
3
+ // Cron trigger for the forget-cleanup pipeline. The handler only wraps
4
+ // `runForgetCleanup` so the dispatcher can invoke it as the system user;
5
+ // the pipeline logic itself lives in the pure-function module
6
+ // `run-forget-cleanup.ts`, which can be tested without the dispatcher.
7
7
  //
8
- // Access: privileged — nur System-Caller (cron, ops-script). Im Cron-
9
- // Setup laeuft der Job mit `createSystemUser(...)` als executor.
8
+ // Access: privileged — only system callers (cron, ops script). In the cron
9
+ // setup, the job runs with `createSystemUser(...)` as executor.
10
10
  //
11
- // Rueckgabe: Stats fuer Operator-Monitoring (processed-count, error-list).
11
+ // Returns stats for operator monitoring (processed count, error list).
12
12
  import { access, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
13
13
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
14
14
  import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
@@ -2,17 +2,15 @@ export { deletionTokenSecretEnvSchema } from "./env.js";
2
2
  export { createUserDataRightsFeature } from "./feature.js";
3
3
  export { denyIfTargetOutsideAdminTenant, TARGET_USER_NOT_IN_ADMIN_TENANT, } from "./lib/deny-if-target-outside-admin-tenant.js";
4
4
  export { isSystemAdminActor } from "./lib/is-admin-actor.js";
5
- // #494 Bestandsdaten-Reconcile — Apps rufen das einmalig vor dem Re-Enable
6
- // von read_users-Rebuilds (siehe lib-Doc).
5
+ // Reconcile existing data once before re-enabling read_users rebuilds.
6
+ // See the library documentation for the required procedure.
7
7
  export { backfillUserLifecycleEvents, updateUserLifecycle } from "./lib/update-user-lifecycle.js";
8
- // Runner-Exports — App-Tests dürfen export/forget deterministisch laufen
9
- // lassen, statt über den Job-Cron zu warten (siehe sample
10
- // user-data-rights-demo).
11
- // Shared retention→strategy mapping (single source of truth per its own
12
- // doc comment) — other EXT_USER_DATA delete hooks that must independently
13
- // consult a DIFFERENT entity's retention (e.g. notes-history-user-data's
14
- // host-entity check) reuse this instead of re-deriving the anonymize/delete
15
- // split.
8
+ // Exported so app tests can run export/forget deterministically instead of
9
+ // waiting for the job cron.
10
+ // Shared retention-to-strategy mapping: other EXT_USER_DATA delete hooks that
11
+ // independently consult a DIFFERENT entity's retention (for example,
12
+ // notes-history-user-data's host-entity check) reuse this instead of
13
+ // re-deriving the anonymize/delete split.
16
14
  export { policyToStrategy, runForgetCleanup } from "./run-forget-cleanup.js";
17
15
  export { runUserExport } from "./run-user-export.js";
18
16
  export { downloadAttemptEntity, downloadAttemptsTable } from "./schema/download-attempt.js";
@@ -93,9 +93,9 @@ function emailChannelOf(registry) {
93
93
  }
94
94
  export function makeDefaultDeletionExecutedEmail(deps, defaults = {}) {
95
95
  return async (args) => {
96
- // Der User ist global, der Mail-Transport per-Tenant — wir senden ueber den
97
- // Transport des ersten Memberships. Orphan-User (0 Memberships) liefert
98
- // keine Tenant-Identitaet → kein Transport aufloesbar, Mail entfaellt.
96
+ // The user is global, but the mail transport is tenant-specific, so use the
97
+ // first membership's transport. An orphan user has no tenant identity, so no
98
+ // transport can be resolved and the mail is omitted.
99
99
  const tenantId = args.tenantIds[0];
100
100
  if (tenantId === undefined) {
101
101
  // skip: orphan user has no tenant whose transport could send the mail
@@ -2,20 +2,17 @@ import { createEventStoreExecutor, createTenantDb, selectMany, } from "@cosmicdr
2
2
  import { createSystemUser, SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-framework/engine";
3
3
  import { InternalError } from "@cosmicdrift/kumiko-framework/errors";
4
4
  import { USER_STATUS, userEntity, userTable } from "../../user/index.js";
5
- // #494 — Lifecycle-Mutationen der user-Entity MUESSEN als `user.updated`-Event
6
- // laufen. Roh per updateMany geschrieben, wischt ein read_users-Rebuild sie
7
- // weg (er replayt nur `user.created` -> status faellt auf den Default zurueck;
8
- // gracePeriodEnd/pendingDeletionRequestId/Deleted gehen verloren = DSGVO-
9
- // Datenverlust).
5
+ // Lifecycle mutations of the user entity MUST be emitted as `user.updated` events.
6
+ // Writing them directly with updateMany causes a read_users rebuild to erase them
7
+ // (it replays only `user.created`, so status falls back to its default;
8
+ // gracePeriodEnd/pendingDeletionRequestId/Deleted are lost, causing GDPR data loss).
10
9
  //
11
- // Das Event MUSS in denselben (tenant_id, aggregate_id)-Stream wie
12
- // `user.created` landen, sonst splittet das Aggregat ueber Tenants und der
13
- // Rebuild rekonstruiert nichts. Die user-Entity laeuft `r.systemScope()`, ihre
14
- // Events landen aber auf einem konkreten Tenant-Stream (siehe
15
- // auth-email-password/stream-tenant.ts; Root-Cause-Fix tracked in #497). Darum:
16
- // Rescope auf den Stream-Tenant des Users — den des `user.created`-Events,
17
- // NICHT `event.user.tenantId` (das ist der aktive Tenant zur Lifecycle-Zeit und
18
- // kann abweichen).
10
+ // The event MUST use the same (tenant_id, aggregate_id) stream as `user.created`,
11
+ // otherwise the aggregate is split across tenants and cannot be reconstructed.
12
+ // The user entity runs under `r.systemScope()`, but its events use a concrete
13
+ // tenant stream (see auth-email-password/stream-tenant.ts). Therefore, rescope to
14
+ // the user's stream tenant—the tenant of the `user.created` event—not
15
+ // `event.user.tenantId`, which is the active tenant at lifecycle time and may differ.
19
16
  const userExecutor = createEventStoreExecutor(userTable, userEntity, { entityName: "user" });
20
17
  // `conn` is ctx.db.unsafeRaw() (regular handlers) or the open tx
21
18
  // (forget-cleanup sub-tx) — keeps the event append atomic with the write.
@@ -29,10 +26,10 @@ const userExecutor = createEventStoreExecutor(userTable, userEntity, { entityNam
29
26
  // throws — those callers never checked a return value, so silently dropping
30
27
  // their write would be silent data loss.
31
28
  export async function updateUserLifecycle(conn, userId, changes, options) {
32
- // user ist systemStream (#497): der Executor-Choke-Point addressiert den
33
- // Stream immer auf SYSTEM_TENANT_ID — ein Rescope auf die row-tenant_id
34
- // waere wirkungslos. "system"-Mode, damit loadById auch Legacy-Rows findet,
35
- // deren tenant_id noch vor dem #762-Backfill-Rebuild steht.
29
+ // The user is a system stream: the executor choke point always addresses the
30
+ // stream through SYSTEM_TENANT_ID; rescoping to row-tenant_id would have no
31
+ // effect. Use "system" mode so loadById also finds legacy rows whose tenant_id
32
+ // predates the backfill rebuild.
36
33
  // skipOptimisticLock: every caller is a server-side business transition
37
34
  // (restrict/lift-restriction/grace-period/cancel/forget) that holds no row
38
35
  // version to pass as `payload.version`, which update() requires otherwise.