@cosmicdrift/kumiko-bundled-features 0.386.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 (469) hide show
  1. package/LICENSE +21 -57
  2. package/dist/agent-tools/tool-catalog.js +1 -1
  3. package/dist/audit/screens.js +1 -1
  4. package/dist/auth-email-password/feature.js +1 -1
  5. package/dist/auth-email-password/handlers/change-password.write.js +3 -3
  6. package/dist/auth-email-password/handlers/confirm-token-flow.js +5 -5
  7. package/dist/auth-email-password/handlers/invite-accept-with-login.write.js +1 -1
  8. package/dist/auth-email-password/handlers/invite-accept.write.js +18 -18
  9. package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
  10. package/dist/auth-email-password/handlers/invite-create.write.js +10 -10
  11. package/dist/auth-email-password/handlers/invite-info.query.js +1 -1
  12. package/dist/auth-email-password/handlers/invite-signup-complete.write.js +24 -26
  13. package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
  14. package/dist/auth-email-password/handlers/login.write.js +1 -1
  15. package/dist/auth-email-password/handlers/self-registration-status.query.js +1 -1
  16. package/dist/auth-email-password/handlers/signup-confirm.write.js +34 -37
  17. package/dist/auth-email-password/handlers/signup-request.write.js +6 -7
  18. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
  19. package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.js +1 -4
  20. package/dist/auth-email-password/index.js +5 -5
  21. package/dist/auth-email-password/lockout-store.js +1 -1
  22. package/dist/auth-email-password/seeding.d.ts +42 -45
  23. package/dist/auth-email-password/seeding.js +51 -53
  24. package/dist/auth-email-password/signup-token-store.js +8 -8
  25. package/dist/auth-email-password/testing.js +3 -3
  26. package/dist/auth-email-password/web/auth-client.d.ts +2 -2
  27. package/dist/auth-email-password/web/auth-client.js +36 -37
  28. package/dist/auth-email-password/web/auth-form-primitives.js +10 -10
  29. package/dist/auth-email-password/web/auth-gate.js +15 -16
  30. package/dist/auth-email-password/web/client-plugin.d.ts +7 -7
  31. package/dist/auth-email-password/web/client-plugin.js +4 -5
  32. package/dist/auth-email-password/web/confirm-account-unlock-screen.js +1 -1
  33. package/dist/auth-email-password/web/constants.js +3 -3
  34. package/dist/auth-email-password/web/default-topbar-actions.d.ts +8 -8
  35. package/dist/auth-email-password/web/default-topbar-actions.js +6 -6
  36. package/dist/auth-email-password/web/forgot-password-screen.d.ts +2 -2
  37. package/dist/auth-email-password/web/forgot-password-screen.js +9 -9
  38. package/dist/auth-email-password/web/index.js +5 -5
  39. package/dist/auth-email-password/web/invite-accept-screen.d.ts +1 -1
  40. package/dist/auth-email-password/web/invite-accept-screen.js +16 -16
  41. package/dist/auth-email-password/web/login-screen.d.ts +1 -1
  42. package/dist/auth-email-password/web/login-screen.js +2 -3
  43. package/dist/auth-email-password/web/reset-password-screen.d.ts +4 -4
  44. package/dist/auth-email-password/web/reset-password-screen.js +12 -13
  45. package/dist/auth-email-password/web/session.d.ts +10 -9
  46. package/dist/auth-email-password/web/session.js +28 -29
  47. package/dist/auth-email-password/web/signup-complete-screen.js +3 -3
  48. package/dist/auth-email-password/web/signup-screen.d.ts +1 -1
  49. package/dist/auth-email-password/web/signup-screen.js +13 -13
  50. package/dist/auth-email-password/web/tenant-switcher.d.ts +4 -4
  51. package/dist/auth-email-password/web/tenant-switcher.js +21 -22
  52. package/dist/auth-email-password/web/use-shell-user.js +12 -13
  53. package/dist/auth-email-password/web/user-menu.d.ts +4 -4
  54. package/dist/auth-email-password/web/user-menu.js +12 -13
  55. package/dist/auth-email-password/web/verify-email-screen.d.ts +2 -2
  56. package/dist/auth-email-password/web/verify-email-screen.js +9 -10
  57. package/dist/auth-foundation/boot-checks.js +4 -4
  58. package/dist/auth-foundation/resolve-anonymous-access.d.ts +1 -1
  59. package/dist/auth-foundation/resolve-anonymous-access.js +3 -3
  60. package/dist/auth-foundation/types.js +2 -2
  61. package/dist/auth-mfa/handlers/disable.write.js +3 -3
  62. package/dist/auth-mfa/handlers/enable-confirm-preauth.write.js +4 -4
  63. package/dist/auth-mfa/handlers/enable-confirm.write.js +2 -2
  64. package/dist/auth-mfa/handlers/enable-start-preauth.write.js +1 -1
  65. package/dist/auth-mfa/handlers/reencrypt.job.js +1 -1
  66. package/dist/auth-mfa/handlers/regenerate-recovery.write.js +5 -5
  67. package/dist/auth-mfa/handlers/verify.write.js +1 -1
  68. package/dist/auth-mfa/token-secrets.js +1 -1
  69. package/dist/auth-mfa/web/client-plugin.d.ts +1 -1
  70. package/dist/auth-mfa/web/client-plugin.js +1 -1
  71. package/dist/auth-mfa/web/i18n.js +3 -3
  72. package/dist/auth-mfa/web/index.js +4 -4
  73. package/dist/auth-mfa/web/mfa-client.js +17 -16
  74. package/dist/auth-mfa/web/mfa-verify-screen.js +6 -6
  75. package/dist/billing-foundation/aggregate-id.d.ts +5 -5
  76. package/dist/billing-foundation/aggregate-id.js +10 -11
  77. package/dist/billing-foundation/entities.js +27 -27
  78. package/dist/billing-foundation/events.js +18 -17
  79. package/dist/billing-foundation/feature.js +42 -43
  80. package/dist/billing-foundation/get-subscription-for-tenant.d.ts +3 -3
  81. package/dist/billing-foundation/get-subscription-for-tenant.js +3 -5
  82. package/dist/billing-foundation/handlers/create-checkout-session.write.js +18 -17
  83. package/dist/billing-foundation/handlers/create-portal-session.write.js +11 -12
  84. package/dist/billing-foundation/handlers/list-subscriptions.query.js +4 -4
  85. package/dist/billing-foundation/handlers/process-event.write.js +20 -20
  86. package/dist/billing-foundation/projection.d.ts +15 -11
  87. package/dist/billing-foundation/projection.js +38 -37
  88. package/dist/billing-foundation/subscription-tier-sync.js +3 -3
  89. package/dist/billing-foundation/tenant-destroy-hook.d.ts +2 -2
  90. package/dist/billing-foundation/tenant-destroy-hook.js +7 -7
  91. package/dist/billing-foundation/types.d.ts +40 -41
  92. package/dist/billing-foundation/types.js +20 -20
  93. package/dist/billing-foundation/web/billing-plans-panel.js +4 -4
  94. package/dist/cap-counter/aggregate-id.js +8 -9
  95. package/dist/cap-counter/constants.js +11 -12
  96. package/dist/cap-counter/enforce-cap.d.ts +59 -62
  97. package/dist/cap-counter/enforce-cap.js +47 -48
  98. package/dist/cap-counter/entity.js +29 -29
  99. package/dist/cap-counter/feature.js +34 -35
  100. package/dist/cap-counter/handlers/increment-rolling.write.d.ts +2 -2
  101. package/dist/cap-counter/handlers/increment-rolling.write.js +31 -31
  102. package/dist/cap-counter/handlers/mark-soft-warned.write.js +4 -5
  103. package/dist/cap-counter/stock-cap-guard.js +1 -1
  104. package/dist/cap-counter/with-cap-enforcement.d.ts +3 -5
  105. package/dist/channel-email/smtp-transport.d.ts +18 -17
  106. package/dist/channel-email/smtp-transport.js +24 -21
  107. package/dist/channel-in-app/handlers/unread-count.query.js +3 -4
  108. package/dist/compliance-profiles/feature.js +4 -4
  109. package/dist/compliance-profiles/handlers/for-tenant.query.js +3 -6
  110. package/dist/compliance-profiles/handlers/list-profiles.query.js +5 -5
  111. package/dist/compliance-profiles/handlers/needs-profile.query.js +4 -4
  112. package/dist/compliance-profiles/handlers/set-profile.write.js +13 -14
  113. package/dist/compliance-profiles/handlers/sub-processors.query.js +9 -11
  114. package/dist/compliance-profiles/resolve-for-tenant.js +7 -7
  115. package/dist/compliance-profiles/schema/profile-selection.js +18 -23
  116. package/dist/compliance-profiles/seeding.js +14 -15
  117. package/dist/compliance-profiles-ops/handlers/tenants-missing-profile.query.js +3 -3
  118. package/dist/compliance-profiles-ops/index.js +2 -2
  119. package/dist/config/handlers/readiness.query.d.ts +4 -4
  120. package/dist/config/handlers/readiness.query.js +1 -1
  121. package/dist/config/handlers/reencrypt.job.js +4 -5
  122. package/dist/config/handlers/set.write.js +4 -4
  123. package/dist/config/resolver.js +4 -4
  124. package/dist/config/table.js +10 -10
  125. package/dist/config/write-helpers.js +1 -1
  126. package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +2 -2
  127. package/dist/crypto-shredding/handlers/forget-subject.write.js +12 -11
  128. package/dist/custom-fields/aggregate-id.d.ts +12 -13
  129. package/dist/custom-fields/aggregate-id.js +16 -17
  130. package/dist/custom-fields/entity.js +49 -47
  131. package/dist/custom-fields/events.js +7 -8
  132. package/dist/custom-fields/feature.d.ts +14 -14
  133. package/dist/custom-fields/feature.js +53 -54
  134. package/dist/custom-fields/handlers/clear-custom-field.write.d.ts +3 -2
  135. package/dist/custom-fields/handlers/clear-custom-field.write.js +9 -8
  136. package/dist/custom-fields/handlers/define-tenant-field.write.d.ts +1 -1
  137. package/dist/custom-fields/handlers/define-tenant-field.write.js +2 -2
  138. package/dist/custom-fields/handlers/delete-system-field.write.js +6 -7
  139. package/dist/custom-fields/handlers/delete-tenant-field.write.d.ts +1 -1
  140. package/dist/custom-fields/handlers/delete-tenant-field.write.js +3 -3
  141. package/dist/custom-fields/handlers/set-custom-field.write.d.ts +3 -3
  142. package/dist/custom-fields/handlers/set-custom-field.write.js +25 -28
  143. package/dist/custom-fields/handlers/update-tenant-field.write.d.ts +1 -1
  144. package/dist/custom-fields/handlers/update-tenant-field.write.js +1 -1
  145. package/dist/custom-fields/lib/field-access.js +2 -2
  146. package/dist/custom-fields/lib/parse-serialized-field.js +1 -1
  147. package/dist/custom-fields/lib/quota.js +1 -1
  148. package/dist/custom-fields/lib/value-schema.js +10 -12
  149. package/dist/custom-fields/run-retention.js +3 -3
  150. package/dist/custom-fields/schemas.js +14 -14
  151. package/dist/custom-fields/web/client-plugin.js +2 -5
  152. package/dist/custom-fields/web/constants.js +2 -2
  153. package/dist/custom-fields/web/custom-fields-form-section.d.ts +4 -4
  154. package/dist/custom-fields/web/custom-fields-form-section.js +22 -22
  155. package/dist/custom-fields/wire-for-entity.js +65 -67
  156. package/dist/custom-fields/wire-user-data-rights.js +3 -3
  157. package/dist/data-retention/_internal/parse-override.js +2 -3
  158. package/dist/data-retention/feature.js +11 -18
  159. package/dist/data-retention/handlers/policy-for.query.js +6 -6
  160. package/dist/data-retention/keep-for.d.ts +7 -7
  161. package/dist/data-retention/keep-for.js +15 -15
  162. package/dist/data-retention/override-schema.d.ts +3 -4
  163. package/dist/data-retention/override-schema.js +13 -15
  164. package/dist/data-retention/presets.d.ts +4 -5
  165. package/dist/data-retention/presets.js +18 -23
  166. package/dist/data-retention/resolve-tenant-preset.js +17 -16
  167. package/dist/data-retention/resolver.d.ts +12 -12
  168. package/dist/data-retention/resolver.js +24 -23
  169. package/dist/data-retention/run-retention-cleanup.d.ts +8 -3
  170. package/dist/data-retention/run-retention-cleanup.js +61 -51
  171. package/dist/data-retention/schema/tenant-retention-override.js +13 -11
  172. package/dist/delivery/feature.js +2 -2
  173. package/dist/delivery/handlers/log.query.js +1 -1
  174. package/dist/delivery/tables.js +9 -8
  175. package/dist/delivery/unsubscribe.js +4 -4
  176. package/dist/document-ingest-foundation/entity.js +4 -4
  177. package/dist/document-ingest-foundation/events.js +2 -2
  178. package/dist/document-ingest-foundation/feature.js +2 -2
  179. package/dist/document-ingest-foundation/pages.js +1 -1
  180. package/dist/document-ingest-foundation/tenant-destroy-hook.js +4 -4
  181. package/dist/feature-toggles/compose-tier-resolver.js +1 -1
  182. package/dist/feature-toggles/feature.js +1 -1
  183. package/dist/feature-toggles/global-feature-state-table.js +1 -1
  184. package/dist/feature-toggles/handlers/registered.query.js +5 -5
  185. package/dist/feature-toggles/toggle-sync-signal.js +1 -1
  186. package/dist/feature-toggles/web/constants.js +1 -1
  187. package/dist/file-derivatives/feature.d.ts +1 -1
  188. package/dist/file-derivatives/feature.js +1 -1
  189. package/dist/file-derivatives/handlers/public-variant.query.js +1 -1
  190. package/dist/file-derivatives/presets.js +1 -1
  191. package/dist/file-foundation/feature.js +6 -6
  192. package/dist/file-provider-inmemory/feature.d.ts +1 -1
  193. package/dist/file-provider-inmemory/feature.js +16 -16
  194. package/dist/file-provider-s3/feature.js +16 -16
  195. package/dist/file-provider-s3/lib/s3-provider.js +6 -6
  196. package/dist/files/feature.js +6 -6
  197. package/dist/files-tenant-data/handlers/sweep-orphaned-derivatives.job.js +4 -4
  198. package/dist/files-tenant-data/hooks.js +24 -26
  199. package/dist/files-tenant-data/index.js +1 -1
  200. package/dist/folders/feature.d.ts +1 -1
  201. package/dist/folders/web/folder-manager.js +2 -2
  202. package/dist/folders/web/tree.js +5 -5
  203. package/dist/form-draft/db/queries/cleanup.js +1 -1
  204. package/dist/form-draft/db/queries/owned-file-refs.js +1 -1
  205. package/dist/form-draft/entity.js +3 -3
  206. package/dist/form-draft/feature.js +4 -5
  207. package/dist/form-draft/handlers/discard.write.js +1 -1
  208. package/dist/form-draft/release-file-refs.js +6 -6
  209. package/dist/form-draft/schemas.js +3 -3
  210. package/dist/form-draft/web/constants.js +0 -2
  211. package/dist/inbound-mail-foundation/aggregate-id.d.ts +13 -13
  212. package/dist/inbound-mail-foundation/aggregate-id.js +19 -19
  213. package/dist/inbound-mail-foundation/connect-routes.js +4 -3
  214. package/dist/inbound-mail-foundation/constants.d.ts +22 -24
  215. package/dist/inbound-mail-foundation/constants.js +30 -33
  216. package/dist/inbound-mail-foundation/entities.d.ts +12 -12
  217. package/dist/inbound-mail-foundation/entities.js +47 -48
  218. package/dist/inbound-mail-foundation/events.d.ts +4 -3
  219. package/dist/inbound-mail-foundation/events.js +50 -47
  220. package/dist/inbound-mail-foundation/feature.js +39 -39
  221. package/dist/inbound-mail-foundation/handlers/account-state.js +8 -8
  222. package/dist/inbound-mail-foundation/handlers/connect-account.write.js +25 -26
  223. package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +7 -7
  224. package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +50 -51
  225. package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +8 -8
  226. package/dist/inbound-mail-foundation/handlers/list-messages.query.js +10 -10
  227. package/dist/inbound-mail-foundation/handlers/scope-visibility.js +3 -4
  228. package/dist/inbound-mail-foundation/handlers/update-account.write.js +11 -11
  229. package/dist/inbound-mail-foundation/oauth-state.d.ts +5 -5
  230. package/dist/inbound-mail-foundation/oauth-state.js +11 -10
  231. package/dist/inbound-mail-foundation/projection.d.ts +4 -4
  232. package/dist/inbound-mail-foundation/projection.js +31 -29
  233. package/dist/inbound-mail-foundation/provider-factory.d.ts +4 -4
  234. package/dist/inbound-mail-foundation/provider-factory.js +9 -9
  235. package/dist/inbound-mail-foundation/retention-sweep.d.ts +5 -3
  236. package/dist/inbound-mail-foundation/retention-sweep.js +38 -36
  237. package/dist/inbound-mail-foundation/tenant-destroy-hook.js +14 -16
  238. package/dist/inbound-mail-foundation/types.d.ts +45 -46
  239. package/dist/inbound-mail-foundation/types.js +21 -21
  240. package/dist/inbound-mail-foundation/watch-supervisor.d.ts +10 -10
  241. package/dist/inbound-mail-foundation/watch-supervisor.js +57 -56
  242. package/dist/inbound-provider-imap/credential-document.js +13 -13
  243. package/dist/inbound-provider-imap/feature.d.ts +2 -2
  244. package/dist/inbound-provider-imap/feature.js +42 -40
  245. package/dist/inbound-provider-imap/imap-client.d.ts +12 -11
  246. package/dist/inbound-provider-imap/imap-client.js +20 -19
  247. package/dist/inbound-provider-inmemory/feature.d.ts +9 -9
  248. package/dist/inbound-provider-inmemory/feature.js +19 -19
  249. package/dist/jobs/db/queries/retention.js +2 -2
  250. package/dist/jobs/db/queries/stale-run-sweep.js +3 -3
  251. package/dist/jobs/events.js +1 -1
  252. package/dist/jobs/feature.js +5 -6
  253. package/dist/jobs/handlers/detail.query.js +4 -4
  254. package/dist/jobs/handlers/list.query.js +1 -1
  255. package/dist/jobs/handlers/projection-rebuild.job.js +1 -1
  256. package/dist/jobs/handlers/reindex-entity.job.js +1 -1
  257. package/dist/jobs/handlers/retry.write.js +1 -1
  258. package/dist/jobs/job-instant.js +1 -1
  259. package/dist/jobs/job-run-logger.js +10 -11
  260. package/dist/jobs/job-run-table.js +3 -3
  261. package/dist/jobs/screens.js +1 -1
  262. package/dist/jobs/tenant-job-failure-table.js +1 -1
  263. package/dist/jobs/tenant-job-run-table.js +1 -1
  264. package/dist/ledger/entity.js +5 -5
  265. package/dist/ledger/feature.js +3 -3
  266. package/dist/ledger/handlers/confirm-schedule-period.write.js +3 -3
  267. package/dist/ledger/recurring.js +12 -12
  268. package/dist/ledger/schemas.js +1 -1
  269. package/dist/ledger/web/constants.js +2 -2
  270. package/dist/ledger/web/index.js +7 -7
  271. package/dist/legal-pages/feature.d.ts +4 -4
  272. package/dist/legal-pages/feature.js +25 -26
  273. package/dist/legal-pages/markdown.js +3 -3
  274. package/dist/legal-pages/web/client-plugin.js +23 -24
  275. package/dist/legal-pages/web/index.js +0 -1
  276. package/dist/mail-foundation/feature.d.ts +2 -2
  277. package/dist/mail-foundation/feature.js +24 -25
  278. package/dist/mail-transport-inmemory/feature.d.ts +4 -4
  279. package/dist/mail-transport-inmemory/feature.js +27 -28
  280. package/dist/mail-transport-smtp/feature.js +20 -20
  281. package/dist/managed-pages/branding.js +6 -6
  282. package/dist/managed-pages/feature.d.ts +26 -26
  283. package/dist/managed-pages/feature.js +34 -34
  284. package/dist/managed-pages/handlers/by-slug.query.js +5 -6
  285. package/dist/managed-pages/handlers/by-tenant-published.query.js +2 -2
  286. package/dist/managed-pages/handlers/set.write.js +5 -7
  287. package/dist/managed-pages/screens/page-screens.js +11 -11
  288. package/dist/managed-pages/seeding.js +8 -8
  289. package/dist/managed-pages/table.js +13 -12
  290. package/dist/managed-pages/web/client-plugin.d.ts +1 -1
  291. package/dist/managed-pages/web/client-plugin.js +5 -5
  292. package/dist/managed-pages/web/i18n.js +1 -1
  293. package/dist/notes-history/entity.js +4 -4
  294. package/dist/notes-history/feature.d.ts +2 -2
  295. package/dist/notes-history-user-data/hooks.js +1 -1
  296. package/dist/page-render/layout.js +9 -9
  297. package/dist/page-render/markdown.js +11 -11
  298. package/dist/page-render/security-headers.js +7 -6
  299. package/dist/personal-access-tokens/feature.js +5 -5
  300. package/dist/personal-access-tokens/roles.js +2 -2
  301. package/dist/readiness/handlers/status.query.js +3 -3
  302. package/dist/renderer-foundation/api.js +12 -13
  303. package/dist/renderer-foundation/constants.js +2 -2
  304. package/dist/renderer-foundation/feature.js +7 -7
  305. package/dist/secrets/feature.js +9 -9
  306. package/dist/secrets/web/constants.js +2 -2
  307. package/dist/seo/feature.js +3 -3
  308. package/dist/sessions/constants.d.ts +1 -1
  309. package/dist/sessions/constants.js +1 -1
  310. package/dist/sessions/feature.js +8 -8
  311. package/dist/sessions/handlers/revoke-all-for-user.write.js +2 -2
  312. package/dist/sessions/handlers/revoke-all-others.write.js +2 -2
  313. package/dist/sessions/handlers/revoke.write.js +1 -1
  314. package/dist/sessions/schema/user-session.js +4 -4
  315. package/dist/sessions/screens.js +2 -2
  316. package/dist/sessions/session-callbacks.js +2 -2
  317. package/dist/sessions/session-revoked-event.js +2 -2
  318. package/dist/shared/assert-no-where-rule-in-ownership-write.js +1 -1
  319. package/dist/shared/decrypt-stored-pii.js +1 -1
  320. package/dist/shared/encrypt-for-direct-write.js +1 -1
  321. package/dist/shared/map-with-concurrency.js +5 -4
  322. package/dist/shared/parent-visibility.js +2 -2
  323. package/dist/shared/password-hashing.js +1 -1
  324. package/dist/shared/signup-handover.js +1 -2
  325. package/dist/shared/single-use-token-store.js +1 -1
  326. package/dist/subscription-mollie/constants.js +15 -17
  327. package/dist/subscription-mollie/feature.d.ts +17 -18
  328. package/dist/subscription-mollie/feature.js +24 -24
  329. package/dist/subscription-mollie/index.js +3 -3
  330. package/dist/subscription-mollie/plugin-methods.d.ts +2 -2
  331. package/dist/subscription-mollie/plugin-methods.js +15 -14
  332. package/dist/subscription-mollie/verify-webhook.d.ts +10 -10
  333. package/dist/subscription-mollie/verify-webhook.js +27 -27
  334. package/dist/subscription-stripe/constants.js +4 -6
  335. package/dist/subscription-stripe/feature.d.ts +14 -14
  336. package/dist/subscription-stripe/feature.js +35 -34
  337. package/dist/subscription-stripe/index.js +6 -6
  338. package/dist/subscription-stripe/plugin-methods.js +18 -18
  339. package/dist/subscription-stripe/runtime.d.ts +1 -1
  340. package/dist/subscription-stripe/runtime.js +1 -1
  341. package/dist/subscription-stripe/verify-webhook.d.ts +11 -11
  342. package/dist/subscription-stripe/verify-webhook.js +59 -61
  343. package/dist/tags/feature.d.ts +3 -3
  344. package/dist/tags/screens.js +1 -1
  345. package/dist/template-resolver/api.js +10 -10
  346. package/dist/template-resolver/handlers/find-by-id.query.js +5 -5
  347. package/dist/template-resolver/handlers/list.query.js +1 -1
  348. package/dist/template-resolver/handlers/shared.js +2 -2
  349. package/dist/template-resolver/handlers/template-write.js +3 -3
  350. package/dist/template-resolver/handlers/upsert-system.write.js +3 -4
  351. package/dist/template-resolver/handlers/upsert-tenant.write.js +4 -5
  352. package/dist/template-resolver/seeding.js +4 -4
  353. package/dist/template-resolver/table.js +10 -11
  354. package/dist/template-resolver/web/client-plugin.js +2 -2
  355. package/dist/tenant/feature.js +7 -7
  356. package/dist/tenant/handlers/member-directory.query.js +1 -1
  357. package/dist/tenant/handlers/members.query.js +1 -1
  358. package/dist/tenant/handlers/team-list.query.js +1 -1
  359. package/dist/tenant/handlers/tenant-directory.query.js +1 -1
  360. package/dist/tenant/invitation-table.js +37 -40
  361. package/dist/tenant/membership-table.js +3 -3
  362. package/dist/tenant/schema/tenant.js +7 -9
  363. package/dist/tenant/screens.js +1 -1
  364. package/dist/tenant/seeding.d.ts +6 -5
  365. package/dist/tenant/seeding.js +12 -12
  366. package/dist/tenant/testing.js +5 -6
  367. package/dist/tenant/web/constants.js +2 -2
  368. package/dist/tenant-handover/events.js +5 -7
  369. package/dist/tenant-handover/feature.js +1 -1
  370. package/dist/tenant-handover/grant.js +1 -1
  371. package/dist/tenant-handover/handlers/claim.write.js +1 -1
  372. package/dist/tenant-handover/move-entity-graph.js +8 -9
  373. package/dist/tenant-handover/signup-handover-provider.js +1 -2
  374. package/dist/tenant-handover/transfer-graph.js +4 -5
  375. package/dist/tenant-lifecycle/boot-checks.js +1 -1
  376. package/dist/tenant-lifecycle/feature.js +1 -1
  377. package/dist/tenant-settings/constants.js +1 -1
  378. package/dist/tenant-settings/tenant-defaults.d.ts +1 -1
  379. package/dist/tenant-settings/tenant-defaults.js +9 -2
  380. package/dist/tier-engine/aggregate-id.d.ts +11 -11
  381. package/dist/tier-engine/aggregate-id.js +15 -16
  382. package/dist/tier-engine/compose-app.d.ts +14 -14
  383. package/dist/tier-engine/compose-app.js +1 -1
  384. package/dist/tier-engine/entity.js +18 -19
  385. package/dist/tier-engine/feature.d.ts +19 -17
  386. package/dist/tier-engine/feature.js +68 -69
  387. package/dist/tier-engine/handlers/active-tier.query.js +6 -7
  388. package/dist/tier-engine/handlers/get-tenant-tier.query.js +4 -4
  389. package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +5 -5
  390. package/dist/tier-engine/handlers/set-tenant-tier.write.js +3 -3
  391. package/dist/tier-engine/tier-resolver.js +2 -2
  392. package/dist/tier-engine/trial.js +8 -8
  393. package/dist/tier-engine/web/index.js +4 -4
  394. package/dist/user/db/queries/stream-tenant-backfill.js +8 -8
  395. package/dist/user/handlers/create.write.js +4 -4
  396. package/dist/user/schema/user.d.ts +11 -11
  397. package/dist/user/schema/user.js +45 -44
  398. package/dist/user/seeding.d.ts +15 -15
  399. package/dist/user/seeding.js +28 -28
  400. package/dist/user/testing.js +3 -3
  401. package/dist/user-data-rights/audit-download.d.ts +8 -8
  402. package/dist/user-data-rights/audit-download.js +19 -20
  403. package/dist/user-data-rights/boot-checks.js +1 -1
  404. package/dist/user-data-rights/deletion-token.js +1 -1
  405. package/dist/user-data-rights/feature.d.ts +49 -50
  406. package/dist/user-data-rights/feature.js +54 -53
  407. package/dist/user-data-rights/handlers/cancel-deletion.write.js +9 -9
  408. package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.js +8 -8
  409. package/dist/user-data-rights/handlers/download-by-job.query.js +29 -30
  410. package/dist/user-data-rights/handlers/download-by-token.query.js +40 -42
  411. package/dist/user-data-rights/handlers/export-status.query.js +8 -9
  412. package/dist/user-data-rights/handlers/lift-restriction.write.js +7 -8
  413. package/dist/user-data-rights/handlers/list-download-attempts.query.js +2 -2
  414. package/dist/user-data-rights/handlers/my-audit-log.query.js +4 -4
  415. package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +5 -5
  416. package/dist/user-data-rights/handlers/request-deletion-by-email.write.js +16 -15
  417. package/dist/user-data-rights/handlers/request-deletion.write.d.ts +2 -2
  418. package/dist/user-data-rights/handlers/request-deletion.write.js +7 -9
  419. package/dist/user-data-rights/handlers/request-export.write.js +42 -41
  420. package/dist/user-data-rights/handlers/restrict-account.write.js +22 -19
  421. package/dist/user-data-rights/handlers/run-forget-cleanup.write.js +8 -8
  422. package/dist/user-data-rights/index.js +8 -10
  423. package/dist/user-data-rights/lib/default-mailers.js +3 -3
  424. package/dist/user-data-rights/lib/update-user-lifecycle.js +14 -17
  425. package/dist/user-data-rights/run-export-jobs.d.ts +38 -42
  426. package/dist/user-data-rights/run-export-jobs.js +127 -233
  427. package/dist/user-data-rights/run-forget-cleanup.d.ts +16 -20
  428. package/dist/user-data-rights/run-forget-cleanup.js +63 -82
  429. package/dist/user-data-rights/run-user-export.d.ts +34 -33
  430. package/dist/user-data-rights/run-user-export.js +55 -57
  431. package/dist/user-data-rights/schema/download-attempt.js +11 -11
  432. package/dist/user-data-rights/schema/download-token.js +37 -41
  433. package/dist/user-data-rights/schema/export-job.d.ts +4 -4
  434. package/dist/user-data-rights/schema/export-job.js +65 -67
  435. package/dist/user-data-rights/token-helpers.d.ts +8 -9
  436. package/dist/user-data-rights/token-helpers.js +21 -25
  437. package/dist/user-data-rights/web/client-plugin.d.ts +5 -5
  438. package/dist/user-data-rights/web/client-plugin.js +1 -1
  439. package/dist/user-data-rights/web/confirm-deletion-screen.js +6 -5
  440. package/dist/user-data-rights/web/constants.js +1 -1
  441. package/dist/user-data-rights/web/index.js +5 -5
  442. package/dist/user-data-rights/web/privacy-center-screen.js +14 -13
  443. package/dist/user-data-rights/web/public-deletion-gate.d.ts +4 -4
  444. package/dist/user-data-rights/web/request-deletion-screen.js +6 -6
  445. package/dist/user-data-rights/zip-path.d.ts +15 -15
  446. package/dist/user-data-rights/zip-path.js +41 -40
  447. package/dist/user-data-rights-defaults/feature.js +15 -15
  448. package/dist/user-data-rights-defaults/hooks/delivery-attempt.userdata-hook.js +3 -5
  449. package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +45 -51
  450. package/dist/user-data-rights-defaults/hooks/job-run.userdata-hook.js +2 -2
  451. package/dist/user-data-rights-defaults/hooks/notification-preference.userdata-hook.js +1 -1
  452. package/dist/user-data-rights-defaults/hooks/user-session.userdata-hook.js +3 -3
  453. package/dist/user-data-rights-defaults/hooks/user.userdata-hook.js +32 -31
  454. package/dist/user-profile/handlers/change-email.write.js +13 -13
  455. package/dist/user-profile/index.js +3 -3
  456. package/dist/user-profile/web/client-plugin.js +1 -1
  457. package/dist/user-profile/web/constants.js +1 -1
  458. package/dist/user-profile/web/profile-screen.js +1 -1
  459. package/dist/workflow-runner/aggregate-id.d.ts +1 -1
  460. package/dist/workflow-runner/aggregate-id.js +1 -1
  461. package/dist/workflow-runner/event-subscriber.js +4 -5
  462. package/dist/workflow-runner/event-trigger.js +4 -17
  463. package/dist/workflow-runner/feature.js +2 -2
  464. package/dist/workflow-runner/handlers/resume-run.write.js +4 -4
  465. package/dist/workflow-runner/pending-projection.js +6 -7
  466. package/dist/workflow-runner/runner.js +6 -6
  467. package/dist/workflow-runner/tables.js +6 -6
  468. package/dist/workflow-runner/workflow-registry.js +1 -1
  469. package/package.json +10 -10
@@ -1,7 +1,7 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-renderer/headless";
3
3
  // Export section (Art. 20) — the one part of user-data-rights' privacy-center
4
- // screen that stays custom (fw#2312). Registered as an EditExtensionSection
4
+ // screen that stays custom. Registered as an EditExtensionSection
5
5
  // component (see web/client-plugin.tsx); the projectionDetail screen
6
6
  // (feature.ts) supplies the surrounding Section chrome (title, testId), so
7
7
  // this component renders only its own body content.
@@ -15,18 +15,19 @@ import { postWithDownload } from "@cosmicdrift/kumiko-renderer/web";
15
15
  import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
16
16
  import { useEffect, useState } from "react";
17
17
  import { EXPORT_JOB_STATUS, UserDataRightsHandlers, UserDataRightsQueries, } from "./constants.js";
18
- // Export-Job läuft async (worker-Lane-Cron, ~1 Min). Solange er pending/running
19
- // ist, pollt der Screen den Status, damit der Download ohne manuellen Reload
20
- // erscheint.
18
+ // The export job runs asynchronously (worker-Lane-Cron, ~1 Min). While it is
19
+ // pending/running, the screen polls its status so the download appears without
20
+ // a manual reload.
21
21
  const EXPORT_POLL_MS = 4000;
22
- // Dispatcher-Failures tragen i18nKey nur wenn der Handler einen setzt —
23
- // Boundary-Read mit generischem Fallback.
22
+ // Dispatcher failures include i18nKey only when the handler sets one; read it
23
+ // at the boundary with a generic fallback.
24
24
  function failureKey(error) {
25
25
  const key = propertyOf(error, "i18nKey");
26
26
  return typeof key === "string" ? key : "userDataRights.privacyCenter.errors.generic";
27
27
  }
28
- // Roher ISO-Instant → nur der Datums-Teil ist relevant; reiner String-Slice,
29
- // kein Date-API (no-date-api-Guard) und universell. Leer/null → "—".
28
+ // Only the date portion of the raw ISO instant is relevant; use a string slice
29
+ // instead of the Date API (no-date-api-Guard) for universal support. Empty/null
30
+ // values become "—".
30
31
  export function formatDate(iso) {
31
32
  if (!iso)
32
33
  return EMPTY_VALUE_PLACEHOLDER;
@@ -65,10 +66,10 @@ export function ExportSection() {
65
66
  setStatus({ kind: "idle" });
66
67
  void statusQuery.refetch?.();
67
68
  };
68
- // Download laeuft ueber den Dispatcher (traegt X-CSRF-Token) statt ueber
69
- // eine <a>-Navigation: download-by-job liefert eine signed URL zurueck, auf
70
- // die postWithDownload den Browser navigiert (content-disposition:
71
- // attachment → laedt herunter).
69
+ // Download runs through the dispatcher (which supplies X-CSRF-Token) instead of
70
+ // an <a>-navigation: download-by-job returns a signed URL, which
71
+ // postWithDownload navigates the browser to (content-disposition:
72
+ // attachment → triggers a download).
72
73
  const downloadExport = async (jobId) => {
73
74
  const err = await postWithDownload(dispatcher, UserDataRightsQueries.downloadByJob, { jobId });
74
75
  if (err)
@@ -82,7 +83,7 @@ export function ExportSection() {
82
83
  const failed = job?.status === EXPORT_JOB_STATUS.Failed;
83
84
  // While the job is running: poll until Done/Failed, then auto-stop.
84
85
  const refetch = statusQuery.refetch;
85
- // kumiko-lint-ignore no-raw-hooks Phase-3 conversion tracked in #2312
86
+ // kumiko-lint-ignore no-raw-hooks not yet converted to the framework hook set
86
87
  useEffect(() => {
87
88
  if (!inProgress || !refetch)
88
89
  return;
@@ -1,11 +1,11 @@
1
1
  import type { ComponentType, ReactNode } from "react";
2
2
  export type PublicDeletionRoutes = {
3
- /** Login-freie Route für die Email-Antrags-Maske (z.B. "/account/delete"). */
3
+ /** Login-free route for the email request screen (e.g. "/account/delete"). */
4
4
  readonly requestPath: string;
5
- /** Login-freie Route für die Token-Bestätigung; = Pfad der deletionVerifyUrl. */
5
+ /** Login-free route for token confirmation; path of deletionVerifyUrl. */
6
6
  readonly confirmPath: string;
7
- /** Chrome um die Screen-Card. Default: vollflächig zentriert (wie der Auth-
8
- * defaultShell). Apps reichen ihre eigene Shell (z.B. Marketing-Header). */
7
+ /** Shell around the screen card. Default: full-screen centered (like the auth-
8
+ * defaultShell). Apps can provide their own shell (e.g. a marketing header). */
9
9
  readonly shell?: (screen: ReactNode) => ReactNode;
10
10
  };
11
11
  export declare function makePublicDeletionGate(routes: PublicDeletionRoutes): ComponentType<{
@@ -1,11 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // RequestAccountDeletionScreen — anonymer Apex-Screen Schritt 1. Email-Form
3
- // → user-data-rights:write:request-deletion-by-email. Enumeration-safe: zeigt
4
- // unconditional ein "Falls Account existiert, Mail unterwegs"-Confirm, auch
5
- // wenn der Server intern erkannt hat dass die Email nicht existiert.
2
+ // RequestAccountDeletionScreen — anonymous Apex screen, step 1: email form
3
+ // → user-data-rights:write:request-deletion-by-email. Enumeration-safe: always
4
+ // shows a "If an account exists, the email is on its way" confirmation, even
5
+ // when the server has determined internally that the email does not exist.
6
6
  //
7
- // App mountet den Screen unter einer Apex-Route (z.B. /delete-account) via
8
- // createPublicSurface; die Page-Shell liefert die Chrome.
7
+ // The app mounts this screen at an Apex route (e.g. /delete-account) via
8
+ // createPublicSurface; the page shell provides the surrounding chrome.
9
9
  import { useDispatcher, usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
10
10
  import { useState } from "react";
11
11
  const REQUEST_BY_EMAIL = "user-data-rights:write:request-deletion-by-email";
@@ -1,27 +1,27 @@
1
1
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
2
2
  /**
3
- * Sanitize einen vom User-Input stammenden fileName fuer Verwendung als
4
- * ZIP-internal-path-Suffix. Defense gegen:
5
- * - Path-Traversal: "../../etc/passwd" → "file.etc_passwd"
6
- * - Null-Bytes: "report\x00.pdf" → "report_.pdf"
7
- * - Path-Separator: "sub/dir/file.txt" → "sub_dir_file.txt"
8
- * - Reserved-Names: "." / ".." / "..." → "file"
3
+ * Sanitizes a user-provided fileName for use as a ZIP-internal-path suffix.
4
+ * - Path traversal: "../../etc/passwd" → "file.etc_passwd"
5
+ * - Null bytes: "report\x00.pdf" → "report_.pdf"
6
+ * - Path separators: "sub/dir/file.txt" → "sub_dir_file.txt"
7
+ * - Reserved names: "." / ".." / "..." → "file"
9
8
  * - Empty input: "" / null / undef → "unnamed"
10
- * - Ueberlange: lange Strings auf MAX_SANITIZED_BASENAME_LENGTH gekappt
11
- * (Extension bleibt erhalten falls vorhanden)
12
- * - Unicode: non-ASCII → underscore. Leading-strip kann auch dazu
13
- * fuehren dass alle-Unicode-Names zu "file" werden.
9
+ * - Excessive length: long strings are truncated to
10
+ * MAX_SANITIZED_BASENAME_LENGTH
11
+ * (the extension is preserved when present)
12
+ * - Unicode: non-ASCII characters → underscores. Leading stripping
13
+ * can also cause all-Unicode names to become "file".
14
14
  *
15
- * Output ist garantiert: nicht leer, kein Path-Separator, max-len enforced,
16
- * keine `..`-Sequenz im finalen String.
15
+ * The output is guaranteed to be non-empty, contain no path separators, obey
16
+ * the maximum length, and contain no `..` sequence.
17
17
  */
18
18
  export declare function sanitizeZipFilename(raw: string): string;
19
19
  /**
20
- * Berechnet den ZIP-internal-Pfad fuer einen fileRef. Layout:
20
+ * Computes the ZIP-internal path for a fileRef. Layout:
21
21
  * files/<tenantId>/<fileRefId>-<sanitized-fileName>
22
22
  *
23
- * tenantId + fileRefId sind UUID-shape (sicher); fileName geht durch
24
- * sanitizeZipFilename. Garantiert kein path-traversal.
23
+ * tenantId and fileRefId have UUID shapes and are safe; fileName is passed
24
+ * through sanitizeZipFilename. Path traversal is guaranteed to be excluded.
25
25
  */
26
26
  export declare function buildFileRefZipPath(args: {
27
27
  readonly tenantId: TenantId;
@@ -1,65 +1,66 @@
1
- // Shared helper fuer ZIP-Path-Berechnung von fileRefs (S2.U3 Atom 3c).
1
+ // Shared helper for computing ZIP paths from fileRefs.
2
2
  //
3
- // Das Bundle hat zwei Sichten auf die selben fileRefs:
4
- // 1. bundle.json: Eine flat-Liste mit `zipPath` pro fileRef. Reader-
5
- // Tools koennen so JSON ↔ files/-Pfade verlinken.
6
- // 2. ZIP-Entries: Bytes liegen unter genau diesen `zipPath`-Schluesseln.
3
+ // The bundle has two views of the same fileRefs:
4
+ // 1. bundle.json: A flat list with `zipPath` for each fileRef. Reader
5
+ // tools can use this to link JSON to files/-paths.
6
+ // 2. ZIP entries: Bytes are stored under exactly these `zipPath` keys.
7
7
  //
8
- // Damit beide Sichten NICHT auseinander driften, lebt die Pfad-Berechnung
9
- // EXAKT EINMAL hier. run-user-export befuellt zipPath im fileRef-Item,
10
- // run-export-jobs's bundleToZipEntries nutzt dieselben Pfade als Entry-
11
- // Keys.
8
+ // To keep both views synchronized, path computation lives EXACTLY ONCE here.
9
+ // run-user-export fills zipPath in the fileRef item, and
10
+ // run-export-jobs's bundleToZipEntries uses the same paths as entry keys.
12
11
  /**
13
- * Maximale Laenge des sanitized fileName (ohne Extension). Realistic
14
- * Filenames sind <50, 100 ist eine sichere Grenze fuer ZIP-Kompatibilitaet
15
- * (PKWARE-spec keine harte limit, aber viele Reader haengen bei extrem
16
- * langen Namen).
12
+ * Maximum length of the sanitized fileName without its extension. Realistic
13
+ * filenames are <50; 100 is a safe limit for ZIP compatibility
14
+ * (the PKWARE spec has no hard limit, but many readers struggle with
15
+ * extremely long names).
17
16
  */
18
17
  const MAX_SANITIZED_BASENAME_LENGTH = 100;
19
18
  /**
20
- * Erlaubte Filename-Chars: alphanumerisch, dot, dash, underscore. Alles
21
- * andere wird zu underscore replaced. Path-Separator (`/`, `\`),
22
- * relative-traversal (`..`), und null-bytes sind insbesondere ausgeschlossen.
19
+ * Allowed filename chars: alphanumerics, dot, dash, underscore. Everything
20
+ * else is replaced with an underscore. This excludes path separators (`/`,
21
+ * `\`) and null bytes in particular; relative traversal (`..`) is handled
22
+ * by the basename and leading-dot rules below.
23
23
  */
24
24
  const FILENAME_SAFE_CHARS = /[^a-zA-Z0-9._-]/g;
25
25
  /**
26
- * Sanitize einen vom User-Input stammenden fileName fuer Verwendung als
27
- * ZIP-internal-path-Suffix. Defense gegen:
28
- * - Path-Traversal: "../../etc/passwd" → "file.etc_passwd"
29
- * - Null-Bytes: "report\x00.pdf" → "report_.pdf"
30
- * - Path-Separator: "sub/dir/file.txt" → "sub_dir_file.txt"
31
- * - Reserved-Names: "." / ".." / "..." → "file"
26
+ * Sanitizes a user-provided fileName for use as a ZIP-internal-path suffix.
27
+ * - Path traversal: "../../etc/passwd" → "file.etc_passwd"
28
+ * - Null bytes: "report\x00.pdf" → "report_.pdf"
29
+ * - Path separators: "sub/dir/file.txt" → "sub_dir_file.txt"
30
+ * - Reserved names: "." / ".." / "..." → "file"
32
31
  * - Empty input: "" / null / undef → "unnamed"
33
- * - Ueberlange: lange Strings auf MAX_SANITIZED_BASENAME_LENGTH gekappt
34
- * (Extension bleibt erhalten falls vorhanden)
35
- * - Unicode: non-ASCII → underscore. Leading-strip kann auch dazu
36
- * fuehren dass alle-Unicode-Names zu "file" werden.
32
+ * - Excessive length: long strings are truncated to
33
+ * MAX_SANITIZED_BASENAME_LENGTH
34
+ * (the extension is preserved when present)
35
+ * - Unicode: non-ASCII characters → underscores. Leading stripping
36
+ * can also cause all-Unicode names to become "file".
37
37
  *
38
- * Output ist garantiert: nicht leer, kein Path-Separator, max-len enforced,
39
- * keine `..`-Sequenz im finalen String.
38
+ * The output is guaranteed to be non-empty, contain no path separators, obey
39
+ * the maximum length, and contain no `..` sequence.
40
40
  */
41
41
  export function sanitizeZipFilename(raw) {
42
42
  if (raw === undefined || raw === null || raw === "")
43
43
  return "unnamed";
44
- // Extension extrahieren (letzte ".X" wo X kein "." enthaelt).
44
+ // Extract the extension (the last ".X" where X contains no ".").
45
45
  const lastDot = raw.lastIndexOf(".");
46
46
  const hasExt = lastDot > 0 && lastDot < raw.length - 1;
47
47
  const baseName = hasExt ? raw.slice(0, lastDot) : raw;
48
48
  const extension = hasExt ? raw.slice(lastDot + 1) : "";
49
49
  const safeBase = collapseUnsafe(baseName).slice(0, MAX_SANITIZED_BASENAME_LENGTH);
50
50
  const safeExt = collapseUnsafe(extension).slice(0, 20);
51
- // Empty oder all-underscores → "file" als reproduzierbarer Fallback.
51
+ // Empty or all-underscore input → "file" as a reproducible fallback.
52
52
  const finalBase = safeBase.length === 0 ? "file" : safeBase;
53
53
  return safeExt.length > 0 ? `${finalBase}.${safeExt}` : finalBase;
54
54
  }
55
55
  /**
56
- * 3-step Sanitize:
57
- * 1. Replace alles ausser [a-zA-Z0-9._-] mit "_"
58
- * 2. Collapse `..` (oder mehr) → "_" — verhindert dass `..` nach
59
- * Sanitize uebrig bleibt (z.B. wenn input nur dots+slashes ist).
60
- * 3. Strip leading [._-]+ — verhindert hidden-file-Patterns + leere
61
- * Basenames + leading-segments die nach den ersten zwei Steps
62
- * lauter underscores haetten.
56
+ * Three-step sanitization:
57
+ * 1. Replace everything except [a-zA-Z0-9._-] with "_".
58
+ * 2. Collapse `..` (or more) to "_"—this prevents `..` from surviving
59
+ * sanitization (for example, when the input contains only dots and
60
+ * slashes).
61
+ * 3. Strip leading [._-]+—this prevents hidden-file patterns, empty
62
+ * basenames, and leading segments that would consist entirely of
63
+ * underscores after the first two steps.
63
64
  */
64
65
  function collapseUnsafe(s) {
65
66
  let out = s.replace(FILENAME_SAFE_CHARS, "_");
@@ -68,11 +69,11 @@ function collapseUnsafe(s) {
68
69
  return out;
69
70
  }
70
71
  /**
71
- * Berechnet den ZIP-internal-Pfad fuer einen fileRef. Layout:
72
+ * Computes the ZIP-internal path for a fileRef. Layout:
72
73
  * files/<tenantId>/<fileRefId>-<sanitized-fileName>
73
74
  *
74
- * tenantId + fileRefId sind UUID-shape (sicher); fileName geht durch
75
- * sanitizeZipFilename. Garantiert kein path-traversal.
75
+ * tenantId and fileRefId have UUID shapes and are safe; fileName is passed
76
+ * through sanitizeZipFilename. Path traversal is guaranteed to be excluded.
76
77
  */
77
78
  export function buildFileRefZipPath(args) {
78
79
  const safeName = sanitizeZipFilename(args.fileName);
@@ -10,23 +10,23 @@ import { notificationPreferenceDeleteHook, notificationPreferenceExportHook, } f
10
10
  import { tenantInvitationDeleteHook, tenantInvitationExportHook, } from "./hooks/tenant-invitation.userdata-hook.js";
11
11
  import { userDeleteHook, userExportHook } from "./hooks/user.userdata-hook.js";
12
12
  import { userSessionDeleteHook, userSessionExportHook, } from "./hooks/user-session.userdata-hook.js";
13
- // user-data-rights-defaults — Default-Hooks für die Core-Entities
14
- // `user` (S2.H1) und `fileRef` (S2.H2).
13
+ // user-data-rights-defaults — Default hooks for the core entities
14
+ // `user` and `fileRef`.
15
15
  //
16
- // Architektur-Entscheidung (S2.H1+H2): user-data-rights selbst kann
17
- // nicht r.requires({ features: ["user", "files"] }) + r.useExtension(EXT_USER_DATA, ...)
18
- // machen weil es selbst Provider von EXT_USER_DATA ist (Boot-Validator
19
- // lehnt self-extension ab). Lösung: drittes optional-mountbares Feature
20
- // das requires beide Sources + die useExtension-Calls macht.
16
+ // Architectural decision: user-data-rights itself cannot call
17
+ // r.requires({ features: ["user", "files"] }) + r.useExtension(EXT_USER_DATA, ...)
18
+ // because it provides EXT_USER_DATA itself (the boot validator rejects
19
+ // self-extension). The solution is a third, optionally mountable feature
20
+ // that requires both sources and makes the useExtension calls.
21
21
  //
22
- // App-Author kann dieses Feature weglassen wenn er Custom-Hooks
23
- // stattdessen registrieren will (z.B. "anonymize sollte den User-Row
24
- // hard-delete" — App-spezifische Compliance-Entscheidung). Default-
25
- // Implementierung deckt 95% der Apps ab.
22
+ // App authors can omit this feature if they want to register custom hooks
23
+ // instead (for example, "anonymize should hard-delete the user row" — an
24
+ // app-specific compliance decision). The default implementation covers 95%
25
+ // of apps.
26
26
  //
27
- // Pattern matched file-foundation + file-provider-s3 (separate Plugin-
28
- // Feature), nicht user/files schreiben ihre eigenen Hooks selbst weil
29
- // das circular-requires waere.
27
+ // This follows the file-foundation + file-provider-s3 pattern (separate
28
+ // plugin features): user/files do not define their own hooks because that
29
+ // would create circular requires.
30
30
  // Binary storage for the fileRef delete-hook is resolved at run time from the
31
31
  // mounted file-foundation via ctx.buildStorageProvider (injected by the forget
32
32
  // orchestrator) — no provider is captured here, so a single app-wide store and
@@ -78,7 +78,7 @@ export function createUserDataRightsDefaultsFeature() {
78
78
  export: configValueExportHook,
79
79
  delete: configValueDeleteHook,
80
80
  });
81
- // Events-only aggregates (#799): export reads the projected rows, the
81
+ // Events-only aggregates: export reads the projected rows, the
82
82
  // delete hooks are deliberate no-ops — erasure happens via crypto-
83
83
  // shredding (forget erases the user's DEK; recipientAddress / job
84
84
  // payload become unreadable in events AND rows).
@@ -1,11 +1,9 @@
1
1
  import { appendEventInTenantDb, getStreamVersionInTenantDb, } from "@cosmicdrift/kumiko-framework/event-store";
2
2
  import { DELIVERY_ATTEMPT_ADDRESS_ERASED_EVENT, deliveryAttemptsTable, } from "../../delivery/index.js";
3
3
  import { featureMounted } from "./feature-mounted.js";
4
- // userData-Hooks for delivery's attempt log (deferred from #797, closed by
5
- // #799). deliveryAttempt is an events-only aggregate — the export reads the
6
- // projected rows; recipientAddress may be ciphertext (kumiko-pii:), which
7
- // the export runner's central decrypt sweep resolves to plaintext (or
8
- // [[erased]] after a forget).
4
+ // userData-Hooks for delivery's attempt log. deliveryAttempt is an events-only aggregate — the
5
+ // export reads the projected rows; recipientAddress may be ciphertext (kumiko-pii:), which the
6
+ // export runner's central decrypt sweep resolves to plaintext (or [[erased]] after a forget).
9
7
  export const deliveryAttemptExportHook = async (ctx) => {
10
8
  if (!featureMounted(ctx, "delivery"))
11
9
  return null;
@@ -10,66 +10,62 @@ const ERROR_CONTEXT = "user-data-rights-defaults:fileRef";
10
10
  // writes are wiped/resurrected on rebuild — the Art.17 hole this fixes. Bounded:
11
11
  // per-user forget flows are rare, so per-row events are acceptable.
12
12
  const crud = createEventStoreExecutor(fileRefsTable, fileRefEntity, { entityName: "fileRef" });
13
- // userData-Hook fuer fileRef-entity (S2.H2).
13
+ // User-data hook for the fileRef entity.
14
14
  //
15
- // Export-Hook liefert Metadata aller FileRefs des Users mit Subject-
16
- // Resolver via insertedById. Storage-Provider-binary-Streams kommen
17
- // NICHT direkt — sie werden via signed-Download-URLs separat ins ZIP
18
- // gepackt (S2.U3 Export-Job-Pipeline orchestriert das).
15
+ // The export hook returns metadata for all of the user's FileRefs, with the
16
+ // subject resolved through insertedById. Storage-provider binary streams are
17
+ // not included directly; signed download URLs package them into the ZIP
18
+ // separately.
19
19
  //
20
- // Delete-hook removes the fileRef row + binary:
20
+ // The delete hook removes the fileRef row and binary:
21
21
  // "delete": storageProvider.delete() per file + row hard-delete — but
22
22
  // ONLY for rows whose field is marked as PII of the person
23
- // (isPersonalFileRow, #3005). All other rows (business/
24
- // tenant data, no resolvable field, no annotation) go
25
- // through severPersonLink instead, even when the entity
26
- // strategy is "delete" — the uploader axis (insertedById) is
27
- // not the subject axis.
28
- // "anonymize": insertedById=null, row + binary survive (FK refs can still
29
- // point at it; person-link removed) — applies to ALL rows
23
+ // (isPersonalFileRow). All other rows (business/tenant data,
24
+ // no resolvable field, no annotation) go through
25
+ // severPersonLink instead, even when the entity strategy is
26
+ // "delete" — the uploader axis (insertedById) is not the
27
+ // subject axis.
28
+ // "anonymize": insertedById=null; row and binary survive (FK refs can still
29
+ // point at it; person-link removed). This applies to ALL rows
30
30
  // when a retention override on fileRef (anonymize or
31
31
  // blockDelete, e.g. a statutory retention duty) sets the
32
32
  // strategy, regardless of the field.
33
33
  //
34
- // **Provider-Resolution:** der Provider kommt zur Lauf-Zeit aus
35
- // `ctx.buildStorageProvider(ctx.tenantId)` — der Forget-Orchestrator
36
- // (run-forget-cleanup) baut ihn aus dem gemounteten file-foundation, also aus
37
- // DEMSELBEN Store den Upload + Export nutzen (delete-target == upload-target by
38
- // construction). Kein bei-Mount captured Provider mehr.
34
+ // **Provider resolution:** the provider is obtained at runtime from
35
+ // `ctx.buildStorageProvider(ctx.tenantId)`. The forget orchestrator builds it
36
+ // from the mounted file-foundation, using the SAME store as upload and export
37
+ // (delete-target == upload-target by construction). No provider is captured at
38
+ // mount time.
39
39
  //
40
- // **Zwei Fehlerklassen, bewusst verschieden behandelt:**
41
- // 1. Resolution schlaegt fehl (kein Provider konfiguriert / configResolver
42
- // fehlt) → NICHT fail-closed: Warn pro Aufruf + row-only-delete. Ein
43
- // fehlkonfigurierter Store darf die Art.-17-Loeschung nicht DAUERHAFT
44
- // blockieren (sonst haengt jeder User fuer immer in DeletionRequested);
45
- // der Boot-Guard macht die Fehlkonfiguration sichtbar, Binaries werden
46
- // nachgeholt sobald ein Provider existiert.
47
- // 2. Binary-DELETE schlaegt fehl, OBWOHL ein Provider da ist → FAIL-CLOSED:
48
- // der Hook wirft NACH dem Loop, die per-User-Sub-Tx von runForgetCleanup
49
- // rollt zurueck, der User bleibt DeletionRequested, der naechste Run
50
- // retried (delete ist idempotent → konvergiert). Den Fehler zu schlucken +
51
- // die Row trotzdem zu loeschen wuerde Erasure als "done" markieren waehrend
52
- // die Bytes liegen bleiben — falsche Compliance-Aussage. Das "KEIN globaler
53
- // Rollback" der Sprint-2-Atomicity bleibt gewahrt: nur DIESE Sub-Tx rollt
54
- // zurueck. Der anonymize-Pfad behaelt Row+binary, hat nichts zu schlucken.
40
+ // **Two error classes are handled differently:**
41
+ // 1. Resolution fails (no provider configured / configResolver missing) →
42
+ // NOT fail-closed: warn per invocation and perform a row-only delete. A
43
+ // misconfigured store must not permanently block the Art. 17 deletion;
44
+ // the boot guard exposes the misconfiguration, and binaries are removed
45
+ // once a provider exists.
46
+ // 2. Binary DELETE fails even though a provider exists → FAIL-CLOSED: the
47
+ // hook throws after the loop, the per-user sub-transaction rolls back,
48
+ // the user remains DeletionRequested, and the next run retries (delete is
49
+ // idempotent → converges). Swallowing the error and deleting the row would
50
+ // mark erasure as "done" while leaving the bytes behind. Only this
51
+ // sub-transaction rolls back; there is no global rollback. The anonymize
52
+ // path retains the row and binary, so it has no error to swallow.
55
53
  //
56
- // Caveat: hard-delete via deleteMany emittiert KEIN fileRef.deleted —
57
- // die storage-tracking-MSP dekrementiert nicht. Wenn die zu loeschenden
58
- // Files vorher nicht soft-deleted waren, bleibt `tenant_storage_usage`
59
- // inflated. Forget-Flows sind selten (per-User-Art.-17) und damit
60
- // bounded; ein executor.purge-API folgt mit dem trashed-files-GC.
54
+ // Caveat: hard-delete via deleteMany emits no fileRef.deleted event, so
55
+ // storage-tracking does not decrement. If the files being deleted were not
56
+ // soft-deleted first, `tenant_storage_usage` remains inflated. Forget flows are
57
+ // rare and bounded; an executor.purge API will follow with trashed-files GC.
61
58
  export const fileRefExportHook = async (ctx) => {
62
- // isDeleted:false — soft-deleted (trashed) Files gehören nicht ins
63
- // Auskunfts-Bundle. Forget (delete-Hook unten) erfasst sie trotzdem.
59
+ // isDeleted:false — soft-deleted (trashed) files are excluded from the
60
+ // export bundle. The forget hook below still processes them.
64
61
  const rawRows = await ctx.db.selectMany(fileRefsTable, {
65
62
  tenantId: ctx.tenantId,
66
63
  insertedById: ctx.userId,
67
64
  isDeleted: false,
68
65
  });
69
- // @cast-boundary db-row: drizzle liefert insertedAt als Instant
70
- // (framework-customType). Fuer JSON-Export brauchen wir String —
71
- // .toString() funktioniert sowohl auf Temporal.Instant als auch
72
- // Date.
66
+ // @cast-boundary db-row: drizzle returns insertedAt as an Instant
67
+ // (framework-customType). JSON export requires a string —
68
+ // .toString() works for both Temporal.Instant and Date.
73
69
  const rows = rawRows.map((r) => {
74
70
  const row = r; // @cast-boundary recursive-walk
75
71
  return {
@@ -92,9 +88,8 @@ export const fileRefExportHook = async (ctx) => {
92
88
  size: r.size,
93
89
  insertedAt: r.insertedAt,
94
90
  })),
95
- // Plus die fileRefs-Liste die Sprint-2-U3 dann zum Storage-Provider
96
- // bringt + signed-URLs erzeugt + ins ZIP packt (siehe S1.9-Z1
97
- // UserDataExportSnippet.fileRefs).
91
+ // The fileRefs list is passed to the storage provider, which generates
92
+ // signed URLs and adds the files to the ZIP.
98
93
  fileRefs: rows.map((r) => ({
99
94
  fileRefId: r.id,
100
95
  storageKey: r.storageKey,
@@ -119,7 +114,7 @@ async function resolveProvider(ctx) {
119
114
  return undefined;
120
115
  }
121
116
  }
122
- // Per-row Art.17 decision (kumiko-framework#3005): whether THIS file's field
117
+ // Per-row Art.17 decision: whether THIS file's field
123
118
  // carries personal data of the forgotten person, or is business/tenant data
124
119
  // that merely loses its uploader-attribution. insertedById names who
125
120
  // UPLOADED the file, not whose data it is — a dealer's vehicle photo
@@ -138,8 +133,7 @@ function isPersonalPiiField(field) {
138
133
  ("userOwned" in field && field.userOwned !== undefined) ||
139
134
  ("recordOwned" in field && field.recordOwned === true));
140
135
  }
141
- // Three cases the field-lookup itself can't resolve (issue #3005's rule for
142
- // the non-resolvable cases):
136
+ // Three cases the field-lookup itself can't resolve:
143
137
  // 1. Unattached upload (entityType/fieldName both null) → hard-delete: a
144
138
  // file with no entity binding belongs to nobody but its uploader.
145
139
  // 2. Field exists but carries no PII annotation → anonymize (the
@@ -211,7 +205,7 @@ export const fileRefDeleteHook = async (ctx, strategy) => {
211
205
  return;
212
206
  }
213
207
  // strategy="delete" decides PER ROW based on the field, not uniformly
214
- // (#3005): only rows whose field is marked as PII of the person (or
208
+ // only rows whose field is marked as PII of the person (or
215
209
  // unattached, see isPersonalFileRow) take the hard path. Everything else
216
210
  // only loses the uploader link.
217
211
  const personalRows = [];
@@ -1,6 +1,6 @@
1
1
  import { jobRunsTable } from "../../jobs/index.js";
2
2
  import { featureMounted } from "./feature-mounted.js";
3
- // userData-Hooks for the jobs run log (deferred from #797, closed by #799).
3
+ // userData-Hooks for the jobs run log.
4
4
  // Job runs live on the SYSTEM tenant regardless of who triggered them, so
5
5
  // the export filters by triggeredById only — Art. 15 covers everything the
6
6
  // user caused, across tenants. payload may be ciphertext (kumiko-pii:); the
@@ -27,6 +27,6 @@ export const jobRunExportHook = async (ctx) => {
27
27
  export const jobRunDeleteHook = async () => {
28
28
  // Deliberate no-op: erasure runs via crypto-shredding — the forget pipeline
29
29
  // erases the triggering user's DEK, which makes the payload unreadable in
30
- // BOTH the append-only events and the projected rows (#799). triggeredById
30
+ // BOTH the append-only events and the projected rows. triggeredById
31
31
  // itself is a pseudonymous fk (plaintext by design, like config.userId).
32
32
  };
@@ -9,7 +9,7 @@ import { featureMounted } from "./feature-mounted.js";
9
9
  // the forget verb.
10
10
  //
11
11
  // The delivery ATTEMPTS log is covered separately: export via
12
- // delivery-attempt.userdata-hook.ts, erasure via crypto-shredding (#799).
12
+ // delivery-attempt.userdata-hook.ts, erasure via crypto-shredding.
13
13
  const crud = createEventStoreExecutor(notificationPreferencesTable, notificationPreferenceEntity, {
14
14
  entityName: "notification-preference",
15
15
  });
@@ -3,9 +3,9 @@ import { featureMounted } from "./feature-mounted.js";
3
3
  // userData-Hooks for the sessions feature's user-session rows (ip, userAgent).
4
4
  //
5
5
  // user-session is an unmanaged direct-write store (no event stream, excluded
6
- // from projection rebuilds — see sessions/feature.ts #494/#498), so a direct
7
- // DELETE is legal here and survives rebuilds; the executor path the ES
8
- // entities use does not apply.
6
+ // from projection rebuilds, see sessions/feature.ts), so a direct DELETE is
7
+ // legal here and survives rebuilds; the executor path the ES entities use does
8
+ // not apply.
9
9
  //
10
10
  // Both forget strategies hard-delete: a session row without its user is
11
11
  // worthless (revocation audit trail loses its subject), and ip/userAgent are