@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
package/LICENSE CHANGED
@@ -1,57 +1,21 @@
1
- Business Source License 1.1
2
-
3
- Parameters
4
-
5
- Licensor: Marc Frost
6
-
7
- Licensed Work: @cosmicdrift/kumiko-framework
8
- The Licensed Work is © 2026 Marc Frost.
9
-
10
- Additional Use Grant:
11
- You may use the Licensed Work in production for any purpose, including
12
- commercially, EXCEPT for the Restricted Use.
13
-
14
- "Restricted Use" is defined as using the Licensed Work to provide a platform
15
- or service to third parties that allows them to host, deploy, or run their
16
- own applications built with the Licensed Work. This includes, but is not
17
- limited to: managed hosting services, software-as-a-service (SaaS) platforms,
18
- platform-as-a-service (PaaS), developer platforms, or any multi-tenant
19
- managed offering of the Licensed Work.
20
-
21
- This restriction does not apply to the Licensor, any entity controlled by,
22
- controlling, or under common control with the Licensor ("Affiliates"), or
23
- contractors acting on their behalf. The Licensor remains free to use the
24
- Licensed Work for any purpose, including for the operation of kumiko.rocks.
25
-
26
- Change Date: 2030-05-05
27
- Change License: Apache License, Version 2.0
28
-
29
-
30
- Terms
31
-
32
- The Licensor hereby grants you the right to copy, modify, create derivative works,
33
- redistribute, and make non-production use of the Licensed Work. The Licensor may
34
- make an Additional Use Grant, above, permitting limited production use.
35
-
36
- Effective on the Change Date, or the fourth anniversary of the first publicly
37
- available distribution of the Licensed Work under this License, whichever comes
38
- first, this License will convert to the Change License.
39
-
40
- This Business Source License governs use of the Licensed Work in all cases, except
41
- as to any use that is explicitly granted in the Additional Use Grant above or
42
- under the Change License after the Change Date.
43
-
44
- If your use of the Licensed Work does not comply with the requirements of this
45
- License, you must cease use of the Licensed Work immediately.
46
-
47
- All copies of the Licensed Work, and all derivative works thereof, must include
48
- this License.
49
-
50
- This License does not grant you any right, title, or interest in any trademark,
51
- logo, or branding of the Licensor, except as required to comply with this License.
52
-
53
- TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN
54
- “AS IS” BASIS. LICENSOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
55
- WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
56
- TITLE, AND NON-INFRINGEMENT. IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY DAMAGES
57
- ARISING OUT OF OR RELATED TO THIS LICENSE OR THE USE OF THE LICENSED WORK.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Marc Frost
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -68,7 +68,7 @@ function isListHandlerQn(qn, entityName) {
68
68
  function isDetailHandlerQn(qn, entityName) {
69
69
  return qn.endsWith(`:${entityName}:detail`);
70
70
  }
71
- /** #2700: the entity CRUD tools are enumerated off the registry, not off the manifest, so
71
+ /** The entity CRUD tools are enumerated off the registry, not off the manifest, so
72
72
  * `resolveAgentExposure` never runs for them. Only an EXPLICIT opt-out may hide one here —
73
73
  * the resolver's own default is fail-closed on a missing `description`, and CRUD-generated
74
74
  * handlers never carry one, so reusing it would delete every entity tool in every app. */
@@ -85,7 +85,7 @@ export function auditLogDetailLayout(options) {
85
85
  "id",
86
86
  ],
87
87
  },
88
- // No section `title` here (fw#2312 label-dedup fix): each section
88
+ // No section `title` here (label-dedup fix): each section
89
89
  // holds exactly one field, so a title would repeat the field's own
90
90
  // label (rendered by RenderField as the Field's heading) verbatim.
91
91
  { fields: [{ field: "payload", renderer: { format: "json" } }] },
@@ -66,7 +66,7 @@ export function createAuthEmailPasswordFeature(opts = {}) {
66
66
  const strictVerification = opts.emailVerification !== undefined && (opts.emailVerification.mode ?? "strict") === "strict";
67
67
  const feature = defineFeature("auth-email-password", (r) => {
68
68
  r.describe("Provides email+password authentication: the always-on handlers are `login`, `changePassword`, and `logout`; optional flows — password reset, email verification, magic-link self-signup, tenant invite, and account-unlock — are registered only when you pass their respective option objects (`passwordReset`, `emailVerification`, `signup`, `invite`, `accountUnlock`) to `createAuthEmailPasswordFeature(opts)`. All five magic-link flows dispatch their mail through the `delivery` feature via `ctx.notify`, so mounting any of them additionally requires `delivery`. Tokens are HMAC-signed (reset/verify/unlock) or opaque-random in Redis (signup/invite). `accountUnlock` is the self-service escape hatch for `accountLockout`'s monotonic failure-counter (#1266): confirming the mailed token clears the Redis lockout state without touching the user entity. Requires the `user` and `tenant` features, and declares `JWT_SECRET` (≥ 32 chars) in `authEmailPasswordEnvSchema` so a missing secret surfaces at boot validation rather than on the first login attempt.");
69
- // kumiko-lint-ignore i18n-ui-strings uiHints labels are feature-registry metadata for the admin feature catalog, not yet wired to the i18n system, see #2312
69
+ // kumiko-lint-ignore i18n-ui-strings uiHints labels are feature-registry metadata for the admin feature catalog, not yet wired to the i18n system
70
70
  r.uiHints({
71
71
  displayLabel: "Auth \u00b7 Email + Password",
72
72
  category: "identity",
@@ -42,9 +42,9 @@ export const changePasswordWrite = defineWriteHandler({
42
42
  return invalidCredentials();
43
43
  }
44
44
  const newHash = await hashPassword(event.payload.newPassword);
45
- // The user aggregate is systemStream (#497): its event stream lives on
46
- // SYSTEM_TENANT_ID deterministically. Pre-#497 scattered streams need the
47
- // one-time backfillUserStreamTenants migration (#762).
45
+ // The user aggregate is systemStream: its event stream lives on
46
+ // SYSTEM_TENANT_ID deterministically. Previously scattered streams need the
47
+ // one-time backfillUserStreamTenants migration.
48
48
  const writer = createSystemUser(SYSTEM_TENANT_ID);
49
49
  // Apply via user feature's update handler — writeAs(system) satisfies
50
50
  // the privileged-only write rule on passwordHash. Pass the current version
@@ -15,11 +15,11 @@
15
15
  // else — including future branches a maintainer adds — releases
16
16
  // automatically.
17
17
  //
18
- // The user aggregate is systemStream (#497): its event stream lives on
18
+ // The user aggregate uses systemStream: its event stream lives on
19
19
  // SYSTEM_TENANT_ID deterministically, so the write targets exactly one
20
20
  // stream. The former membership-probing (`tryWriteAcrossTenants`) existed
21
- // for pre-#497 scattered streams; those need the one-time
22
- // backfillUserStreamTenants migration (#762) — probing them stopped working
21
+ // for scattered streams; those need the one-time
22
+ // backfillUserStreamTenants migration — probing them stopped working
23
23
  // the moment the executor's stream choke-point landed anyway.
24
24
  import { createSystemUser, declareEscapeHatch, SYSTEM_TENANT_ID, } from "@cosmicdrift/kumiko-framework/engine";
25
25
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
@@ -61,8 +61,8 @@ export async function runConfirmTokenFlow(ctx, userId, expiresAtMs, spec) {
61
61
  committed = true;
62
62
  return { isSuccess: true, data: spec.successData };
63
63
  }
64
- // version_conflict = concurrent modification (or an un-migrated pre-#497
65
- // stream, see header) → token-level failure. Anything else (DB down,
64
+ // version_conflict = concurrent modification (or an un-migrated
65
+ // stream) → token-level failure. Anything else (DB down,
66
66
  // access denied) bubbles unchanged so ops sees the real failure class.
67
67
  if (writeRes.error.code === "version_conflict")
68
68
  return spec.invalidToken();
@@ -88,7 +88,7 @@ export function createInviteAcceptWithLoginHandler(opts = {}) {
88
88
  }
89
89
  // Password check against userTable, through the same gates
90
90
  // login.write.ts runs (see login-gates.test.ts for the gate contracts).
91
- // Email uniqueness is partial on live rows (framework#2593) — without
91
+ // Email uniqueness is partial on live rows — without
92
92
  // this filter the lookup can resolve a soft-deleted row.
93
93
  const userRow = await ctx.db.global(userTable).fetchOne({
94
94
  email: invitationEmail,
@@ -1,31 +1,31 @@
1
- // Tenant-Invite Step 2 — Branch 1 (logged-in user accepts).
1
+ // Tenant invitation — logged-in user accepts.
2
2
  //
3
- // User ist eingeloggt (in irgendeinem Tenant), klickt Accept-Link.
3
+ // The user is signed in to some tenant and clicks the Accept link.
4
4
  // Server:
5
5
  // 1. Token → invitationId (Redis)
6
6
  // 2. Burn (single-use)
7
- // 3. Invitation-Row aus DB
8
- // 4. Email-Match: invitation.email === user.email (sonst inviteEmailMismatch)
7
+ // 3. Load the invitation row from the database
8
+ // 4. Email match: invitation.email === user.email (otherwise inviteEmailMismatch)
9
9
  // 5+6. grantInvitedMembershipRole: create the membership, or add the
10
10
  // invited role to an existing one (add-only)
11
- // 7. Invitation-Row → status=accepted
12
- // 8. Redis-Keys löschen (Burn-Key bleibt für Replay-Schutz)
11
+ // 7. Invitation row → status=accepted
12
+ // 8. Delete Redis keys (the burn key remains for replay protection)
13
13
  //
14
- // Branch 1 ist der klassische "shared workspace bei eingeloggter
15
- // Session"-Flow. Branch 2 (anon + existing email) und Branch 3 (anon +
16
- // new email) kommen als separate Handler.
14
+ // This is the classic "shared workspace with a logged-in session" flow.
15
+ // Branch 2 (anonymous + existing email) and Branch 3 (anonymous + new
16
+ // email) are handled separately.
17
17
  import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
18
18
  import { createSystemUser, defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
19
19
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
20
20
  import * as z from "zod";
21
21
  import { decryptStoredPii } from "../../shared/index.js";
22
- // kumiko-lint-ignore cross-feature-import invite-flow lebt in auth-email-password (Magic-Link), DB-row-owner ist tenant-feature
22
+ // kumiko-lint-ignore cross-feature-import the invite flow lives in auth-email-password (Magic-Link), while the DB-row owner is a tenant feature
23
23
  import { INVITATION_STATUS, tenantInvitationEntity, tenantInvitationsTable, } from "../../tenant/invitation-table.js";
24
24
  // kumiko-lint-ignore cross-feature-import membership grant for a privileged cross-tenant add (like provisionSignupAccount)
25
25
  import { grantInvitedMembershipRole } from "../../tenant/invited-membership.js";
26
26
  // kumiko-lint-ignore cross-feature-import global roles granted on invite accept live on the user row
27
27
  import { grantInvitedGlobalRoles, parseInvitedGlobalRoles, } from "../../user/invited-global-roles.js";
28
- // kumiko-lint-ignore cross-feature-import auth handler reads user-row für email-match
28
+ // kumiko-lint-ignore cross-feature-import the auth handler reads the user row for the email match
29
29
  import { userTable } from "../../user/schema/user.js";
30
30
  import { invalidInviteToken, inviteEmailMismatch } from "../errors.js";
31
31
  import { burnInviteToken, deleteInviteToken, getInvitationIdForToken, unburnInviteToken, } from "../invite-token-store.js";
@@ -73,9 +73,9 @@ export function createInviteAcceptHandler() {
73
73
  const invitationEmail = await decryptStoredPii(invitation.email, "email", "auth:invite-accept");
74
74
  const invitationRole = invitation.role;
75
75
  const invitationVersion = invitation.version;
76
- // Email-Match: User muss mit der eingeladenen Email matchen.
77
- // Sonst kann ein Angreifer mit Zugriff zur invitee-Mail seinen
78
- // eigenen Account dem Tenant zuschlagen.
76
+ // Email match: the user must match the invited email.
77
+ // Otherwise, anyone with access to the invitee's email could add
78
+ // their own account to the tenant.
79
79
  const userRow = await ctx.db.global(userTable).fetchOne({
80
80
  id: event.user.id,
81
81
  });
@@ -103,10 +103,10 @@ export function createInviteAcceptHandler() {
103
103
  });
104
104
  if (!globalGrant.isSuccess)
105
105
  return globalGrant;
106
- // Invitation-Status → accepted via event-store-executor.
107
- // Tenant-scoping: ctx.db ist auf event.user.tenantId gescopt
108
- // (= NICHT der invitation-tenant). Eigene TenantDb für den
109
- // invitation-tenant bauen damit der executor die row findet.
106
+ // Invitation status → accepted via event-store-executor.
107
+ // Tenant scoping: ctx.db is scoped to event.user.tenantId
108
+ // (not the invitation tenant). Build a TenantDb for the
109
+ // invitation tenant so the executor can find the row.
110
110
  const invitationTdb = createTenantDb({
111
111
  db: dbConn,
112
112
  tenantId: invitationTenantId,
@@ -11,7 +11,7 @@ export type InviteCreateData = {
11
11
  readonly expiresAt: string;
12
12
  };
13
13
  export type InviteCreateOptions = {
14
- /** TTL für den Activation-Token. Default 7 Tage. */
14
+ /** TTL for the activation token. Default: 7 days. */
15
15
  readonly tokenTtlMinutes?: number;
16
16
  /** App page that receives the magic-link; the handler appends `?token=…`
17
17
  * and dispatches the invite mail via delivery (ctx.notify). Apps with
@@ -25,7 +25,7 @@ export type InviteCreateOptions = {
25
25
  readonly locale?: AuthMailLocale;
26
26
  readonly canAssignRole?: (inviterRoles: readonly string[], targetRole: string) => boolean;
27
27
  /** Opt-in allow-list for app-defined (unranked) roles the elevation guard
28
- * would otherwise reject with unassignable_membership_role (fw#2398).
28
+ * would otherwise reject with unassignable_membership_role.
29
29
  * Rank-aware alternative: declare roles via EXT_ASSIGNABLE_ROLE. */
30
30
  readonly additionalAssignableRoles?: readonly string[];
31
31
  };
@@ -1,10 +1,10 @@
1
1
  // Tenant-Invite Step 1 (create).
2
2
  //
3
- // Admin invitet email → DB-Row entsteht via event-store-executor (oder
4
- // wird re-used bei Re-Invite), Random-Token in Redis bidirektional, und der
5
- // Handler schickt die Invite-Mail an den Invitee via delivery (ctx.notify) —
6
- // wie reset/verify/signup. Der Token geht NICHT an den Admin zurück (er soll
7
- // die Annahme nicht impersonieren können).
3
+ // An admin invites an email address → a DB row is created via
4
+ // event-store-executor (or reused for a re-invite), a random token is stored
5
+ // bidirectionally in Redis, and the handler sends the invite email to the
6
+ // invitee via delivery (ctx.notify), as with reset/verify/signup. The token
7
+ // is NOT returned to the admin, so the admin cannot impersonate acceptance.
8
8
  //
9
9
  // Re-invite for the same (tenantId, email): the existing row is reused
10
10
  // regardless of its prior status (pending/cancelled/accepted), reset to
@@ -12,10 +12,10 @@
12
12
  // still live for that invitation is invalidated first, so the previous
13
13
  // mail's link stops working (see invite-token-store.ts).
14
14
  //
15
- // Always-200 für unbekannten User: bei invitee-Email die nicht in users
16
- // existiert wird trotzdem ein Invite erstellt — Branch-3-Accept-Flow
17
- // erlaubt new-user-signup mit dem Token. Keine Enumeration durchs
18
- // invite-create.
15
+ // Always-200 for an unknown user: an invite is created even when the
16
+ // invitee's email does not exist in users — the Branch-3-Accept-Flow
17
+ // permits new-user-signup with the token. invite-create does not enable
18
+ // enumeration.
19
19
  import { generateToken } from "@cosmicdrift/kumiko-framework/api";
20
20
  import { createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
21
21
  import { access, assignableAppRolesOf, defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
@@ -23,7 +23,7 @@ import { InternalError, writeFailure, } from "@cosmicdrift/kumiko-framework/erro
23
23
  import { isValidLocaleTag } from "@cosmicdrift/kumiko-framework/i18n";
24
24
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
25
25
  import * as z from "zod";
26
- // kumiko-lint-ignore cross-feature-import invite-flow lebt in auth-email-password (Magic-Link-Pattern), DB-row-owner ist tenant-feature
26
+ // kumiko-lint-ignore cross-feature-import invite flow lives in auth-email-password (Magic-Link-Pattern); DB-row owner is the tenant feature
27
27
  import { INVITATION_STATUS, tenantInvitationEntity, tenantInvitationsTable, } from "../../tenant/invitation-table.js";
28
28
  // kumiko-lint-ignore cross-feature-import membership version read is owned by the tenant feature
29
29
  import { membershipVersionOf } from "../../tenant/invited-membership.js";
@@ -9,7 +9,7 @@ import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
9
9
  import { UnprocessableError } from "@cosmicdrift/kumiko-framework/errors";
10
10
  import * as z from "zod";
11
11
  import { decryptStoredPii } from "../../shared/index.js";
12
- // kumiko-lint-ignore cross-feature-import invite-flow lebt in auth-email-password (Magic-Link), DB-row-owner ist tenant-feature
12
+ // kumiko-lint-ignore cross-feature-import invite-flow lives in auth-email-password (Magic-Link), DB-row-owner belongs to the tenant feature
13
13
  import { INVITATION_STATUS, tenantInvitationsTable } from "../../tenant/invitation-table.js";
14
14
  // kumiko-lint-ignore cross-feature-import login-style account lookup, same as invite-accept-with-login
15
15
  import { userTable } from "../../user/schema/user.js";
@@ -1,21 +1,21 @@
1
- // Tenant-Invite Step 2 — Branch 3 (anon User, Email NICHT registriert).
1
+ // Tenant-Invite Step 2 — Branch 3 (anonymous user, email NOT registered).
2
2
  //
3
- // Anders als signup-confirm: KEIN neuer Tenant entsteht. Der Tenant
4
- // existiert schon (im invitation-row), wir legen NUR User+Membership an.
3
+ // Unlike signup-confirm, no new tenant is created. The tenant already
4
+ // exists in the invitation row; only the user and membership are created.
5
5
  //
6
6
  // Flow:
7
- // 1. User klickt Invite-Link → /invite/signup?token=...
8
- // 2. Frontend zeigt Password-Form (email kommt aus invitation, kein
9
- // User-Input damit kein Email-Mismatch möglich)
10
- // 3. User submitted password + token
7
+ // 1. User clicks the invite link → /invite/signup?token=...
8
+ // 2. The frontend shows the password form (the email comes from the
9
+ // invitation, not user input, so an email mismatch is impossible)
10
+ // 3. User submits the password and token
11
11
  // 4. Server:
12
12
  // a. Token → invitationId → invitation row
13
- // b. User-Existence-Check: invitation.email darf NICHT in userTable
14
- // existieren (sonst soll Branch 2 oder Branch 1 genutzt werden)
15
- // c. Create user (emailVerified=true wegen Magic-Link)
16
- // d. Add membership im invited Tenant
17
- // e. Invitation → accepted, Token gelöscht
18
- // 5. Response: SessionUser + tenantId für Auto-Login
13
+ // b. User-existence check: invitation.email must NOT exist in userTable
14
+ // (otherwise Branch 2 or Branch 1 must be used)
15
+ // c. Create the user (emailVerified=true because of the magic link)
16
+ // d. Add membership to the invited tenant
17
+ // e. Mark the invitation accepted and delete the token
18
+ // 5. Response: SessionUser + tenantId for automatic login
19
19
  import { createEventStoreExecutor, createTenantDb, fetchOne, } from "@cosmicdrift/kumiko-framework/db";
20
20
  import { buildSessionRoles, createSystemUser, defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
21
21
  import { InternalError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
@@ -25,7 +25,7 @@ import { decryptStoredPii, registrationLocaleFromRequest } from "../../shared/in
25
25
  import { INVITATION_STATUS, tenantInvitationEntity, tenantInvitationsTable, } from "../../tenant/invitation-table.js";
26
26
  // kumiko-lint-ignore cross-feature-import reserved-role check owned by tenant-feature
27
27
  import { findForbiddenMembershipRole, reservedMembershipRoleError, } from "../../tenant/membership-roles.js";
28
- // kumiko-lint-ignore cross-feature-import membership-seed-helper für privilegierten cross-tenant-add
28
+ // kumiko-lint-ignore cross-feature-import membership-seed-helper for privileged cross-tenant addition
29
29
  import { seedTenantMembership } from "../../tenant/seeding.js";
30
30
  // kumiko-lint-ignore cross-feature-import global roles granted on invite accept live on the user row
31
31
  import { parseInvitedGlobalRoles } from "../../user/invited-global-roles.js";
@@ -74,20 +74,19 @@ export function createInviteSignupCompleteHandler(opts = {}) {
74
74
  const invitationRole = invitation.role;
75
75
  const invitationGlobalRoles = parseInvitedGlobalRoles(invitation.globalRoles);
76
76
  const invitationVersion = invitation.version;
77
- // User-Not-Exists-Check: wenn die Email schon registriert ist,
78
- // muss der User Branch 2 (acceptWithLogin) nutzen. Hier ist
79
- // explizit "neue Email" — sonst hätten wir zwei Wege ein
80
- // Password zu setzen für denselben User.
81
- // Email uniqueness is partial on live rows (framework#2593) — without
82
- // this filter the lookup can resolve a soft-deleted row.
77
+ // If the email is already registered, the user must use Branch 2
78
+ // (acceptWithLogin). This flow explicitly requires a new email;
79
+ // otherwise there would be two ways to set a password for the same user.
80
+ // Email uniqueness is partial on live rows — without this filter,
81
+ // the lookup can resolve a soft-deleted row.
83
82
  const existingUser = await ctx.db.global(userTable).fetchOne({
84
83
  email: invitationEmail,
85
84
  isDeleted: false,
86
85
  });
87
86
  if (existingUser)
88
87
  return invalidInviteToken();
89
- // User anlegen via seedUserWithPassword (gleiches Pattern wie
90
- // signup-confirm), emailVerified=true wegen Magic-Link.
88
+ // Create the user through seedUserWithPassword so the magic-link flow
89
+ // records emailVerified=true.
91
90
  // @cast-boundary db-runner — helpers use only the query API that
92
91
  // DbConnection and DbTx share.
93
92
  const dbConn = ctx.db.unsafeRaw();
@@ -100,9 +99,8 @@ export function createInviteSignupCompleteHandler(opts = {}) {
100
99
  ...registrationLocale,
101
100
  ...(invitationGlobalRoles.length > 0 && { roles: invitationGlobalRoles }),
102
101
  });
103
- // Membership-Add via seed-helper (gleiches Pattern wie
104
- // provisionSignupAccount — bypassed addMember access-check
105
- // weil createSystemUser nicht ["SystemAdmin"] matcht).
102
+ // The seed helper bypasses addMember's access check because
103
+ // createSystemUser does not match ["SystemAdmin"].
106
104
  const forbiddenInviteRole = findForbiddenMembershipRole([invitationRole]);
107
105
  if (forbiddenInviteRole !== undefined) {
108
106
  return writeFailure(reservedMembershipRoleError(forbiddenInviteRole));
@@ -112,7 +110,7 @@ export function createInviteSignupCompleteHandler(opts = {}) {
112
110
  tenantId: invitationTenantId,
113
111
  roles: [invitationRole],
114
112
  });
115
- // Invitation → accepted: TenantDb für invitation-tenant
113
+ // Update the invitation in the invited tenant's database context.
116
114
  const invitationTdb = createTenantDb({
117
115
  db: dbConn,
118
116
  tenantId: invitationTenantId,
@@ -45,7 +45,7 @@ type GateOutcome<T> = GateReject | GateOk<T>;
45
45
  type AuthenticatableUserRow = AuthUserRow & {
46
46
  readonly passwordHash: string;
47
47
  };
48
- /** Uniform response on any credential miss — burns argon2 cost (#774). */
48
+ /** Uniform response on any credential miss — burns argon2 cost. */
49
49
  export declare function gateResolveAuthUser(found: AuthUserRow | null, password: string): Promise<GateOutcome<AuthenticatableUserRow>>;
50
50
  export declare function gateCountUnknownUser(ctx: HandlerContext, email: string, maxFailedAttempts: number, lockoutDurationMinutes: number): Promise<GateOutcome<undefined>>;
51
51
  /**
@@ -14,7 +14,7 @@ function reject(result) {
14
14
  function ok(value) {
15
15
  return { ok: true, value };
16
16
  }
17
- /** Uniform response on any credential miss — burns argon2 cost (#774). */
17
+ /** Uniform response on any credential miss — burns argon2 cost. */
18
18
  export async function gateResolveAuthUser(found, password) {
19
19
  if (!found?.passwordHash || found.isDeleted) {
20
20
  await verifyDummyPassword(password);
@@ -16,7 +16,7 @@ export const selfRegistrationStatusQuery = defineQueryHandler({
16
16
  rateLimit: { per: "ip+handler", limit: 30, windowSeconds: 60 },
17
17
  description: "Reports whether self-registration is currently switched on, readable without signing in, so a signup page can hide its own form instead of collecting an address that would be silently ignored.",
18
18
  handler: async (_query, ctx) => {
19
- // Same fail-open reasoning as signup-request.write.ts (#1468): only
19
+ // Same fail-open reasoning as signup-request.write.ts: only
20
20
  // report disabled when the toggle feature is actually composed.
21
21
  const gated = ctx.registry.getFeature(AUTH_SELF_REGISTRATION_FEATURE) !== undefined;
22
22
  return { enabled: gated ? await ctx.hasFeature(AUTH_SELF_REGISTRATION_FEATURE) : true };
@@ -1,23 +1,22 @@
1
- // Magic-Link-Signup, Step 2 (confirm).
1
+ // Magic-Link signup, step 2 (confirmation).
2
2
  //
3
- // Token aus URL + Password vom User → wir lösen den Token in Redis ein
4
- // und legen Tenant + User + TenantAdmin membership atomically. emailVerified
5
- // wird sofort auf true gesetzt — der Magic-Link IST der Beweis.
3
+ // Token from the URL + password from the user → redeem the token in Redis
4
+ // and atomically create the tenant, user, and TenantAdmin membership.
5
+ // emailVerified is set to true immediately—the magic link IS the proof.
6
6
  //
7
7
  // Pipeline:
8
8
  // 1. Redis check: token → email lookup
9
- // 2. Single-Use-Burn (SETNX) — gleichzeitiger Klick aus zwei Tabs
10
- // gewinnt nur einer
11
- // 3. Tenant-Key generieren (generateUniqueName mit DB-isAvailable-
12
- // check gegen tenants.key)
13
- // 4. provisionSignupAccount: Tenant + User + Membership in einem
14
- // Rutsch (durch event-store-executor; events + projection +
15
- // MSPs sehen das wie einen regulären create)
16
- // 5. Token-Keys löschen (burn-key bleibt für TTL-Replay-Protection)
9
+ // 2. Single-use burn (SETNX)—only one of two simultaneous tab clicks wins
10
+ // 3. Generate the tenant key (generateUniqueName with a DB isAvailable
11
+ // check against tenants.key)
12
+ // 4. provisionSignupAccount: create the tenant, user, and membership in one
13
+ // operation (through event-store-executor; events, projection, and MSPs
14
+ // see this as a regular create)
15
+ // 5. Delete the token keys (the burn key remains for TTL replay protection)
17
16
  //
18
- // Failure-Recovery: jeder Pfad nach dem burn checked `committed`-Flag;
19
- // bei !committed wird der burn released damit ein legitimer Retry
20
- // nicht durch einen stale Marker geblockt wird (wie reset/verify).
17
+ // Failure recovery: every path after the burn checks the `committed` flag;
18
+ // when !committed, the burn is released so a legitimate retry is not blocked
19
+ // by a stale marker, as with reset/verify.
21
20
  import { fetchOne } from "@cosmicdrift/kumiko-framework/db";
22
21
  import { defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
23
22
  import { ConflictError, InternalError, reraiseAsKumikoError, writeFailure, } from "@cosmicdrift/kumiko-framework/errors";
@@ -87,21 +86,21 @@ export function createSignupConfirmHandler(opts = {}) {
87
86
  message: "signup-confirm requires ctx.redis for token consumption",
88
87
  }));
89
88
  }
90
- // Token-Lookup: nicht-existent / abgelaufen / schon konsumiert →
91
- // alle collapsen auf invalid_signup_token. Anti-enumeration.
89
+ // Token lookup: nonexistent, expired, and already-consumed tokens all
90
+ // collapse to invalid_signup_token to prevent enumeration.
92
91
  const email = await getEmailForSignupToken(ctx.redis, event.payload.token);
93
92
  if (!email)
94
93
  return invalidSignupToken();
95
- // Single-Use-Burn: zwei parallele Confirms aus verschiedenen
96
- // Tabs — einer wins, der andere kriegt invalid_signup_token.
94
+ // Single-use burn: of two parallel confirmations from different tabs,
95
+ // one succeeds and the other receives invalid_signup_token.
97
96
  const burn = await burnSignupToken(ctx.redis, event.payload.token);
98
97
  if (burn === "already-used")
99
98
  return invalidSignupToken();
100
99
  let committed = false;
101
100
  try {
102
- // Tenant-Key: 2-Wort-Slug aus framework/random, mit DB-Conflict-
103
- // Check gegen tenants.key. 22.500 Default-Combos + Suffix-
104
- // Fallback bei Kollision (siehe generateUniqueName).
101
+ // Tenant key: a two-word slug from framework/random, with a DB conflict
102
+ // check against tenants.key. 22,500 default combinations plus a
103
+ // suffix fallback in case of collision (see generateUniqueName).
105
104
  // @cast-boundary db-runner — helpers use only the query API that
106
105
  // DbConnection and DbTx share.
107
106
  const dbConn = ctx.db.unsafeRaw();
@@ -112,8 +111,8 @@ export function createSignupConfirmHandler(opts = {}) {
112
111
  },
113
112
  });
114
113
  const tenantId = generateId(); // @cast-boundary engine-payload
115
- // Display-Name aus email-prefix als sinnvolles Default; User kann
116
- // den Tenant-Namen + sein eigenes displayName später ändern.
114
+ // Use the email prefix as a meaningful default display name; the user can
115
+ // change the tenant name and their own displayName later.
117
116
  const displayName = email.split("@")[0] ?? email;
118
117
  const registrationLocale = registrationLocaleFromRequest();
119
118
  let provisioned;
@@ -128,25 +127,24 @@ export function createSignupConfirmHandler(opts = {}) {
128
127
  tenantName: tenantKey,
129
128
  ...registrationLocale,
130
129
  },
131
- // #1463: seedTenant's postSave hooks (tier-engine's auto-default-
130
+ // seedTenant's postSave hooks (tier-engine's auto-default-
132
131
  // tier, an app's auto-default-compliance) must fire on self-signup
133
132
  // exactly like they do on the regular TenantHandlers.create path.
134
133
  { registry: ctx.registry, context: ctx });
135
134
  }
136
135
  catch (err) {
137
- // Email hat bereits ein Konto — provisionSignupAccount ist create-only
138
- // (#365): sauberer User-Fehler, KEINE Session für den fremden Account.
139
- // committed bleibt false → der burn wird im finally released (ein
140
- // Retry scheitert wieder gleich, kein stale-Marker-Block).
136
+ // The email already has an account—provisionSignupAccount is create-only:
137
+ // return a clean user error and never create a session for that account.
138
+ // committed remains false, so finally releases the burn; a retry fails
139
+ // the same way without being blocked by a stale marker.
141
140
  if (err instanceof ConflictError)
142
141
  return signupEmailAlreadyRegistered();
143
142
  throw err;
144
143
  }
145
- // SessionUser für JWT-Mint. Roles aus INITIAL_SIGNUP_ROLES
146
- // damit DB-write (provisionSignupAccount) und Session-claim
147
- // dieselbe Quelle teilen — sonst hätten zwei Stellen "TenantAdmin"
148
- // hardcoded und ein Refactor würde role-mismatch zwischen DB
149
- // und JWT erzeugen.
144
+ // Build the SessionUser for JWT minting. Use roles from INITIAL_SIGNUP_ROLES
145
+ // so the database write (provisionSignupAccount) and session claim share
146
+ // one source; otherwise two hardcoded "TenantAdmin" values could drift
147
+ // during a refactor and create a role mismatch between the DB and JWT.
150
148
  const session = {
151
149
  id: provisioned.userId,
152
150
  tenantId: provisioned.tenantId,
@@ -195,9 +193,8 @@ export function createSignupConfirmHandler(opts = {}) {
195
193
  }
196
194
  finally {
197
195
  if (!committed && ctx.redis) {
198
- // Burn-release damit ein retry nach DB-Hiccup nicht blockt.
199
- // Token-Lookup-Keys bleiben — der User kann seinen Mail-Link
200
- // erneut klicken.
196
+ // Release the burn so a retry after a DB hiccup is not blocked.
197
+ // Keep the token lookup keys so the user can click the email link again.
201
198
  await unburnSignupToken(ctx.redis, event.payload.token);
202
199
  }
203
200
  }
@@ -15,7 +15,7 @@
15
15
  // Always-200 (enumeration-safe): the response looks the same for every
16
16
  // email, whether it's already registered or not. An email CAN already have
17
17
  // an account (seeding or an earlier signup) — the actual gate sits
18
- // deliberately in the confirm step (#365): signup-confirm rejects an
18
+ // deliberately in the confirm step: signup-confirm rejects an
19
19
  // already-registered email instead of reusing the existing user. Here it
20
20
  // stays always-200 + resend-idempotent so the request path leaks nothing;
21
21
  // suppressing the link on the request side would be defense-in-depth, but
@@ -31,10 +31,9 @@ import { issueSignupActivation } from "../signup-activation.js";
31
31
  import { storeSignupHandover, takeOverSignupHandoverForResend } from "../signup-token-store.js";
32
32
  const SignupRequestSchema = z.object({
33
33
  email: z.email(),
34
- // Cross-device try-first handover (kumiko-framework#3035 follow-up,
35
- // offlot-app#454) — see shared/signup-handover.ts for why the grant is
36
- // verified here and rebound to the signup token instead of the client
37
- // carrying it through the activation link.
34
+ // Cross-device try-first handover: see shared/signup-handover.ts for why the
35
+ // grant is verified here and rebound to the signup token instead of the
36
+ // client carrying it through the activation link.
38
37
  handover: z
39
38
  .object({
40
39
  entityType: z.string().min(1),
@@ -64,8 +63,8 @@ export function createSignupRequestHandler(opts) {
64
63
  // ctx.hasFeature() is fail-closed for *unregistered* names the moment
65
64
  // feature-toggles/tier-engine is wired, which silently kills
66
65
  // self-signup for every existing app that mounts auth-email-password
67
- // without also composing createAuthSelfRegistrationToggleFeature()
68
- // (#1468). Only gate when the toggle actually exists.
66
+ // without also composing createAuthSelfRegistrationToggleFeature().
67
+ // Only gate when the toggle actually exists.
69
68
  const gated = ctx.registry.getFeature(AUTH_SELF_REGISTRATION_FEATURE) !== undefined;
70
69
  if (gated && !(await ctx.hasFeature(AUTH_SELF_REGISTRATION_FEATURE))) {
71
70
  // No email address here — this fires on every no-op request, PII